Problem
When emitting events via emit.event.with, the spec requires id, source, and type to be set. The current implementation has gaps:
- No model-level validation —
EventProperties has zero @NotNull/@NotBlank annotations. All fields are optional at the type level, with enforcement only at runtime in EmitExecutor.
- Weak
source default — CloudEventUtils.source() returns URI.create("reference-impl"), which provides no traceability.
- No
time default — emitted events have no timestamp unless the user explicitly sets one. CloudEvents best practice recommends always including time.
Current runtime behavior (EmitExecutor)
| Field |
Behavior when missing |
id |
Auto-generates UUID — good |
source |
Falls back to "reference-impl" — weak |
type |
Throws IllegalArgumentException — correct |
time |
Not set — should default to now |
Proposed improvements
1. Improve CloudEventUtils.source() default
Replace "reference-impl" with something meaningful. Options:
"io.serverlessworkflow.sdk-java" (static, identifies the SDK)
- Derive from
WorkflowDefinitionId: "{namespace}/{name}:{version}" (e.g., "org-acme/order-processor:1.0.0")
The second option requires passing context into EmitExecutor.buildCloudEvent(), which already has access to WorkflowContext.
2. Default time to OffsetDateTime.now() in EmitExecutor
When timeFilter is empty, set ceBuilder.withTime(OffsetDateTime.now()) instead of omitting it.
3. Add defaults in the DSL layer (EmitSpec / produced())
The EmitSpec convenience methods could embed defaults so the common path produces valid, traceable CloudEvents:
produced(type) could auto-set source (e.g., from a configurable default)
randomId() evaluated at definition time won't work for id (needs to be unique per execution), so the runtime fallback is the right place
4. Make source configurable at WorkflowApplication level
Allow setting a default source once that applies to all emitted events, overridable per-emit.
Note on validation annotations
EventProperties is shared between emit and filter contexts (where requirements differ), so adding @NotNull directly would break filter use cases. Runtime validation in EmitExecutor is the correct approach unless a separate emit-specific type is introduced.
Problem
When emitting events via
emit.event.with, the spec requiresid,source, andtypeto be set. The current implementation has gaps:EventPropertieshas zero@NotNull/@NotBlankannotations. All fields are optional at the type level, with enforcement only at runtime inEmitExecutor.sourcedefault —CloudEventUtils.source()returnsURI.create("reference-impl"), which provides no traceability.timedefault — emitted events have no timestamp unless the user explicitly sets one. CloudEvents best practice recommends always includingtime.Current runtime behavior (
EmitExecutor)idsource"reference-impl"— weaktypeIllegalArgumentException— correcttimeProposed improvements
1. Improve
CloudEventUtils.source()defaultReplace
"reference-impl"with something meaningful. Options:"io.serverlessworkflow.sdk-java"(static, identifies the SDK)WorkflowDefinitionId:"{namespace}/{name}:{version}"(e.g.,"org-acme/order-processor:1.0.0")The second option requires passing context into
EmitExecutor.buildCloudEvent(), which already has access toWorkflowContext.2. Default
timetoOffsetDateTime.now()inEmitExecutorWhen
timeFilteris empty, setceBuilder.withTime(OffsetDateTime.now())instead of omitting it.3. Add defaults in the DSL layer (
EmitSpec/produced())The
EmitSpecconvenience methods could embed defaults so the common path produces valid, traceable CloudEvents:produced(type)could auto-setsource(e.g., from a configurable default)randomId()evaluated at definition time won't work forid(needs to be unique per execution), so the runtime fallback is the right place4. Make
sourceconfigurable atWorkflowApplicationlevelAllow setting a default source once that applies to all emitted events, overridable per-emit.
Note on validation annotations
EventPropertiesis shared between emit and filter contexts (where requirements differ), so adding@NotNulldirectly would break filter use cases. Runtime validation inEmitExecutoris the correct approach unless a separate emit-specific type is introduced.