Skip to content

Conversation

@cppwfs
Copy link
Contributor

@cppwfs cppwfs commented Sep 26, 2025

Introduces Cloud Events v1.0 specification support including message converters, transformers, and utilities.

Key components added:

  • CloudEventMessageConverter for message format conversion
  • ToCloudEventTransformer for transforming messages to Cloud Events
  • MessageBinaryMessageReader/Writer for binary format handling
  • CloudEventProperties for configuration management
  • Header pattern matching utilities for flexible event mapping
  • Add reference docs and what's-new paragraph

@cppwfs cppwfs requested a review from artembilan September 26, 2025 20:28
@cppwfs cppwfs force-pushed the SI-cloud-events branch 2 times, most recently from 03d1f51 to 02a1329 Compare September 26, 2025 20:47
Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

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

Left some at a glance review.

Thank you!

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

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

Sorry for a lengthy review and some doubts I've expressed.

I addition, what are your thoughts about content of this package in Spring Cloud Function: https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/cloudevent ?

I mean transformer does the trick indeed, but only from an integration flow context.
How about the way to be able to construct CloudEvent programmatically?
Or just existing SDK API is enough to deal with?

@cppwfs cppwfs force-pushed the SI-cloud-events branch 2 times, most recently from cabc5e5 to d14c5f8 Compare October 6, 2025 15:32
@cppwfs
Copy link
Contributor Author

cppwfs commented Oct 6, 2025

For now hold off on a review. I'm writing up some questions for some guidance on some of the issues you raised in the last 2 reviews.

cppwfs and others added 7 commits November 24, 2025 07:20
Introduces Cloud Events v1.0 specification support
including message converters, transformers, and utilities.

Key components added:
- CloudEventMessageConverter for message format conversion
- ToCloudEventTransformer for transforming messages to Cloud Events
- MessageBinaryMessageReader/Writer for binary format handling
- CloudEventProperties for configuration management
- Header pattern matching utilities for flexible event mapping
- Add reference docs and what's-new paragraph
Remove v1 subpackage and flatten the CloudEvents package hierarchy.
Introduce strategy pattern for format conversion to replace enum-based approach,
improving extensibility and reduce dependencies.

Key changes:
- Move all classes from cloudevents.v1 to cloudevents base package
- Remove optional format dependencies (JSON, XML, Avro) from build
- Replace `ConversionType` enum with `FormatStrategy` interface
- Add `CloudEventMessageFormatStrategy` as default implementation
- Inline `HeaderPatternMatcher` logic into `ToCloudEventTransformerExtensions`
- Add `@NullMarked` package annotations and `@Nullable` throughout
- Document `targetClass` parameter behavior in `CloudEventMessageConverter`
- Split transformer tests for better organization and coverage
- Update component type identifier to "ce:to-cloudevents-transformer"
- Remove unnecessary docs from package-info
- Simplify the CloudEvent transformer by consolidating configuration
  directly into ToCloudEventTransformer class rather than using
  separate configuration objects
- Remove CloudEventProperties and ToCloudEventTransformerExtensions
  classes to reduce abstraction layers and improve maintainability
- Make MessageBinaryMessageReader package-private and convert
  CloudEventMessageConverter methods to static where possible
- Move extension filtering logic into a private inner class within
  the transformer
- Remove CloudEventsHeaders class and CE_PREFIX constant as the
  prefix is no longer used as a configurable value
Replace custom CloudEvent converter infrastructure with direct
CloudEvents SDK format implementations.

Key changes:
- Replace `FormatStrategy` pattern-based approach with direct
  `EventFormatProvider` integration from CloudEvents SDK
- Remove custom converter classes (`CloudEventMessageConverter`,
  `MessageBinaryMessageReader`, `MessageBuilderMessageWriter`)
- Simplify transformer to use Expression-based configuration for
  all CloudEvent attributes (id, source, type, dataSchema, subject)
- Add validation for required CloudEvent attributes with clear
  error messages when expressions evaluate to null or empty values
- Update documentation to reflect Expression-based API and
  byte[] payload requirement
- Consolidate tests by removing coverage for deleted converter
  infrastructure
The previous extension extraction mechanism using `Expression` arrays
and a separate `ExtensionsExtractor` interface was overly complex for
the simple use case of pattern matching header names.

This change simplifies the API by:
- Removing the `ExtensionsExtractor` interface and implementations
- Replacing `Expression`-based extension configuration with simple
  String pattern matching in the transformer constructor
