diff --git a/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/FuncDSLDataFlowTransformationHelpersTest.java b/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/FuncDSLDataFlowTransformationHelpersTest.java index 5a294790..0e82f242 100644 --- a/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/FuncDSLDataFlowTransformationHelpersTest.java +++ b/experimental/lambda/src/test/java/io/serverless/workflow/impl/executors/func/FuncDSLDataFlowTransformationHelpersTest.java @@ -25,6 +25,7 @@ import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowContextData; import io.serverlessworkflow.impl.WorkflowDefinition; +import io.serverlessworkflow.impl.WorkflowInstance; import io.serverlessworkflow.impl.WorkflowModel; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; @@ -160,4 +161,82 @@ void test_input_with_inputFrom_fluent_way() { softly.assertAll(); } + + @Test + void test_output_with_outputAs() { + + SoftAssertions softly = new SoftAssertions(); + + Workflow workflow = + FuncWorkflowBuilder.workflow("enrichOutputWithTaskOutputTest") + .tasks( + function( + "add5", + (Long input) -> { + softly.assertThat(input).isEqualTo(10L); + return input + 5; + }, + Long.class) + .outputAs( + (object, workflowContext, taskContextData) -> { + Long taskOutput = output(taskContextData, Long.class); + softly.assertThat(taskOutput).isEqualTo(15L); + Long input = input(workflowContext, Long.class); + softly.assertThat(input).isEqualTo(10L); + return input + taskOutput; + }, + Long.class)) + .build(); + + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + WorkflowDefinition def = app.workflowDefinition(workflow); + + WorkflowModel model = def.instance(10L).start().join(); + Number number = model.asNumber().orElseThrow(); + + softly.assertThat(number.longValue()).isEqualTo(25L); + } + + softly.assertAll(); + } + + @Test + void test_input_with_exportAs() { + + SoftAssertions softly = new SoftAssertions(); + + Workflow workflow = + FuncWorkflowBuilder.workflow("enrichExportWithInputTest") + .tasks( + function( + "add5", + (Long input) -> { + softly.assertThat(input).isEqualTo(10L); + return input + 5; + }, + Long.class) + .exportAs( + (Long object, + WorkflowContextData workflowContext, + TaskContextData taskContextData) -> { + Long taskOutput = output(taskContextData, Long.class); + softly.assertThat(taskOutput).isEqualTo(15L); + Long input = input(workflowContext, Long.class); + softly.assertThat(input).isEqualTo(10L); + return input + taskOutput; + })) + .build(); + + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + WorkflowDefinition def = app.workflowDefinition(workflow); + + WorkflowInstance instance = def.instance(10L); + instance.start().join(); + Number number = instance.context().asNumber().orElseThrow(); + + softly.assertThat(number.longValue()).isEqualTo(25L); + } + + softly.assertAll(); + } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java index 55ba761a..0133a98d 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java @@ -44,6 +44,7 @@ public abstract class BaseTaskItemListBuilder list; private final int offset; diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/DoTaskBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/DoTaskBuilder.java index 70157672..f6c02318 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/DoTaskBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/DoTaskBuilder.java @@ -97,4 +97,10 @@ public DoTaskBuilder openapi(String name, Consumer items this.listBuilder().openapi(name, itemsConfigurer); return this; } + + @Override + public DoTaskBuilder workflow(String name, Consumer itemsConfigurer) { + this.listBuilder().workflow(name, itemsConfigurer); + return this; + } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java index 6d4c0845..cf1c6845 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java @@ -144,4 +144,17 @@ public TaskItemListBuilder openapi( return addTaskItem(new TaskItem(name, task)); } + + @Override + public TaskItemListBuilder workflow(String name, Consumer itemsConfigurer) { + name = defaultNameAndRequireConfig(name, itemsConfigurer, TYPE_WORKFLOW); + + final WorkflowTaskBuilder workflowTaskBuilder = new WorkflowTaskBuilder(); + itemsConfigurer.accept(workflowTaskBuilder); + + final Task task = new Task(); + task.setRunTask(workflowTaskBuilder.build()); + + return addTaskItem(new TaskItem(name, task)); + } } diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/WorkflowTaskBuilder.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/WorkflowTaskBuilder.java new file mode 100644 index 00000000..adef4214 --- /dev/null +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/WorkflowTaskBuilder.java @@ -0,0 +1,56 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.spec; + +import io.serverlessworkflow.api.types.RunTask; +import io.serverlessworkflow.api.types.RunTaskConfigurationUnion; +import io.serverlessworkflow.api.types.RunWorkflow; +import io.serverlessworkflow.api.types.SubflowConfiguration; +import io.serverlessworkflow.fluent.spec.spi.WorkflowTaskFluent; + +public class WorkflowTaskBuilder extends TaskBaseBuilder + implements WorkflowTaskFluent { + + private final RunTask task; + private final RunWorkflow configuration; + private final SubflowConfiguration workflow; + + WorkflowTaskBuilder() { + this.task = new RunTask(); + this.configuration = new RunWorkflow(); + this.workflow = new SubflowConfiguration(); + this.configuration.setWorkflow(this.workflow); + this.task.setRun(new RunTaskConfigurationUnion().withRunWorkflow(this.configuration)); + this.setTask(task); + } + + @Override + public WorkflowTaskBuilder self() { + return this; + } + + public RunWorkflow config() { + return this.configuration; + } + + public SubflowConfiguration workflow() { + return this.workflow; + } + + public RunTask build() { + return this.task; + } +} diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/configurers/WorkflowConfigurer.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/configurers/WorkflowConfigurer.java new file mode 100644 index 00000000..087b78d7 --- /dev/null +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/configurers/WorkflowConfigurer.java @@ -0,0 +1,22 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.spec.configurers; + +import io.serverlessworkflow.fluent.spec.WorkflowTaskBuilder; +import java.util.function.Consumer; + +@FunctionalInterface +public interface WorkflowConfigurer extends Consumer {} diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/DSL.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/DSL.java index 50bc4021..c0d68d26 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/DSL.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/DSL.java @@ -33,6 +33,7 @@ import io.serverlessworkflow.fluent.spec.configurers.TasksConfigurer; import io.serverlessworkflow.fluent.spec.configurers.TryCatchConfigurer; import io.serverlessworkflow.fluent.spec.configurers.TryConfigurer; +import io.serverlessworkflow.fluent.spec.configurers.WorkflowConfigurer; import io.serverlessworkflow.types.Errors; import java.net.URI; import java.util.List; @@ -101,6 +102,18 @@ public static CallOpenAPISpec openapi() { return new CallOpenAPISpec(); } + public static WorkflowSpec workflow(String namespace, String name, String version) { + return new WorkflowSpec().namespace(namespace).name(name).version(version); + } + + public static WorkflowSpec workflow(String namespace, String name) { + return new WorkflowSpec().namespace(namespace).name(name); + } + + public static WorkflowSpec workflow() { + return new WorkflowSpec(); + } + /** * Convenience for defining a {@code use} block with a single secret. * @@ -636,6 +649,10 @@ public static TasksConfigurer call(CallOpenAPIConfigurer configurer) { return list -> list.openapi(configurer); } + public static TasksConfigurer workflow(WorkflowConfigurer configurer) { + return list -> list.workflow(configurer); + } + /** * Create a {@link TasksConfigurer} that adds an OpenAPI call task with an explicit name. * diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/WorkflowSpec.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/WorkflowSpec.java new file mode 100644 index 00000000..9c3d0539 --- /dev/null +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/dsl/WorkflowSpec.java @@ -0,0 +1,71 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.spec.dsl; + +import io.serverlessworkflow.api.types.RunTaskConfiguration; +import io.serverlessworkflow.fluent.spec.WorkflowTaskBuilder; +import io.serverlessworkflow.fluent.spec.configurers.WorkflowConfigurer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +public final class WorkflowSpec implements WorkflowConfigurer { + + private final List> steps = new ArrayList<>(); + + public WorkflowSpec namespace(String namespace) { + steps.add(b -> b.namespace(namespace)); + return this; + } + + public WorkflowSpec name(String name) { + steps.add(b -> b.name(name)); + return this; + } + + public WorkflowSpec version(String version) { + steps.add(b -> b.version(version)); + return this; + } + + public WorkflowSpec input(Map input) { + steps.add(b -> b.input(input)); + return this; + } + + public WorkflowSpec input(String key, Object value) { + steps.add(b -> b.input(key, value)); + return this; + } + + public WorkflowSpec await(boolean await) { + steps.add(b -> b.await(await)); + return this; + } + + public WorkflowSpec returnType(RunTaskConfiguration.ProcessReturnType returnType) { + steps.add(b -> b.returnType(returnType)); + return this; + } + + @Override + public void accept(WorkflowTaskBuilder builder) { + for (var s : steps) { + s.accept(builder); + } + } +} diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/DoFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/DoFluent.java index c11c2d19..4d1048fb 100644 --- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/DoFluent.java +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/DoFluent.java @@ -26,6 +26,7 @@ import io.serverlessworkflow.fluent.spec.SwitchTaskBuilder; import io.serverlessworkflow.fluent.spec.TaskItemListBuilder; import io.serverlessworkflow.fluent.spec.TryTaskBuilder; +import io.serverlessworkflow.fluent.spec.WorkflowTaskBuilder; /** * Documents the exposed fluent `do` DSL. @@ -44,4 +45,5 @@ public interface DoFluent ForkFluent, ListenFluent, RaiseFluent, - CallOpenAPIFluent {} + CallOpenAPIFluent, + WorkflowFluent {} diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowFluent.java new file mode 100644 index 00000000..adecdf6a --- /dev/null +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowFluent.java @@ -0,0 +1,29 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.spec.spi; + +import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; +import java.util.UUID; +import java.util.function.Consumer; + +public interface WorkflowFluent, LIST> { + + LIST workflow(String name, Consumer itemsConfigurer); + + default LIST workflow(Consumer itemsConfigurer) { + return this.workflow(UUID.randomUUID().toString(), itemsConfigurer); + } +} diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowTaskFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowTaskFluent.java new file mode 100644 index 00000000..06ee0927 --- /dev/null +++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/WorkflowTaskFluent.java @@ -0,0 +1,68 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.serverlessworkflow.fluent.spec.spi; + +import io.serverlessworkflow.api.types.RunTaskConfiguration; +import io.serverlessworkflow.api.types.SubflowInput; +import io.serverlessworkflow.fluent.spec.TaskBaseBuilder; +import io.serverlessworkflow.fluent.spec.WorkflowTaskBuilder; +import java.util.Map; + +public interface WorkflowTaskFluent> { + + SELF self(); + + default SELF namespace(String namespace) { + ((WorkflowTaskBuilder) this.self()).workflow().setNamespace(namespace); + return self(); + } + + default SELF name(String name) { + ((WorkflowTaskBuilder) this.self()).workflow().setName(name); + return self(); + } + + default SELF version(String version) { + ((WorkflowTaskBuilder) this.self()).workflow().setVersion(version); + return self(); + } + + default SELF input(Map input) { + final SubflowInput subflowInput = new SubflowInput(); + input.forEach(subflowInput::setAdditionalProperty); + ((WorkflowTaskBuilder) this.self()).workflow().setInput(subflowInput); + return self(); + } + + default SELF input(String key, Object value) { + final WorkflowTaskBuilder builder = (WorkflowTaskBuilder) this.self(); + if (builder.workflow().getInput() == null) { + builder.workflow().setInput(new SubflowInput()); + } + builder.workflow().getInput().setAdditionalProperty(key, value); + return self(); + } + + default SELF await(boolean await) { + ((WorkflowTaskBuilder) this.self()).config().setAwait(await); + return self(); + } + + default SELF returnType(RunTaskConfiguration.ProcessReturnType returnType) { + ((WorkflowTaskBuilder) this.self()).config().setReturn(returnType); + return self(); + } +} diff --git a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/WorkflowBuilderTest.java b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/WorkflowBuilderTest.java index 3650bd80..c98f18d1 100644 --- a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/WorkflowBuilderTest.java +++ b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/WorkflowBuilderTest.java @@ -51,6 +51,7 @@ import io.serverlessworkflow.api.types.OneEventConsumptionStrategy; import io.serverlessworkflow.api.types.RetryLimitAttempt; import io.serverlessworkflow.api.types.RetryPolicy; +import io.serverlessworkflow.api.types.RunTaskConfiguration; import io.serverlessworkflow.api.types.SetTask; import io.serverlessworkflow.api.types.TaskItem; import io.serverlessworkflow.api.types.TryTask; @@ -635,4 +636,51 @@ void testDoTaskCallHTTPRedirectAndOutput() { call.getWith().getOutput(), "Output should be overridden"); } + + @Test + void testDoTaskRunWorkflow() { + Workflow wf = + WorkflowBuilder.workflow("parentFlow") + .tasks( + d -> + d.workflow( + "runChild", + w -> + w.namespace("org.acme") + .name("childFlow") + .version("1.0.0") + .input(Map.of("id", 42, "region", "us-east")) + .await(false) + .returnType(RunTaskConfiguration.ProcessReturnType.NONE))) + .build(); + + var runTask = wf.getDo().get(0).getTask().getRunTask(); + assertNotNull(runTask, "RunTask should be present"); + assertNotNull(runTask.getRun(), "RunTask configuration should be present"); + assertNotNull(runTask.getRun().getRunWorkflow(), "RunWorkflow should be selected"); + assertEquals("org.acme", runTask.getRun().getRunWorkflow().getWorkflow().getNamespace()); + assertEquals("childFlow", runTask.getRun().getRunWorkflow().getWorkflow().getName()); + assertEquals("1.0.0", runTask.getRun().getRunWorkflow().getWorkflow().getVersion()); + assertEquals( + 42, + runTask + .getRun() + .getRunWorkflow() + .getWorkflow() + .getInput() + .getAdditionalProperties() + .get("id")); + assertEquals( + "us-east", + runTask + .getRun() + .getRunWorkflow() + .getWorkflow() + .getInput() + .getAdditionalProperties() + .get("region")); + assertEquals( + RunTaskConfiguration.ProcessReturnType.NONE, runTask.getRun().getRunWorkflow().getReturn()); + assertEquals(false, runTask.getRun().getRunWorkflow().isAwait()); + } } diff --git a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/DSLTest.java b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/DSLTest.java index 23a67794..e8a5c3fc 100644 --- a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/DSLTest.java +++ b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/DSLTest.java @@ -26,14 +26,17 @@ import static io.serverlessworkflow.fluent.spec.dsl.DSL.produced; import static io.serverlessworkflow.fluent.spec.dsl.DSL.secrets; import static io.serverlessworkflow.fluent.spec.dsl.DSL.to; +import static io.serverlessworkflow.fluent.spec.dsl.DSL.workflow; import static org.assertj.core.api.Assertions.assertThat; import io.serverlessworkflow.api.types.HTTPArguments; import io.serverlessworkflow.api.types.ListenTaskConfiguration; +import io.serverlessworkflow.api.types.RunTaskConfiguration; import io.serverlessworkflow.api.types.Workflow; import io.serverlessworkflow.fluent.spec.WorkflowBuilder; import io.serverlessworkflow.types.Errors; import java.net.URI; +import java.util.Map; import org.junit.jupiter.api.Test; public class DSLTest { @@ -284,6 +287,51 @@ void use_spec_accumulates_secrets_and_auths() { .containsExactly("basic-auth", "bearer-auth"); } + @Test + void when_dsl_subflow_workflow_task() { + Workflow wf = + WorkflowBuilder.workflow("parent", "ns", "1") + .tasks( + workflow( + workflow("child.ns", "child-flow", "2.3.4") + .input("id", 99) + .await(false) + .returnType(RunTaskConfiguration.ProcessReturnType.NONE))) + .build(); + + var run = wf.getDo().get(0).getTask().getRunTask().getRun().getRunWorkflow(); + assertThat(run).isNotNull(); + assertThat(run.getWorkflow().getNamespace()).isEqualTo("child.ns"); + assertThat(run.getWorkflow().getName()).isEqualTo("child-flow"); + assertThat(run.getWorkflow().getVersion()).isEqualTo("2.3.4"); + assertThat(run.getWorkflow().getInput().getAdditionalProperties().get("id")).isEqualTo(99); + assertThat(run.isAwait()).isFalse(); + assertThat(run.getReturn()).isEqualTo(RunTaskConfiguration.ProcessReturnType.NONE); + } + + @Test + void when_dsl_subflow_workflow_task_with_map_input() { + Workflow wf = + WorkflowBuilder.workflow("parent", "ns", "1") + .tasks( + workflow( + workflow("child.ns", "child-flow", "2.3.4") + .input(Map.of("id", 7, "region", "eu")) + .input("extra", true) + .await(true) + .returnType(RunTaskConfiguration.ProcessReturnType.NONE))) + .build(); + + var run = wf.getDo().get(0).getTask().getRunTask().getRun().getRunWorkflow(); + assertThat(run).isNotNull(); + assertThat(run.getWorkflow().getInput().getAdditionalProperties().get("id")).isEqualTo(7); + assertThat(run.getWorkflow().getInput().getAdditionalProperties().get("region")) + .isEqualTo("eu"); + assertThat(run.getWorkflow().getInput().getAdditionalProperties().get("extra")).isEqualTo(true); + assertThat(run.isAwait()).isTrue(); + assertThat(run.getReturn()).isEqualTo(RunTaskConfiguration.ProcessReturnType.NONE); + } + @Test public void when_call_openapi_with_explicit_name() { Workflow wf = diff --git a/impl/test/pom.xml b/impl/test/pom.xml index f040989b..ed7fb9c7 100644 --- a/impl/test/pom.xml +++ b/impl/test/pom.xml @@ -16,6 +16,12 @@ io.serverlessworkflow serverlessworkflow-api + + io.serverlessworkflow + serverlessworkflow-fluent-spec + ${project.version} + test + io.serverlessworkflow serverlessworkflow-persistence-mvstore @@ -173,4 +179,4 @@ - \ No newline at end of file + diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/SubWorkflowTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/SubWorkflowTest.java index 1a01fdcf..16e37458 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/SubWorkflowTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/SubWorkflowTest.java @@ -19,6 +19,8 @@ import static org.junit.Assert.assertEquals; import io.serverlessworkflow.api.types.Workflow; +import io.serverlessworkflow.fluent.spec.WorkflowBuilder; +import io.serverlessworkflow.fluent.spec.dsl.DSL; import io.serverlessworkflow.impl.WorkflowApplication; import java.io.IOException; import java.util.Map; @@ -143,4 +145,30 @@ public void outputExportContextAndSetTest() throws IOException { throw new RuntimeException("Workflow execution failed", e); } } + + @Test + public void runSubWorkflowFromDslTest() { + Workflow child = + WorkflowBuilder.workflow("childFlow", "org.acme", "1.0.0") + .tasks(d -> d.set("update", s -> s.put("counter", 1).put("greeting", "helloWorld"))) + .build(); + + Workflow parent = + WorkflowBuilder.workflow("parentFlow", "org.acme", "1.0.0") + .tasks( + DSL.workflow( + DSL.workflow("org.acme", "childFlow", "1.0.0") + .input(Map.of("id", 42, "region", "us-east")))) + .build(); + + try (WorkflowApplication app = WorkflowApplication.builder().build()) { + app.workflowDefinition(child); + Map result = + app.workflowDefinition(parent).instance(Map.of()).start().get().asMap().orElseThrow(); + assertEquals("1", result.get("counter").toString()); + assertEquals("helloWorld", result.get("greeting").toString()); + } catch (Exception e) { + throw new RuntimeException("Workflow execution failed", e); + } + } }