Skip to content

Add CloudEventHeadersBuilder DSL support - #10828

Merged
artembilan merged 6 commits into
spring-projects:mainfrom
cppwfs:SI-ce-headers
Feb 20, 2026
Merged

Add CloudEventHeadersBuilder DSL support#10828
artembilan merged 6 commits into
spring-projects:mainfrom
cppwfs:SI-ce-headers

Conversation

@cppwfs

@cppwfs cppwfs commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Introduce CloudEventHeadersBuilder to allow setting CloudEvent headers via the Spring Integration DSL using direct values, SpEL expressions, or Java functions. Expose the builder through a CloudEvents.headers() factory method.

@artembilan artembilan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good!

Comment thread src/reference/antora/modules/ROOT/pages/cloudevents.adoc Outdated
Comment thread src/reference/antora/modules/ROOT/pages/cloudevents.adoc Outdated
return IntegrationFlow
.from("inputChannel")
.enrichHeaders(CloudEvents.headers()
.idExpression("headers['orderId']")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

May we use MapAccessor style in the doc as well, please?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Was not addressed.
Or just comment here, please, why you have not changed it, but approved.

* @param prefix the event prefix
* @return the builder
*/
public CloudEventHeadersBuilder prefix(String prefix) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No. I still don't believe in this method.
Why to give a paradox of choice to user?
There is a ctor requesting such a prefix.
So, on any other mutators, please.

It also may cause the problem.
Let's imaging I have started with a default prefix!
Gave it a couple attributes, then decided to change the prefix.
But only the others after this method are going to be modified.
That is an inconsistency, which is possible, but probably with a generic enrichHeaders API, not with this builder for its own DSL-specific case.

private String eventDataSchemaKey = CloudEventHeaders.EVENT_DATA_SCHEMA;

/**
* Create a new {@link CloudEventHeadersBuilder}.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

... with default prefix ?

*/
public CloudEventHeadersBuilder(String prefix) {
this.prefix = prefix;
updatePrefix();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we don't need this extra method and do all the properties modification directly here.
I also still believe in some compiler optimization when we declare properties as final.
We probably won't need prefix after modified the rest of attributes here on the fly.

* @return the {@link ToCloudEventTransformerSpec} instance
*/
public static ToCloudEventTransformerSpec toCloudEventTransformer(String... extensionPatterns) {
return new ToCloudEventTransformerSpec(extensionPatterns);
}

/**
* Create a {@link CloudEventHeadersBuilder}.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

... with default prefix ?


@Test
void testEnrichHeadersWithDirectValues(@Autowired @Qualifier("directFlow.input") MessageChannel inputChannel) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, we don't need this blank line then?
Just minor, of course, but I wonder if we try to pursue consistence and perfect code.

IntegrationFlow functionFlow() {
return flow -> flow
.enrichHeaders(CloudEvents.headers()
.dataSchemaFunction(msg -> URI.create("https://example.com/schema/" +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would prefer to put the whole lambda body on a new line, rather than break on string concatenation.

return IntegrationFlow
.from("inputChannel")
.enrichHeaders(CloudEvents.headers()
.idExpression("headers['orderId']")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Was not addressed.
Or just comment here, please, why you have not changed it, but approved.

== CloudEvent Headers Builder

Use the `CloudEventHeadersBuilder` to set CloudEvent headers using Spring Integration's DSL.
Access the builder through the `CloudEvents.headers()` factory method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not saying that it is critical.
I feel discomfort with these two sentences.
Both of them are kind of commands I have to do.
Even if they don't use word you, it is still implied.
And this doc gives me some instructions.
In my understanding it has to explain a behavior of the API, not commands what and how to use.
Makes sense?
Or do I exaggerate?

@artembilan artembilan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is good now.
Just one concern with rebasing and redundant now suppress annotations.
Thanks

* @param time the event timestamp
* @return the builder
*/
@SuppressWarnings("NullAway")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please, rebase to the latest main and remove these warnings since nullability is there already.
Thanks

Introduce `CloudEventHeadersBuilder` to allow setting CloudEvent headers
via the Spring Integration DSL using direct values, SpEL expressions, or
Java functions. Expose the builder through a `CloudEvents.headers()`
factory method.
- Update `CloudEventHeadersBuilder` to properly support nullable values
    by changing the type parameter from `Object` to `@Nullable Object`.
- Remove remove `NullAway` `@SuppressWarnings`
@artembilan
artembilan merged commit cdda3d0 into spring-projects:main Feb 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment