feat: add sub worflows run on FuncDSL #1295#1299
feat: add sub worflows run on FuncDSL #1295#1299matheusandre1 wants to merge 3 commits intoserverlessworkflow:mainfrom
Conversation
Signed-off-by: Matheus Andre <matheusandr2@gmail.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for running nested/sub workflows (“run workflow” tasks) from the Func fluent DSL, closing #1295.
Changes:
- Extend Func FuncDo fluent interfaces/builders to include
WorkflowFluentso workflow tasks can be added from Func DSL chains - Add
FuncDSL.workflow(WorkflowConfigurer)helper to append workflow subflow tasks - Add a JUnit test validating the generated
RunWorkflowstructure andawait(false)propagation
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java | Adds a test covering building a workflow task via Func DSL and verifying the produced RunWorkflow fields. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/FuncDoFluent.java | Extends Func DSL fluent surface to include workflow tasks (WorkflowFluent). |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/FuncDSL.java | Introduces FuncDSL.workflow(WorkflowConfigurer) task configurer entrypoint. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java | Implements workflow task addition for Func task lists by delegating to spec TaskItemListBuilder. |
| experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncDoTaskBuilder.java | Wires workflow(...) into the Func do task builder. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| FuncWorkflowBuilder.workflow("step-workflow") | ||
| .tasks( | ||
| workflow( | ||
| workflow("child.ns", "child-flow", "2.3.4") |
There was a problem hiding this comment.
The nested workflow(...) calls are ambiguous/confusing and may not compile as written: the outer call is clearly the Func DSL task configurer, but the inner workflow("child.ns", "child-flow", "2.3.4") requires a different factory method (likely from the spec DSL). To make this compile reliably, qualify at least one of the calls (e.g., FuncDSL.workflow(...) for the outer, or DSL.workflow(...) for the inner), or add the correct static import for the inner factory and avoid name clashes.
| workflow("child.ns", "child-flow", "2.3.4") | |
| io.serverlessworkflow.fluent.spec.dsl.DSL.workflow( | |
| "child.ns", "child-flow", "2.3.4") |
| String name, Consumer<WorkflowTaskBuilder> itemsConfigurer) { | ||
| final TaskItemListBuilder delegate = new TaskItemListBuilder(this.mutableList().size()); | ||
| delegate.workflow(name, itemsConfigurer); | ||
| return addTaskItem(delegate.build().get(0)); |
There was a problem hiding this comment.
delegate.build().get(0) is a fragile assumption and obscures intent (it will throw IndexOutOfBoundsException if the delegate ever produces no items). Prefer constructing/returning the single TaskItem directly (if the underlying API allows), or at least store the built list and enforce the expected size with a clear exception message before indexing. This also avoids building a list only to discard all but the first element.
| return addTaskItem(delegate.build().get(0)); | |
| final List<TaskItem> taskItems = delegate.build(); | |
| if (taskItems.size() != 1) { | |
| throw new IllegalStateException( | |
| "Expected workflow delegate to build exactly 1 TaskItem, but got " | |
| + taskItems.size()); | |
| } | |
| return addTaskItem(taskItems.get(0)); |
| public static FuncTaskConfigurer workflow(WorkflowConfigurer configurer) { | ||
| Objects.requireNonNull(configurer, "configurer"); | ||
| return list -> list.workflow(configurer); | ||
| } | ||
|
|
There was a problem hiding this comment.
Naming this entrypoint workflow(...) is likely to collide with/obscure the spec-side factory that creates a WorkflowConfigurer (as evidenced by call sites ending up with workflow(workflow(...))). Consider renaming the Func task-adder to something unambiguous like runWorkflow(...) / subworkflow(...) / workflowTask(...), or otherwise providing a clearly differentiated API to avoid import conflicts and improve readability for consumers.
| public static FuncTaskConfigurer workflow(WorkflowConfigurer configurer) { | |
| Objects.requireNonNull(configurer, "configurer"); | |
| return list -> list.workflow(configurer); | |
| } | |
| public static FuncTaskConfigurer workflowTask(WorkflowConfigurer configurer) { | |
| Objects.requireNonNull(configurer, "configurer"); | |
| return list -> list.workflow(configurer); | |
| } | |
| /** | |
| * Create a {@link FuncTaskConfigurer} that adds a workflow subflow task. | |
| * | |
| * @param configurer configurer for the nested workflow task | |
| * @return a {@link FuncTaskConfigurer} that adds a workflow task to the tasks list | |
| * @deprecated use {@link #workflowTask(WorkflowConfigurer)} to avoid ambiguity with | |
| * spec-side workflow factory methods | |
| */ | |
| @Deprecated | |
| public static FuncTaskConfigurer workflow(WorkflowConfigurer configurer) { | |
| return workflowTask(configurer); | |
| } |
Signed-off-by: Matheus Andre <matheusandr2@gmail.com>
Signed-off-by: Matheus Andre <matheusandr2@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public FuncTaskItemListBuilder workflow( | ||
| String name, Consumer<WorkflowTaskBuilder> itemsConfigurer) { | ||
| final TaskItemListBuilder delegate = new TaskItemListBuilder(this.mutableList().size()); | ||
| delegate.workflow(name, itemsConfigurer); | ||
| final List<TaskItem> taskItems = delegate.build(); | ||
| if (taskItems.size() != 1) { | ||
| throw new IllegalStateException( | ||
| "Expected workflow delegate to build exactly 1 TaskItem, but got " + taskItems.size()); | ||
| } | ||
| return addTaskItem(taskItems.get(0)); | ||
| } |
There was a problem hiding this comment.
This implementation builds a separate spec TaskItemListBuilder, then builds a list only to extract a single TaskItem. That indirection adds unnecessary complexity and allocation, and also makes failures harder to diagnose. Prefer constructing the workflow task item directly (e.g., build a WorkflowTaskBuilder, apply itemsConfigurer, then add a single TaskItem), and if you keep the current approach, include name in the exception message to improve debuggability.
There was a problem hiding this comment.
what are we trying to do here?
| * @deprecated use {@link #workflowTask(WorkflowConfigurer)} to avoid ambiguity with spec-side | ||
| * workflow factory methods | ||
| */ | ||
| @Deprecated |
There was a problem hiding this comment.
The newly deprecated API uses a bare @Deprecated annotation. Consider using @Deprecated(since = \"<version>\", forRemoval = false/true) to make the deprecation timeline explicit for consumers (and tooling), especially since this method name is intentionally ambiguous with spec-side workflow factory methods.
| @Deprecated | |
| @Deprecated(since = "<version>", forRemoval = false) |
experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java
Show resolved
Hide resolved
| * @deprecated use {@link #workflowTask(WorkflowConfigurer)} to avoid ambiguity with spec-side | ||
| * workflow factory methods | ||
| */ | ||
| @Deprecated |
There was a problem hiding this comment.
Whats the point of adding a new function that is also deprecated???
fjtirado
left a comment
There was a problem hiding this comment.
I think this needs some reworking
Many thanks for submitting your Pull Request ❤️!
What this PR does / why we need it: Closes: #1295
Special notes for reviewers:
Additional information (if needed):