Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,18 @@ public static TasksConfigurer call(CallHttpConfigurer configurer) {
return list -> list.http(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds an HTTP call task with an explicit name using a
* low-level HTTP configurer.
*
* @param name the task name
* @param configurer low-level HTTP configurer
* @return a {@link TasksConfigurer} that adds a CallHTTP task
*/
public static TasksConfigurer call(String name, CallHttpConfigurer configurer) {
return list -> list.http(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds an OpenAPI call task.
*
Expand All @@ -624,6 +636,17 @@ public static TasksConfigurer call(CallOpenAPIConfigurer configurer) {
return list -> list.openapi(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds an OpenAPI call task with an explicit name.
*
* @param name the task name
* @param configurer OpenAPI configurer
* @return a {@link TasksConfigurer} that adds a CallOpenAPI task
*/
public static TasksConfigurer call(String name, CallOpenAPIConfigurer configurer) {
return list -> list.openapi(name, configurer);
}
Comment on lines +639 to +648
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The new overload call(String name, CallOpenAPIConfigurer) isn’t exercised by the test suite (current tests cover only the HTTP variant). Add a unit test that builds a workflow using call("name", openapi()...) and asserts the TaskItem name and that CallTask.callOpenAPI is present/configured, to prevent regressions in this overload.

Copilot uses AI. Check for mistakes.

/**
* Create a {@link TasksConfigurer} that adds a {@code set} task using a low-level configurer.
*
Expand All @@ -634,6 +657,18 @@ public static TasksConfigurer set(SetConfigurer configurer) {
return list -> list.set(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code set} task with an explicit name using a
* low-level configurer.
*
* @param name the task name
* @param configurer configurer for the set task
* @return a {@link TasksConfigurer} that adds a SetTask
*/
public static TasksConfigurer set(String name, SetConfigurer configurer) {
return list -> list.set(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code set} task using a raw expression.
*
Expand All @@ -644,6 +679,18 @@ public static TasksConfigurer set(String expr) {
return list -> list.set(expr);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code set} task with an explicit name using a raw
* expression.
*
* @param name the task name
* @param expr expression to apply in the set task
* @return a {@link TasksConfigurer} that adds a SetTask
*/
public static TasksConfigurer set(String name, String expr) {
return list -> list.set(name, expr);
}

/**
* Adds an {@code emit} task to the workflow's task sequence using a custom configurer. *
*
Expand All @@ -664,13 +711,6 @@ public static TasksConfigurer emit(Consumer<EmitTaskBuilder> configurer) {
return list -> list.emit(configurer);
}

/**
* @see #emit(Consumer)
*/
public static TasksConfigurer emit(String name, Consumer<EmitTaskBuilder> configurer) {
return list -> list.emit(name, configurer);
}

/**
* A convenient shortcut to add an {@code emit} task that only requires a CloudEvent type. *
*
Expand Down Expand Up @@ -704,6 +744,17 @@ public static EmitSpec produced(String cloudEventType) {
return new EmitSpec().type(cloudEventType);
}

/**
* Create a {@link TasksConfigurer} that adds an {@code emit} task with an explicit name.
*
* @param name the task name
* @param configurer consumer configuring {@link EmitTaskBuilder}
* @return a {@link TasksConfigurer} that adds an EmitTask
*/
public static TasksConfigurer emit(String name, Consumer<EmitTaskBuilder> configurer) {
return list -> list.emit(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code listen} task.
*
Expand All @@ -714,6 +765,17 @@ public static TasksConfigurer listen(ListenConfigurer configurer) {
return list -> list.listen(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code listen} task with an explicit name.
*
* @param name the task name
* @param configurer listen configurer
* @return a {@link TasksConfigurer} that adds a ListenTask
*/
public static TasksConfigurer listen(String name, ListenConfigurer configurer) {
return list -> list.listen(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code forEach} task.
*
Expand All @@ -724,6 +786,17 @@ public static TasksConfigurer forEach(ForEachConfigurer configurer) {
return list -> list.forEach(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code forEach} task with an explicit name.
*
* @param name the task name
* @param configurer for-each configurer
* @return a {@link TasksConfigurer} that adds a ForEachTask
*/
public static TasksConfigurer forEach(String name, ForEachConfigurer configurer) {
return list -> list.forEach(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code fork} task.
*
Expand All @@ -734,6 +807,17 @@ public static TasksConfigurer fork(Consumer<ForkTaskBuilder> configurer) {
return list -> list.fork(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code fork} task with an explicit name.
*
* @param name the task name
* @param configurer consumer configuring {@link ForkTaskBuilder}
* @return a {@link TasksConfigurer} that adds a ForkTask
*/
public static TasksConfigurer fork(String name, Consumer<ForkTaskBuilder> configurer) {
return list -> list.fork(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code switch} task.
*
Expand All @@ -744,6 +828,17 @@ public static TasksConfigurer switchCase(SwitchConfigurer configurer) {
return list -> list.switchCase(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code switch} task with an explicit name.
*
* @param name the task name
* @param configurer switch configurer
* @return a {@link TasksConfigurer} that adds a SwitchTask
*/
public static TasksConfigurer switchCase(String name, SwitchConfigurer configurer) {
return list -> list.switchCase(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code raise} task.
*
Expand All @@ -754,6 +849,17 @@ public static TasksConfigurer raise(RaiseConfigurer configurer) {
return list -> list.raise(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code raise} task with an explicit name.
*
* @param name the task name
* @param configurer raise configurer
* @return a {@link TasksConfigurer} that adds a RaiseTask
*/
public static TasksConfigurer raise(String name, RaiseConfigurer configurer) {
return list -> list.raise(name, configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code try/catch} task.
*
Expand All @@ -764,6 +870,17 @@ public static TasksConfigurer tryCatch(TryConfigurer configurer) {
return list -> list.tryCatch(configurer);
}

/**
* Create a {@link TasksConfigurer} that adds a {@code try/catch} task with an explicit name.
*
* @param name the task name
* @param configurer try/catch configurer
* @return a {@link TasksConfigurer} that adds a TryTask
*/
public static TasksConfigurer tryCatch(String name, TryConfigurer configurer) {
return list -> list.tryCatch(name, configurer);
}

// ----- Tasks that requires tasks list --//

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,19 @@
package io.serverlessworkflow.fluent.spec;

import static io.serverlessworkflow.fluent.spec.dsl.DSL.basic;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.call;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.cases;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.doTasks;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.emit;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.forEach;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.fork;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.http;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.listen;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.produced;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.raise;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.set;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.switchCase;
import static io.serverlessworkflow.fluent.spec.dsl.DSL.tryCatch;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand Down Expand Up @@ -125,6 +134,117 @@ void testDoTaskSetAndForEach() {
assertNotNull(forItem.getTask().getForTask(), "ForTask should be present");
}

@Test
void testTaskNamedSet() {
// Test that we can now name a task "set" using the DSL
Workflow wf =
WorkflowBuilder.workflow("flowWithSetTask")
.tasks(
d ->
d.set("set", "$.value = 'test'").set("set", s -> s.expr("$.another = 'value'")))
Comment on lines +143 to +144
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

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

testTaskNamedSet() is described as verifying naming via the DSL, but it only uses the DoTaskBuilder#set(String, ...) instance methods (which already support explicit names). To specifically cover this PR’s new DSL overloads, consider either rewriting this test to use the static DSL.set("set", ...) helpers (like the next test does) or removing/renaming it to avoid redundant coverage.

Suggested change
d ->
d.set("set", "$.value = 'test'").set("set", s -> s.expr("$.another = 'value'")))
doTasks(
set("set", "$.value = 'test'"),
set("set", s -> s.expr("$.another = 'value'"))))

Copilot uses AI. Check for mistakes.
.build();

List<TaskItem> items = wf.getDo();
assertNotNull(items, "Do list must not be null");
assertEquals(2, items.size(), "There should be two tasks");

// First task named "set" with string expression
TaskItem firstSetItem = items.get(0);
assertEquals("set", firstSetItem.getName(), "First task should be named 'set'");
SetTask firstSetTask = firstSetItem.getTask().getSetTask();
assertNotNull(firstSetTask, "SetTask should be present");
assertEquals("$.value = 'test'", firstSetTask.getSet().getString());

// Second task also named "set" with configurer
TaskItem secondSetItem = items.get(1);
assertEquals("set", secondSetItem.getName(), "Second task should be named 'set'");
SetTask secondSetTask = secondSetItem.getTask().getSetTask();
assertNotNull(secondSetTask, "SetTask should be present");
assertEquals("$.another = 'value'", secondSetTask.getSet().getString());
}

@Test
void testTaskNamedSetUsingDSLStaticImport() {
Workflow wf =
WorkflowBuilder.workflow("flowWithDSLSet")
.tasks(
doTasks(
set("set", "$.initialized = true"), set("set", s -> s.expr("$.ready = true"))))
.build();

List<TaskItem> items = wf.getDo();
assertNotNull(items, "Do list must not be null");
assertEquals(2, items.size(), "There should be two tasks");

TaskItem firstItem = items.get(0);
assertEquals("set", firstItem.getName(), "First task should be named 'set'");
SetTask firstTask = firstItem.getTask().getSetTask();
assertNotNull(firstTask, "SetTask should be present");
assertEquals("$.initialized = true", firstTask.getSet().getString());

TaskItem secondItem = items.get(1);
assertEquals("set", secondItem.getName(), "Second task should be named 'set'");
SetTask secondTask = secondItem.getTask().getSetTask();
assertNotNull(secondTask, "SetTask should be present");
assertEquals("$.ready = true", secondTask.getSet().getString());
}

@Test
void testAllTasksWithExplicitNames() {
Workflow wf =
WorkflowBuilder.workflow("flowWithExplicitNames")
.tasks(
doTasks(
set("set", "$.initialized = true"),
call("call", http().GET().endpoint("http://example.com")),
emit("emit", e -> e.event(p -> p.type("test.event"))),
listen(
"listen",
l ->
l.to(
to ->
to.one(
f ->
f.with(p -> p.type("com.test.event").source("test"))))),
forEach("forEach", f -> f.each("item").in("$.items")),
fork("fork", f -> f.compete(false)),
switchCase("switch", cases().onDefault(FlowDirectiveEnum.CONTINUE)),
raise("raise", r -> r.error(e -> e.type("test.error").status(500))),
tryCatch("try", t -> t.tryHandler(inner -> inner.set("inner", "$.value = 1")))))
.build();

List<TaskItem> items = wf.getDo();
assertNotNull(items, "Do list must not be null");
assertEquals(9, items.size(), "There should be nine tasks");

assertEquals("set", items.get(0).getName());
assertNotNull(items.get(0).getTask().getSetTask());

assertEquals("call", items.get(1).getName());
assertNotNull(items.get(1).getTask().getCallTask());

assertEquals("emit", items.get(2).getName());
assertNotNull(items.get(2).getTask().getEmitTask());

assertEquals("listen", items.get(3).getName());
assertNotNull(items.get(3).getTask().getListenTask());

assertEquals("forEach", items.get(4).getName());
assertNotNull(items.get(4).getTask().getForTask());

assertEquals("fork", items.get(5).getName());
assertNotNull(items.get(5).getTask().getForkTask());

assertEquals("switch", items.get(6).getName());
assertNotNull(items.get(6).getTask().getSwitchTask());

assertEquals("raise", items.get(7).getName());
assertNotNull(items.get(7).getTask().getRaiseTask());

assertEquals("try", items.get(8).getName());
assertNotNull(items.get(8).getTask().getTryTask());
}

@Test
void testDoTaskMultipleTypes() {
Workflow wf =
Expand Down
Loading