- Updating all javadocs to use imperative voice per Spring
  conventions (e.g., "Converts messages" instead of "A transformer
  that converts messages")
- Making default value descriptions more concise (e.g., "Defaults
  to null" instead of "Default Expression evaluates to a null")
- Add extensionPattern match logic
Enable CloudEvents to be sent with headers
instead of requiring structured format serialization. This provides
flexibility when integrating with systems that don't support
CloudEvents structured formats.

Introduce `CloudEventMessageConverter` to handle CloudEvent to
Message conversion, utilizing the CloudEvents SDK's
`MessageWriter` abstraction.

Add `noFormat` configuration option to `ToCloudEventsTransformer`.
When enabled and no `EventFormat` is available for the content type,
CloudEvent attributes are written to message headers with
configurable prefix (defaults to "ce-").

Add `cloudEventPrefix` property to customize the header prefix
when `noFormat` is set to true, supporting different integration scenarios.

Add test coverage for binary content mode including
extension handling, custom prefixes, and validation that original
headers are preserved alongside CloudEvent headers.
Update javadoc comments in `CloudEventMessageConverter` and
`ToCloudEventsTransformer` to improve clarity and readability.
Enhance the CloudEvents reference documentation to better explain
how extensions are populated using pattern matching instead of
SpEL expressions.

Changes include:
- Clarify `CloudEventMessageConverter` class-level javadoc
- Improve `isNoFormat()` and `setNoFormat()` method documentation
- Update reference docs to reflect extension patterns approach
- Fix minor formatting issues (double spaces)
Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

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

Sorry for lengthy review: too many concerns.

Please, consider to rebase your branch to the latest main.
And take into account that it is already 7.1.

Thanks

testImplementation "io.cloudevents:cloudevents-json-jackson:$cloudEventsVersion"

testImplementation("io.cloudevents:cloudevents-avro-compact:$cloudEventsVersion") {
exclude group: 'org.apache.avro', module: 'avro'
Copy link
Member

Choose a reason for hiding this comment

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

Why do we care what kind of Avro comes transitively from Cloud Events since it is a test dependency?
On the other hand: do we really have tests with Avro to worry ab out this dependency at all?
Similar question for all other formats: if we don't have respective tests, then we don't need that dependency.

We might need to have just one for Jackson to be sure that our format-related logic is correct.
The rest, out-of--use, deps should be dropped altogether.

@Override
public Message<?> toMessage(Object payload, @Nullable MessageHeaders headers) {
if (payload instanceof CloudEvent event) {
return CloudEventUtils.toReader(event).read(new MessageBuilderMessageWriter(this.cloudEventPrefix,
Copy link
Member

Choose a reason for hiding this comment

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

Since this class is internal and has a logic only delegate to the MessageBuilderMessageWriter, I wonder if we need this class at all and really just use that MessageBuilderMessageWriter in the transformer.

* @param dataContentTypeKey the header name for the data content type
* @param headers the base message headers to include in the output message
*/
MessageBuilderMessageWriter(String cloudEventPrefix, String specVersionKey, String dataContentTypeKey, Map<String, Object> headers) {
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need custom specVersionKey and dataContentTypeKey?
Why would one use something which is not a standard and may not be compatible with consumers of the event?

@SuppressWarnings("NullAway.Init")
private EvaluationContext evaluationContext;

private final EventFormatProvider eventFormatProvider = EventFormatProvider.getInstance();
Copy link
Member

Choose a reason for hiding this comment

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

Please, fix properties order.
The final have to go firsts. Right, after static, but still not here and not in between.

* to the CloudEvent
*/
public ToCloudEventsTransformer(String ... extensionPatterns) {
this.extensionPatterns = extensionPatterns;
Copy link
Member

Choose a reason for hiding this comment

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

You cannot do this. External object mutation problem.
So, we have to copy an input array to the output one.
Also: why those ellipses are not stick to the String type?

The transformer follows the process below:

1. **CloudEvent Building**: Build CloudEvent attributes
2. **Extension Extraction**: Build the CloudEvent extensions using the array of extensionExpressions passed into the constructor.
Copy link
Member

Choose a reason for hiding this comment

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

I think there is no extensionExpressions any more.
Please, revise this text.

===== EventFormats

The `ToCloudEventsTransformer` uses `EventFormat` s to serialize the CloudEvent into the message's payload.
The `EventFormat` s used by the `ToCloudEventsTransformer` are obtained from the classpath of the project.
Copy link
Member

Choose a reason for hiding this comment

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

We cannot assume that formats are always just by classpath scanning.
I think we can add some manually at runtime.
Either way, it is out of our scope to claim how EventFormat works.


[[jsonformat]]
====== JsonFormat
The following dependency can be used to include this `JsonFormat` in your project.
Copy link
Member

Choose a reason for hiding this comment

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

No sticking to the title, please.
And that is, of course, if we move on with "may sub-titles" approach 😄

----
compile "io.cloudevents:cloudevents-json-jackson:$cloudEventsVersion"
----
======
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that we need to be so fine-grained.
Just mention in the text that we need an io.cloudevents:cloudevents-json-jackson dependency and that's it. It should be obvious from there that it depends on your build system.
Plus you made a mistake in the Maven sample.
Has to be ${cloudEventsVersion}, not a Gradle style 😉

This is a breaking change, and direct references to components of the JCIFS library will need to be updated.
See xref:smb.adoc[] for more information.

[[x7.0-cloudevents]]
Copy link
Member

Choose a reason for hiding this comment

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

This would have to be fixed for 7.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants