Skip to content

fix #1252: Add predictable naming to tasks instead of UUIDs#1253

Open
ricardozanini wants to merge 2 commits intoserverlessworkflow:mainfrom
ricardozanini:issue-1252
Open

fix #1252: Add predictable naming to tasks instead of UUIDs#1253
ricardozanini wants to merge 2 commits intoserverlessworkflow:mainfrom
ricardozanini:issue-1252

Conversation

@ricardozanini
Copy link
Member

Many thanks for submitting your Pull Request ❤️!

What this PR does / why we need it:
Fixes #1252

Special notes for reviewers:

Additional information (if needed):

…of UUIDs

Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
Copilot AI review requested due to automatic review settings March 20, 2026 23:17
@ricardozanini ricardozanini requested a review from fjtirado as a code owner March 20, 2026 23:17
Copy link
Contributor

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

Updates the Java fluent DSL to generate deterministic task names when callers pass null/blank names (and when using name-less overloads), replacing previously random UUID-based naming to improve debuggability and testability (Issue #1252).

Changes:

  • Replace UUID defaults in fluent SPI convenience overloads with null so builders can apply deterministic naming.
  • Implement deterministic auto-naming in task list builders via a taskType-index scheme.
  • Add a new JUnit test suite covering auto-naming across top-level and nested task builders (try/forEach/fork).

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/TaskItemDefaultNamingTest.java Adds unit tests asserting deterministic default naming for unnamed tasks (including nested builders).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/TryCatchFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchTaskFluent.java Changes default overload to pass null for switch item names.
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SwitchFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/SetFluent.java Changes default overloads to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/RaiseFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ListenFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForkFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/ForEachFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/EmitFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallOpenAPIFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/TaskItemListBuilder.java Plumbs task type into default-name helper for each task kind.
fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/BaseTaskItemListBuilder.java Introduces deterministic naming helper (taskType + "-" + list.size()) and task type constants.
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/spi/CallFnFluent.java Changes default overload to pass null (enabling deterministic naming downstream).
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncTaskItemListBuilder.java Updates func DSL list builder to use deterministic naming helper (adds TYPE_FUNCTION).
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncSwitchTaskBuilder.java Adds deterministic naming for onPredicate(...) when name is null/blank.
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForkTaskBuilder.java Adds deterministic naming for unnamed fork branches.
experimental/fluent/func/src/main/java/io/serverlessworkflow/fluent/func/FuncForTaskBuilder.java Adds deterministic naming for unnamed loop tasks.

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


List<TaskItem> topItems = wf.getDo();
assertEquals(1, topItems.size());
assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be tryCatch-0");
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 assertion message says "tryCatch-0" but the expected value is "try-0". Please align the message with the expected naming to avoid confusion when the test fails.

Suggested change
assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be tryCatch-0");
assertEquals("try-0", topItems.get(0).getName(), "Top level tryCatch should be try-0");

Copilot uses AI. Check for mistakes.
f ->
f.each("item")
.in("$.list")
// Assuming the DSL exposes `do_` or `tasks` for inner ForEach logic
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.

This comment suggests the DSL might not support .tasks(...) inside forEach, but ForEachTaskBuilder does expose tasks(...). Consider removing or updating the comment since it can mislead readers and may become stale.

Suggested change
// Assuming the DSL exposes `do_` or `tasks` for inner ForEach logic
// Define tasks to be executed for each item in the forEach loop

Copilot uses AI. Check for mistakes.
Comment on lines +73 to 76
if (name == null || name.isBlank()) {
name = "switch-item-" + this.switchItems.size();
}
this.switchItems.add(new SwitchItem(name, switchCase.build()));
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.

SwitchTaskFluent.on(Consumer) now passes null as the name, but this builder only applies default naming in onPredicate(...) and still adds switch items with the raw name in on(String, ...). That means .on(...) will now create SwitchItems with null/blank names. Please add the same null/blank defaulting for on(String, ...) (or override on(Consumer) in this builder) so switch items always have deterministic non-blank names.

Copilot uses AI. Check for mistakes.
Comment on lines 28 to 32
default SELF on(Consumer<SwitchTaskFluent.SwitchCaseBuilder> switchCaseConsumer) {
return this.on(UUID.randomUUID().toString(), switchCaseConsumer);
return this.on(null, switchCaseConsumer);
}

SELF on(final String name, Consumer<SwitchTaskFluent.SwitchCaseBuilder> switchCaseConsumer);
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.

on(Consumer) now delegates to on(null, ...), but SwitchTaskBuilder.on(String, ...) currently stores the provided name directly in new SwitchItem(name, ...). This change can produce SwitchItem entries with null/blank names, which is a behavior change from the previous UUID default and can lead to invalid or ambiguous switch definitions. Please ensure switch-case items get a deterministic non-blank default name when none is provided (e.g., based on insertion index) or keep generating a non-null default here until implementations are updated.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +46
public final String TYPE_SET = "set";
public final String TYPE_FOR = "for";
public final String TYPE_SWITCH = "switch";
public final String TYPE_RAISE = "raise";
public final String TYPE_FORK = "fork";
public final String TYPE_LISTEN = "listen";
public final String TYPE_EMIT = "emit";
public final String TYPE_TRY = "try";
public final String TYPE_HTTP = "http";
public final String TYPE_OPENAPI = "openapi";
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 task type constants are declared as public final instance fields. This unnecessarily expands the public API surface and creates per-instance copies; consider making them protected static final (or private constants) since they appear to be internal implementation details used for default naming.

Suggested change
public final String TYPE_SET = "set";
public final String TYPE_FOR = "for";
public final String TYPE_SWITCH = "switch";
public final String TYPE_RAISE = "raise";
public final String TYPE_FORK = "fork";
public final String TYPE_LISTEN = "listen";
public final String TYPE_EMIT = "emit";
public final String TYPE_TRY = "try";
public final String TYPE_HTTP = "http";
public final String TYPE_OPENAPI = "openapi";
protected static final String TYPE_SET = "set";
protected static final String TYPE_FOR = "for";
protected static final String TYPE_SWITCH = "switch";
protected static final String TYPE_RAISE = "raise";
protected static final String TYPE_FORK = "fork";
protected static final String TYPE_LISTEN = "listen";
protected static final String TYPE_EMIT = "emit";
protected static final String TYPE_TRY = "try";
protected static final String TYPE_HTTP = "http";
protected static final String TYPE_OPENAPI = "openapi";

Copilot uses AI. Check for mistakes.
Comment on lines +72 to 78
protected final String defaultNameAndRequireConfig(
String name, Consumer<?> cfg, String taskType) {
Objects.requireNonNull(cfg, "Configurer must not be null");

if (name == null || name.isBlank()) {
name = UUID.randomUUID().toString();
return taskType + "-" + this.list.size();
}
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.

Auto-generated names currently use this.list.size() as the suffix, which makes the first generated name end with -0. Issue #1252’s example suggests set-1 for the first unnamed task; please confirm whether the index should be 1-based and adjust the implementation/tests accordingly (e.g., size() + 1) if that’s the expected contract.

Copilot uses AI. Check for mistakes.
Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
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.

Java DSL: Predictable task naming when name is not provided

2 participants