Skip to content

Improve CloudEvent defaults and validation for emit events #1554

Description

@ricardozanini

Problem

When emitting events via emit.event.with, the spec requires id, source, and type to be set. The current implementation has gaps:

  1. No model-level validationEventProperties has zero @NotNull/@NotBlank annotations. All fields are optional at the type level, with enforcement only at runtime in EmitExecutor.
  2. Weak source defaultCloudEventUtils.source() returns URI.create("reference-impl"), which provides no traceability.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions