1616package io .serverlessworkflow .fluent .func .dsl ;
1717
1818import io .cloudevents .CloudEventData ;
19+ import io .serverlessworkflow .api .reflection .func .InstanceIdFunction ;
20+ import io .serverlessworkflow .api .reflection .func .ReflectionUtils ;
21+ import io .serverlessworkflow .api .reflection .func .SerializableConsumer ;
22+ import io .serverlessworkflow .api .reflection .func .SerializableFunction ;
23+ import io .serverlessworkflow .api .reflection .func .SerializablePredicate ;
24+ import io .serverlessworkflow .api .reflection .func .UniqueIdBiFunction ;
1925import io .serverlessworkflow .api .types .FlowDirectiveEnum ;
2026import io .serverlessworkflow .api .types .OAuth2AuthenticationData ;
2127import io .serverlessworkflow .api .types .func .ContextFunction ;
@@ -103,7 +109,11 @@ public static <T, V> Consumer<FuncCallTaskBuilder> fn(
103109 * @return a consumer that configures a {@code FuncCallTaskBuilder}
104110 */
105111 public static <T , V > Consumer <FuncCallTaskBuilder > fn (SerializableFunction <T , V > function ) {
106- return f -> f .function (function , ReflectionUtils .inferInputType (function ));
112+ return f ->
113+ f .function (
114+ function ,
115+ ReflectionUtils .inferInputType (function ),
116+ ReflectionUtils .inferResultType (function ));
107117 }
108118
109119 /**
@@ -348,11 +358,16 @@ public static <T, R> FuncCallStep<T, R> withContext(ContextFunction<T, R> fn) {
348358 */
349359 public static <T , R > FuncCallStep <T , R > withContext (
350360 String name , ContextFunction <T , R > fn , Class <T > in ) {
351- return new FuncCallStep <>(name , fn , in );
361+ return withContext (name , fn , in , ReflectionUtils .inferResultType (fn ));
362+ }
363+
364+ public static <T , R > FuncCallStep <T , R > withContext (
365+ String name , ContextFunction <T , R > fn , Class <T > in , Class <R > out ) {
366+ return new FuncCallStep <>(name , fn , in , out );
352367 }
353368
354369 public static <T , R > FuncCallStep <T , R > withContext (String name , ContextFunction <T , R > fn ) {
355- return new FuncCallStep <> (name , fn , ReflectionUtils .inferInputType (fn ));
370+ return withContext (name , fn , ReflectionUtils .inferInputType (fn ));
356371 }
357372
358373 /**
@@ -384,7 +399,12 @@ public static <T, R> FuncCallStep<T, R> withFilter(FilterFunction<T, R> fn, Clas
384399 */
385400 public static <T , R > FuncCallStep <T , R > withFilter (
386401 String name , FilterFunction <T , R > fn , Class <T > in ) {
387- return new FuncCallStep <>(name , fn , in );
402+ return withFilter (name , fn , in , ReflectionUtils .inferResultType (fn ));
403+ }
404+
405+ public static <T , R > FuncCallStep <T , R > withFilter (
406+ String name , FilterFunction <T , R > fn , Class <T > in , Class <R > out ) {
407+ return new FuncCallStep <>(name , fn , in , out );
388408 }
389409
390410 public static <T , R > FuncCallStep <T , R > withFilter (FilterFunction <T , R > fn ) {
@@ -407,8 +427,13 @@ public static <T, R> FuncCallStep<T, R> withFilter(String name, FilterFunction<T
407427 */
408428 public static <T , R > FuncCallStep <T , R > withInstanceId (
409429 String name , InstanceIdFunction <T , R > fn , Class <T > in ) {
430+ return withInstanceId (name , fn , in , ReflectionUtils .inferResultType (fn ));
431+ }
432+
433+ public static <T , R > FuncCallStep <T , R > withInstanceId (
434+ String name , InstanceIdFunction <T , R > fn , Class <T > in , Class <R > out ) {
410435 ContextFunction <T , R > jcf = (payload , wctx ) -> fn .apply (wctx .instanceData ().id (), payload );
411- return new FuncCallStep <>(name , jcf , in );
436+ return new FuncCallStep <>(name , jcf , in , out );
412437 }
413438
414439 /**
@@ -463,9 +488,14 @@ static String defaultUniqueId(WorkflowContextData wctx, TaskContextData tctx) {
463488 */
464489 public static <T , R > FuncCallStep <T , R > withUniqueId (
465490 String name , UniqueIdBiFunction <T , R > fn , Class <T > in ) {
491+ return withUniqueId (name , fn , in , ReflectionUtils .inferResultType (fn ));
492+ }
493+
494+ public static <T , R > FuncCallStep <T , R > withUniqueId (
495+ String name , UniqueIdBiFunction <T , R > fn , Class <T > in , Class <R > out ) {
466496 FilterFunction <T , R > jff =
467497 (payload , wctx , tctx ) -> fn .apply (defaultUniqueId (wctx , tctx ), payload );
468- return new FuncCallStep <>(name , jff , in );
498+ return new FuncCallStep <>(name , jff , in , out );
469499 }
470500
471501 public static <T , R > FuncCallStep <T , R > withUniqueId (String name , UniqueIdBiFunction <T , R > fn ) {
@@ -577,7 +607,23 @@ public static <T, R> FuncCallStep<T, R> agent(String name, UniqueIdBiFunction<T,
577607 * @return a call step which supports chaining (e.g., {@code .exportAs(...).when(...)})
578608 */
579609 public static <T , R > FuncCallStep <T , R > function (Function <T , R > fn , Class <T > inputClass ) {
580- return new FuncCallStep <>(fn , inputClass );
610+ return function (fn , inputClass , null );
611+ }
612+
613+ /**
614+ * Create a {@link FuncCallStep} that calls a simple Java {@link Function} with explicit input
615+ * type.
616+ *
617+ * @param fn the function to execute at runtime
618+ * @param inputClass expected input class for model conversion
619+ * @param outputClass expected outputClass class for model conversion
620+ * @param <T> input type
621+ * @param <R> result type
622+ * @return a call step which supports chaining (e.g., {@code .exportAs(...).when(...)})
623+ */
624+ public static <T , R > FuncCallStep <T , R > function (
625+ Function <T , R > fn , Class <T > inputClass , Class <R > outputClass ) {
626+ return new FuncCallStep <>(fn , inputClass , outputClass );
581627 }
582628
583629 /**
@@ -590,8 +636,8 @@ public static <T, R> FuncCallStep<T, R> function(Function<T, R> fn, Class<T> inp
590636 * @return a call step
591637 */
592638 public static <T , R > FuncCallStep <T , R > function (SerializableFunction <T , R > fn ) {
593- Class < T > inputClass = ReflectionUtils . inferInputType ( fn );
594- return new FuncCallStep <> (fn , inputClass );
639+ return new FuncCallStep <>(
640+ fn , ReflectionUtils . inferInputType (fn ), ReflectionUtils . inferResultType ( fn ) );
595641 }
596642
597643 /**
@@ -604,8 +650,8 @@ public static <T, R> FuncCallStep<T, R> function(SerializableFunction<T, R> fn)
604650 * @return a named call step
605651 */
606652 public static <T , R > FuncCallStep <T , R > function (String name , SerializableFunction <T , R > fn ) {
607- Class < T > inputClass = ReflectionUtils . inferInputType ( fn );
608- return new FuncCallStep <>( name , fn , inputClass );
653+ return new FuncCallStep <>(
654+ name , fn , ReflectionUtils . inferInputType ( fn ), ReflectionUtils . inferResultType ( fn ) );
609655 }
610656
611657 /**
@@ -620,7 +666,23 @@ public static <T, R> FuncCallStep<T, R> function(String name, SerializableFuncti
620666 */
621667 public static <T , R > FuncCallStep <T , R > function (
622668 String name , Function <T , R > fn , Class <T > inputClass ) {
623- return new FuncCallStep <>(name , fn , inputClass );
669+ return new FuncCallStep <>(name , fn , inputClass , null );
670+ }
671+
672+ /**
673+ * Named variant of {@link #function(Function, Class)} with explicit input type.
674+ *
675+ * @param name task name
676+ * @param fn the function to execute
677+ * @param inputClass expected input class
678+ * @param outputClass expected output class
679+ * @param <T> input type
680+ * @param <R> output type
681+ * @return a named call step
682+ */
683+ public static <T , R > FuncCallStep <T , R > function (
684+ String name , Function <T , R > fn , Class <T > inputClass , Class <R > outputClass ) {
685+ return new FuncCallStep <>(name , fn , inputClass , outputClass );
624686 }
625687
626688 // ------------------ tasks ---------------- //
0 commit comments