-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add Cloud Events support to Spring Integration #10448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
03d1f51 to
02a1329
Compare
artembilan
left a comment
There was a problem hiding this 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!
...src/main/java/org/springframework/integration/cloudevents/v1/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...src/main/java/org/springframework/integration/cloudevents/v1/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...src/main/java/org/springframework/integration/cloudevents/v1/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...g/springframework/integration/cloudevents/v1/transformer/CloudEventMessageConverterTest.java
Outdated
Show resolved
Hide resolved
artembilan
left a comment
There was a problem hiding this 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?
...ts/src/main/java/org/springframework/integration/cloudevents/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...ation/cloudevents/transformer/strategies/cloudeventconverter/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...ation/cloudevents/transformer/strategies/cloudeventconverter/MessageBinaryMessageReader.java
Outdated
Show resolved
Hide resolved
...pringframework/integration/cloudevents/v1/transformer/ToCloudEventTransformerExtensions.java
Outdated
Show resolved
Hide resolved
...a/org/springframework/integration/cloudevents/v1/transformer/utils/HeaderPatternMatcher.java
Outdated
Show resolved
Hide resolved
...java/org/springframework/integration/cloudevents/v1/transformer/ToCloudEventTransformer.java
Outdated
Show resolved
Hide resolved
...java/org/springframework/integration/cloudevents/v1/transformer/ToCloudEventTransformer.java
Outdated
Show resolved
Hide resolved
.../main/java/org/springframework/integration/cloudevents/transformer/CloudEventProperties.java
Outdated
Show resolved
Hide resolved
...loudevents/src/main/java/org/springframework/integration/cloudevents/CloudEventsHeaders.java
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
cabc5e5 to
d14c5f8
Compare
...ts/src/main/java/org/springframework/integration/cloudevents/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...loudevents/src/main/java/org/springframework/integration/cloudevents/CloudEventsHeaders.java
Outdated
Show resolved
Hide resolved
...ts/src/main/java/org/springframework/integration/cloudevents/MessageBinaryMessageReader.java
Outdated
Show resolved
Hide resolved
...ts/src/main/java/org/springframework/integration/cloudevents/MessageBinaryMessageReader.java
Outdated
Show resolved
Hide resolved
...s/src/main/java/org/springframework/integration/cloudevents/MessageBuilderMessageWriter.java
Outdated
Show resolved
Hide resolved
...s/src/main/java/org/springframework/integration/cloudevents/MessageBuilderMessageWriter.java
Outdated
Show resolved
Hide resolved
...g/springframework/integration/cloudevents/transformer/ToCloudEventTransformerExtensions.java
Outdated
Show resolved
Hide resolved
...g/springframework/integration/cloudevents/transformer/ToCloudEventTransformerExtensions.java
Outdated
Show resolved
Hide resolved
.../java/org/springframework/integration/cloudevents/transformer/strategies/FormatStrategy.java
Outdated
Show resolved
Hide resolved
...t/java/org/springframework/integration/cloudevents/transformer/CloudEventPropertiesTest.java
Outdated
Show resolved
Hide resolved
|
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. |
.../java/org/springframework/integration/cloudevents/transformer/strategies/FormatStrategy.java
Outdated
Show resolved
Hide resolved
...s/src/main/java/org/springframework/integration/cloudevents/MessageBuilderMessageWriter.java
Outdated
Show resolved
Hide resolved
...loudevents/src/main/java/org/springframework/integration/cloudevents/CloudEventsHeaders.java
Outdated
Show resolved
Hide resolved
d14c5f8 to
d8989f9
Compare
d8989f9 to
be0fa17
Compare
...in/java/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformer.java
Show resolved
Hide resolved
...in/java/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformer.java
Outdated
Show resolved
Hide resolved
...in/java/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformer.java
Outdated
Show resolved
Hide resolved
...va/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformerTests.java
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
src/reference/antora/modules/ROOT/pages/cloudevents-transform.adoc
Outdated
Show resolved
Hide resolved
...va/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformerTests.java
Outdated
Show resolved
Hide resolved
...va/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformerTests.java
Outdated
Show resolved
Hide resolved
be0fa17 to
d115df2
Compare
d115df2 to
23379aa
Compare
artembilan
left a comment
There was a problem hiding this 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
...java/org/springframework/integration/cloudevents/transformer/CloudEventMessageConverter.java
Outdated
Show resolved
Hide resolved
...ava/org/springframework/integration/cloudevents/transformer/MessageBuilderMessageWriter.java
Outdated
Show resolved
Hide resolved
...n/java/org/springframework/integration/cloudevents/transformer/ToCloudEventsTransformer.java
Outdated
Show resolved
Hide resolved
...n/java/org/springframework/integration/cloudevents/transformer/ToCloudEventsTransformer.java
Outdated
Show resolved
Hide resolved
artembilan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you have addressed everything from the previous review, but probably just locally.
Please, push it into PR with rebase to the latest main.
This way I might review it again before Monday.
Thanks
23379aa to
3db880e
Compare
artembilan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for such a lengthy review before New Year 😄 .
...in/java/org/springframework/integration/cloudevents/transformer/ToCloudEventTransformer.java
Outdated
Show resolved
Hide resolved
| * Create a ToCloudEventTransformer. | ||
| * @param extensionPatterns patterns to evaluate whether message headers should be added as extensions | ||
| * to the CloudEvent | ||
| * @since 7.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This @since on methods is redundant since all of them have been introduced together with the class.
| protected void onInit() { | ||
| super.onInit(); | ||
| this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); | ||
| if (this.sourceExpression == null) { // in the case the user sets the value prior to onInit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, remove the comment.
It does not give any value.
Plus, it sounds like does not reflect reality: the condition is about null, but sentence in comment says something opposite.
| String appName = applicationContext.getEnvironment().getProperty("spring.application.name"); | ||
| logger.warn("'spring.application.name' is not set. " + | ||
| "CloudEvent source URIs will use 'null' as the application name. " + | ||
| "Consider setting 'spring.application.name'"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this warning has to be conditional on appName == null
| String type = this.typeExpression.getValue(this.evaluationContext, message, String.class); | ||
| MessageHeaders headers = message.getHeaders(); | ||
| MessageHeaderAccessor accessor = new MessageHeaderAccessor(message); | ||
| MimeType mimeType = accessor.getContentType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, consider to use StaticMessageHeaderAccessor.getContentType() instead.
That way we won't have an extra MessageHeaderAccessor volatile object.
|
|
||
| ==== Extension Patterns | ||
|
|
||
| The extensionPatterns constructor parameter is a vararg of ``String``s. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to wrap into code snippet.
Just say of strings and that's enough.
Really this sentence does not emphasize about exactly String object logic and API.
| .withHeader(MessageHeaders.CONTENT_TYPE, "application/octet-stream") | ||
| .build(); | ||
| // Transformer with extension patterns | ||
| ToCloudEventTransformer transformer = new ToCloudEventTransformer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment about does not reflect this constructor behavior.
| // Input message with headers | ||
| Message<byte[]> inputMessage = MessageBuilder | ||
| .withPayload("Hello CloudEvents".getBytes(StandardCharsets.UTF_8)) | ||
| .withHeader(MessageHeaders.CONTENT_TYPE, "application/octet-stream") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I would say this is text/plain.
The octet-stream is too general and could be used somewhere else.
But having just text and ignoring its respective content type, might lead to a wrong impression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to provide the output of the transformation to add clarification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we want an output format explained somewhere, but that is not a concern of this code example.
What I mean here that Hello CloudEvents is a text/plain, not an application/octet-stream.
That's only a change I want to see in this example.
Otherwise it is misleading.
| [[eventformats]] | ||
| ==== EventFormats | ||
|
|
||
| The `ToCloudEventTransformer` uses ``EventFormat``s to serialize the CloudEvent into the message's payload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to say more about contentType header and how it is used for EventFormat search.
I also don't see anywhere that we mention the output contentType and those ce- attributes produced by our transformer.
That is really most important part of the transformer: give a message with some data and get back a message with that data but in CloudEvents format.
And that could be done by the EventFormat delegation or flattening into message headers.
Looks like that is missing in this doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was my request about the transformer output.
The configuration explanation is good, but what is the result of that transformation.
That's is exactly what users are going to deal with.
|
|
||
| assertThat(result).isNotNull(); | ||
| assertThat(result).isInstanceOf(Message.class); | ||
| return (Message<byte[]>) result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole message is redundant.
We simply can use Transformer.transform() API in all those tests.
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)
This commit updates the CloudEvents module from version 7.0 to 7.1 by consolidating classes and improving the architecture. The previous design separated the CloudEvent conversion logic across multiple classes (`CloudEventMessageConverter` and `MessageBuilderMessageWriter`), which added unnecessary complexity for what is fundamentally a single transformation operation. Key changes: - Removed `CloudEventMessageConverter` and `MessageBuilderMessageWriter` as standalone classes - Consolidated conversion logic into `ToCloudEventTransformer` by making `MessageBuilderMessageWriter` a private static inner class - Renamed `ToCloudEventsTransformer` to `ToCloudEventTransformer` to match naming conventions (singular form) - Removed Avro dependencies and associated tests that were no longer needed - Changed `setNoFormat()` to `setFailOnNoFormat()` for clearer semantics - Enhanced null safety by removing `@Nullable` from setters that should always have values - Re-add isFailOnNoFormat logic and tests that was removed - Improved documentation and added defensive copying for the `extensionPatterns` array parameter - Updated tests to reflect the new class names and structure - Rebased The refactoring reduces the public API surface while maintaining all functionality, making the code easier to understand and maintain.
Address multiple improvements to the CloudEvents transformer module: - Reorganize constructor ordering in `ToCloudEventTransformer` to put the no-arg constructor first, following Java conventions - Remove unused Avro test dependency from build.gradle - Improve content type handling using `MessageHeaderAccessor` and `MimeType` instead of direct String extraction - Refactor extension processing to use `Map.copyOf()` for immutability - Rename `ToCloudEventTransformerExtensions` to singular `ToCloudEventTransformerExtension` for consistency - Inline constant strings for specversion and datacontenttype keys - Fix content type header to use `eventFormat.serializedContentType()` instead of the input message's content type - Simplify binary mode message creation by constructing `MessageHeaders` directly - Update test assertions to match null appName behavior - Enhance documentation clarity: improve wording, fix grammar, capitalize table entries, and add examples for content types - Restructure documentation sections for better readability - Update `MessageBuilderMessageWriter` to implement `CloudEventWriterFactory` instead of `MessageWriter` The message writer had default functions unused by the read method. - Remove unused `setEvent()` method and `dataContentTypeKey` field from `MessageBuilderMessageWriter` - Apply Spring code convention
|
|
||
| private static final String DEFAULT_PREFIX = "ce-"; | ||
|
|
||
| private static final EventFormatProvider eventFormatProvider = EventFormatProvider.getInstance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is static final then it has to be in upper case.
It is a constant then, therefore respective naming convention.
| .setHeader(MessageHeaders.CONTENT_TYPE, eventFormat.serializedContentType()) | ||
| .build(); | ||
| } | ||
| HashMap<String, Object> messageMap = new HashMap<>(headers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think putting the contentType header could be hidden in the MessageBuilderMessageWriter.
Perhaps in its end() implementation.
That way we would not need to wrap headers into a new map.
| .withExtension(extensions) | ||
| .build(); | ||
|
|
||
| EventFormat eventFormat = eventFormatProvider.resolveFormat(contentType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have realized that provider is based on exactly cloudevents+ content types, then we cannot rely on our common types.
I think we should come back to the idea about an EventFormat injection into this our transformer.
(My apologies that I misled to the EventFormatProvider).
We probably still can use an EventFormatProvider, however not against standard contentType header, but with some custom SpEL expression.
This way the logic would be:
- Use injected
EventFormat(if any) - Resolve
eventFormatContentTypeExpression(if any) - Call
EventFormatProviderfor the previous expression result. - If no such a format, fail if
failOnNoFormat - Still use an input
contentTypeheader as adataContentTypein theCloudEvent - Still populate a proper output
contentTypefrom theEventFormator standard one in theMessageBuilderMessageWriter
WDYT?
| assertThat(cloudEvent.getData().toBytes()).isEqualTo(PAYLOAD); | ||
| assertThat(cloudEvent.getSource().toString()).isEqualTo("/spring/null.transformerWithNoExtensions"); | ||
| assertThat(cloudEvent.getDataSchema()).isNull(); | ||
| assertThat(cloudEvent.getDataContentType()).isEqualTo(JsonFormat.CONTENT_TYPE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the current behavior reflects whatever is possible with the current implementation.
However that is not what we want with our transformer.
See my suggestion above about an EventFormat injection and so on.
|
|
||
| @Test | ||
| void emptyStringPayloadHandling() { | ||
| Message<byte[]> message = createBaseMessage("".getBytes(), "application/cloudevents+json").build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to close the loop: in some other comment about I've suggested an EventFormat injection or respective eventFormatContentTypeExpression instead of this not fully flexible logic against a input contentType header.
| | "spring.message" | ||
|
|
||
| | `dataContentType` | ||
| | The contentType of the message, defaults to `application/octet-stream`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, examples here you provide are exactly what I would expect sending a text/json in the contentType to our transformer. So, this value would be copied to the dataContentType attribute of the cloud event.
Meanwhile the output contentType header would be applicaiton/cloudevents (or with + if format is involved).
| // Input message with headers | ||
| Message<byte[]> inputMessage = MessageBuilder | ||
| .withPayload("Hello CloudEvents".getBytes(StandardCharsets.UTF_8)) | ||
| .withHeader(MessageHeaders.CONTENT_TYPE, "application/octet-stream") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we want an output format explained somewhere, but that is not a concern of this code example.
What I mean here that Hello CloudEvents is a text/plain, not an application/octet-stream.
That's only a change I want to see in this example.
Otherwise it is misleading.
| [[eventformats]] | ||
| ==== EventFormats | ||
|
|
||
| The `ToCloudEventTransformer` uses ``EventFormat``s to serialize the CloudEvent into the message's payload. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was my request about the transformer output.
The configuration explanation is good, but what is the result of that transformation.
That's is exactly what users are going to deal with.
Code quality improvements: - Remove unnecessary `@since 7.1` tags from internal javadocs - Fix NullAway suppressions by adding proper null checks - Replace `MessageHeaderAccessor` with `StaticMessageHeaderAccessor` - Eliminate redundant field initialization (failOnNoFormat defaults to false) - Simplify extension comparison using `Boolean.TRUE.equals()` - Remove unnecessary Map.copyOf() in extension implementation - Fix app name null check to only warn when actually null Test refactoring: - Make test helper methods static for better encapsulation - Rename test methods to clearly indicate content type being tested - Separate JSON format vs application/json content type test cases - Add explicit verification for application/* content types - Improve test assertions using containsEntry() instead of get() - Remove unnecessary null checks in tests - Consolidate duplicate test setup code Documentation: - Add package-info.java descriptions for cloudevents packages - Update reference documentation for extension patterns clarity
a4ae49a to
af2dbf8
Compare
| private Map<String, Object> getCloudEventExtensions(MessageHeaders headers) { | ||
| Map<String, Object> cloudEventExtensions = new HashMap<>(); | ||
| Boolean patternResult; | ||
| String headerKey; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These variables really belong to the loop scope below.
Why would you declare them outside of the loop?
| * Perform attribute and extension mapping based on {@link Expression}s. | ||
| * | ||
| * @author Glenn Renfro | ||
| * @since 7.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed blank line after @author
|
|
||
| /** | ||
| * Convert messages to CloudEvent format. | ||
| * Perform attribute and extension mapping based on {@link Expression}s. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK with attribute.
But extension is not does by expression.
Please, consider to revise this Javadoc to reflect reality about the transformer logic.
I guess we can leave EventFormat out of this for now, since we don't have a final solution yet.
But extensionPatterns could be already explained in this Javadocs properly.
Introduces Cloud Events v1.0 specification support including message converters, transformers, and utilities.
Key components added: