no-issue: Adding overloads to remove Class<T> param#1219
no-issue: Adding overloads to remove Class<T> param#1219ricardozanini wants to merge 1 commit intoserverlessworkflow:mainfrom
Conversation
Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the experimental fluent function DSL to infer lambda input types at runtime (via SerializedLambda) so callers can omit explicit Class<T> parameters, and expands the set of supported functional shapes (functions, predicates, consumers, and context-aware functions).
Changes:
- Introduce
Serializable*functional interfaces and update DSL entrypoints to accept them for runtime type inference. - Refactor
ReflectionUtilsto infer input types from any supported serializable lambda shape. - Add/adjust tests to exercise the new inferred-type overloads and DSL behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| experimental/types/src/main/java/io/serverlessworkflow/api/types/func/JavaFilterFunction.java | Makes JavaFilterFunction serializable to support runtime lambda introspection. |
| experimental/types/src/main/java/io/serverlessworkflow/api/types/func/JavaContextFunction.java | Makes JavaContextFunction serializable to support runtime lambda introspection. |
| experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/WorkflowThenTest.java | Updates DSL usage to the new overload that infers input type (removes explicit Class). |
| experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/FuncDSLReflectionsTest.java | Adds tests covering inferred-type overloads and reflective lambda handling. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/UniqueIdBiFunction.java | Makes the bi-function serializable for inference/introspection. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/SerializablePredicate.java | New serializable predicate type for switch/case inference. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/SerializableFunction.java | New serializable function type for task inference. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/SerializableConsumer.java | New serializable consumer type for consume(...) inference. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/ReflectionUtils.java | Refactors inference to use SerializedLambda and exposes overloads per supported functional type. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/InstanceIdBiFunction.java | Makes the injected-instance-id function serializable for inference/introspection. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/FuncEventFilterSpec.java | Updates JSON event data mapping to accept SerializableFunction and infer input class. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/FuncDSL.java | Adds overloads that remove Class<T> requirements using reflective inference. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/CommonFuncOps.java | Moves and adjusts internal ops to use serializable functional types for inference. |
| experimental/fluent/func/pom.xml | Formatting-only change. |
Comments suppressed due to low confidence (1)
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/FuncDSL.java:287
- The Javadoc describes the expected
withContextsignature as(ctx, payload) -> result, butJavaContextFunctionis defined asapply(T payload, WorkflowContextData ctx). Please update the documentation to match the actual parameter order to avoid confusing DSL users.
* Build a call step for functions that need {@link WorkflowContextData} as the first parameter.
* The DSL wraps it as a {@link JavaContextFunction} and injects the runtime context.
*
* <p>Signature expected: {@code (ctx, payload) -> result}
*
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @SuppressWarnings("unchecked") | ||
| static <T> Class<T> inferInputType(InstanceIdBiFunction<T, ?> fn) { | ||
| return throwIllegalStateIfNull((Class<T>) inferInputTypeFromAny(fn)); | ||
| } |
There was a problem hiding this comment.
inferInputType(InstanceIdBiFunction) currently delegates to inferInputTypeFromAny, which (for a typical (String instanceId, T payload) -> R lambda) will infer the first parameter type (String) instead of the payload type T. This will cause the DSL to treat the payload as String.class and can break model conversion at runtime for non-String payloads. Consider inferring the 2nd parameter type for this functional interface (or adding an overload that selects the correct parameter index based on the target SAM signature).
| @SuppressWarnings("unchecked") | ||
| static <T> Class<T> inferInputType(UniqueIdBiFunction<T, ?> fn) { | ||
| return throwIllegalStateIfNull((Class<T>) inferInputTypeFromAny(fn)); | ||
| } |
There was a problem hiding this comment.
inferInputType(UniqueIdBiFunction) has the same issue as InstanceIdBiFunction: for lambdas with signature (String uniqueId, T payload) -> R, inferInputTypeFromAny will infer String (first arg) rather than the payload type T (second arg). This will mis-type the payload conversion for any non-String payloads. Suggest inferring parameter index 1 for this interface (and adding a regression test using a non-String payload type).
| public static <T, R> FuncCallStep<T, R> function(SerializableFunction<T, R> fn) { | ||
| Class<T> inputClass = ReflectionUtils.inferInputType(fn); | ||
| return new FuncCallStep<>(fn, inputClass); | ||
| } |
There was a problem hiding this comment.
Changing the inferred-type overload from function(Function<T,R>) to function(SerializableFunction<T,R>) is a source-breaking API change for callers that hold functions in java.util.function.Function variables (or return them from APIs). If backward compatibility is desired, consider keeping an overload that accepts Function and either (a) falls back to requiring an explicit Class<T> when inference isn't possible, or (b) throws a targeted error message explaining the need for a SerializableFunction/method reference.
|
|
||
| assertTrue(output.isPresent()); | ||
| // It should append the task JSON pointer (likely "/tasks/0" or similar depending on spec) | ||
| assertTrue(output.get().contains("Filter Data at position do/")); |
There was a problem hiding this comment.
This assertion looks incorrect/typoed: jsonPointer() is expected to look like "/tasks/0" (or at least start with /), but the test currently checks for "Filter Data at position do/", which will likely fail even when the feature works. Consider asserting on a stable prefix like "Filter Data at position /" or matching a /tasks/ pattern.
| assertTrue(output.get().contains("Filter Data at position do/")); | |
| assertTrue(output.get().startsWith("Filter Data at position /")); |
Many thanks for submitting your Pull Request ❤️!
What this PR does / why we need it:
Class<T>requirementReflectingUtilsclass to accept any function, predicate, or consumer usageSerializableto our functions so we can infer types at runtimeSpecial notes for reviewers:
I haven't reviewed the changes throughout yet, I should do it tomorrow - improvements in an upcoming commit.
Additional information (if needed):