Skip to content

Add then to the Java DSL#1190

Open
mcruzdev wants to merge 2 commits intoserverlessworkflow:mainfrom
mcruzdev:issue-1188
Open

Add then to the Java DSL#1190
mcruzdev wants to merge 2 commits intoserverlessworkflow:mainfrom
mcruzdev:issue-1188

Conversation

@mcruzdev
Copy link
Collaborator

@mcruzdev mcruzdev commented Feb 27, 2026

Changes

This pull request allows us to jump to a task using then(String taskName):

    Workflow wf =
        FuncWorkflowBuilder.workflow("intelligent-newsletter")
            .tasks(
                consume("sendNewsletter", (String s) -> {}, String.class).then("otherTask"),
                function("nextTask", String::strip, String.class),
                function("otherTask", String::strip, String.class))
            .build();

Closes #1188

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Copy link
Member

@ricardozanini ricardozanini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Have you also checked how the mermaid diagram handles it? It's tangential to this work, but I can't remember whether I implemented it there.

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds .then(...) chaining support to the experimental Java functional fluent DSL steps, allowing a task to direct workflow execution to a named next task (or a flow directive like END) without requiring Consumer.andThen() composition. This addresses issue #1188 by improving DSL ergonomics and adds tests to validate both model generation and runtime behavior.

Changes:

  • Add then(String taskName) and then(FlowDirectiveEnum directive) to the fluent Step DSL so function(...) / consume(...) steps can set the task’s then directive.
  • Extend DSL unit tests to assert the generated workflow model contains the expected then FlowDirective.
  • Add an integration-style test in impl/test to validate runtime execution jumps/stops based on then(...).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/dsl/Step.java Adds then(...) chaining APIs that defer to TaskBaseBuilder.then(...) via queued post-configurers.
experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java Adds unit tests verifying then(...) is serialized into the underlying task model for both function(...) and consume(...).
impl/test/src/test/java/io/serverlessworkflow/impl/test/WorkflowThenTest.java Adds runtime tests asserting .then("task") skips the next task and .then(END) stops execution.
impl/test/pom.xml Adds test-scope dependencies needed to build/execute workflows created with the experimental fluent func DSL and Java lambda execution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


WorkflowApplication app = WorkflowApplication.builder().build();
WorkflowDefinition def = app.workflowDefinition(wf);
def.instance(Map.of()).start().join();
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorkflowDefinition.instance(...) is started with Map.of(), but the first task is a typed Java String function/consumer (String.class). The Java lambda execution path converts the workflow input to the requested arg type via WorkflowModel.as(String.class), which will be empty for a JSON object, causing an exception before the then(...) behavior can be validated. Pass a String (e.g., a sample newsletter payload) as the workflow input, or set an inputFrom mapping that extracts a String from the provided map.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback


WorkflowApplication app = WorkflowApplication.builder().build();
WorkflowDefinition def = app.workflowDefinition(wf);
def.instance(Map.of()).start().join();
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as earlier: the workflow instance is started with Map.of() but the first task is a typed String Java function (String.class), so input conversion will fail for a JSON object. Use a String input value (or add an inputFrom mapping) so this test reliably exercises then("otherTask").

Copilot uses AI. Check for mistakes.

WorkflowApplication app = WorkflowApplication.builder().build();
WorkflowDefinition def = app.workflowDefinition(wf);
def.instance(Map.of()).start().join();
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow instance is started with Map.of(), but the first task is a typed String Java function (String.class), so the Java lambda executor will fail converting an object input to String. Provide a String input (or set inputFrom) so this test validates then(FlowDirectiveEnum.END) rather than failing on input conversion.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add then to the Java DSL

3 participants