This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Integration 7.0.3!

CloudEvents Support

Spring Integration provides support for the CloudEvents specification.

Add the following dependency to your project:

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-cloudevents</artifactId>
    <version>7.1.0-SNAPSHOT</version>
</dependency>
implementation "org.springframework.integration:spring-integration-cloudevents:7.1.0-SNAPSHOT"

ToCloudEventTransformer

Use the ToCloudEventTransformer to convert Spring Integration messages into CloudEvents-compliant messages. This transformer supports the CloudEvents specification v1.0 and serializes CloudEvents if an EventFormat or eventFormatContentTypeExpression is specified. When you specify an EventFormat or eventFormatContentTypeExpression, the transformer uses the EventFormat to generate the CloudEvent in the payload. If neither is specified, the transformer writes the event data message payload as-is and adds attributes as well as extensions to the message headers. The transformer supports defining attributes using expressions and identifies extensions in the message headers via patterns.

Attribute Expressions

Set the CloudEvents' attributes of id, source, type, dataSchema, and subject through SpEL expressions.

The transformer sets the time attribute to the time when it creates the CloudEvent instance.

The following table lists the attribute names and the values the default expressions return.

Attribute Name Default Value

id

The id of the message.

source

A prefix of "/spring/" followed by the appName, a period, and then the transformer’s bean name, e.g., /spring/myapp.toCloudEventTransformerBean.

type

"spring.message"

dataContentType

The contentType of the message, defaults to application/octet-stream. Some other examples include but are not limited to: application/json, application/x-avro, and application/xml.

dataSchema

The URI to the specified schema. The default for dataSchema is null.

subject

Identify the subject of the event in the context of the event producer. The default for subject is null.

time

The time the CloudEvent message is created. Set internally to the current time. Note that you cannot configure this value.

Extension Patterns

Use the extensionPatterns constructor parameter (a vararg of strings) to specify pattern matching with wildcards (*). The transformer includes message headers with keys matching any pattern as CloudEvent extensions. Use a ! prefix to explicitly exclude headers through negation. Note that the first matching pattern wins (whether positive or negative).

For example, configure the patterns "trace*", "span-id", "user-id" to: - Include headers starting with trace (e.g., trace-id, traceparent) - Include headers with exact keys span-id and user-id - Add all matching headers as extensions to the CloudEvent

To exclude specific headers, use negated patterns: "custom-*", "!custom-internal" includes all headers starting with custom- except custom-internal.

Configuration with DSL

Use the CloudEvents factory to add the ToCloudEventTransformer to flows using the Java DSL.

@Bean
public ToCloudEventTransformer cloudEventTransformer() {
    return new ToCloudEventTransformer("trace*", "correlation-id");
}

@Bean
public IntegrationFlow cloudEventTransformFlow(ToCloudEventTransformer toCloudEventTransformer) {
    return IntegrationFlows
        .from("inputChannel")
        .transform(CloudEvents.toCloudEventTransformer().get())
        .channel("outputChannel")
        .get();
}

CloudEvent Transformer Process

Understand the transformation process:

  1. CloudEvent Building - Build the CloudEvent attributes.

  2. Extension Extraction - Build the CloudEvent extensions using the array of extensionPatterns passed into the constructor.

  3. Format Conversion - Apply the specified EventFormat or, if not set, handle the conversion via Binary Format Mode.

A basic transformation may have the following pattern:

// Input message with headers
Message<byte[]> inputMessage = MessageBuilder
    .withPayload("Hello CloudEvents".getBytes(StandardCharsets.UTF_8))
    .withHeader(MessageHeaders.CONTENT_TYPE, "text/plain")
    .build();

ToCloudEventTransformer transformer = new ToCloudEventTransformer();

// Transform to CloudEvent
Object cloudEventMessage = transformer.transform(inputMessage);

EventFormats

The ToCloudEventTransformer uses formatting to serialize the CloudEvent into the message’s payload when the EventFormat is available, or uses Binary Format Mode otherwise. Set the EventFormat in one of two ways:

  1. Set the desired EventFormat.

  2. Set the eventFormatContentTypeExpression with an expression that resolves to a content type that EventFormatProvider can use to provide the required EventFormat. When the eventFormatContentTypeExpression is set and the EventFormatProvider returns null because it cannot find the EventFormat for the content type, the transformer throws a MessageTransformationException. Examples of content types that the eventFormatContentTypeExpression can resolve to that are accepted by the EventFormatProvider are:

    • application/cloudevents+json

    • application/cloudevents+xml

If the EventFormat and the eventFormatContentTypeExpression are not set, the transformer adds cloud event attributes and extensions to the message headers with the cloud event prefix (default is ce-) and leaves the payload unchanged (Binary Format Mode).

To utilize a specific EventFormat, add the associated dependency. For example, to add the XML EventFormat, add the following dependency: io.cloudevents:cloudevents-xml. See the CloudEvents Java Reference Documentation for information on the event formats that are available.

Ensure messages to be transformed to CloudEvents have a payload of type byte[]. The transformer throws an IllegalArgumentException if the payload is not a byte array.

FromCloudEventTransformer

Use the FromCloudEventTransformer to convert CloudEvents into Spring Integration messages. This transformer supports the CloudEvents specification v1.0 and processes CloudEvents from two payload types: CloudEvent objects or serialized CloudEvent byte arrays.

The transformer extracts CloudEvent data from the message payload and maps CloudEvent attributes along with CloudEvent extensions to message headers with a ce- prefix.

Supported Payload Types

The transformer accepts messages with the following payload types:

CloudEvent Object Type

When the message payload is a CloudEvent instance, the transformer:

  1. Extracts the CloudEvent data and uses it as the message payload.

  2. Maps CloudEvent attributes (id, source, type, time, subject, datacontenttype, dataschema) to message headers with a ce- prefix.

  3. Maps all CloudEvent extensions to message headers with the ce- prefix.

  4. Preserves all original message headers unless a header key matches a CloudEvent attribute or extension, in which case the original value is overwritten.

Example:

String orderJson = ...

CloudEvent cloudEvent = CloudEventBuilder.v1()
    .withId("event-123")
    .withSource(URI.create("/myapp/orders"))
    .withType("order.created")
    .withData("application/json", orderJson.getBytes())
    .withExtension("traceid", "trace-abc")
    .build();

Message<CloudEvent> inputMessage = MessageBuilder
    .withPayload(cloudEvent)
    .build();

FromCloudEventTransformer transformer = new FromCloudEventTransformer();
Message<?> outputMessage = transformer.transform(inputMessage);

The outputMessage from the example above produces output similar to the following:

GenericMessage [
    payload = byte[13],
    headers = {
        ce-source          = /myapp/orders,
        ce-datacontenttype = application/json,
        ce-type            = order.created,
        ce-id              = event-123,
        ce-traceid         = trace-abc,
        id                 = 2df76f27-d139-424c-19b6-80b64e4a33b0,
        contentType        = application/json,
        timestamp          = 1770667476433
    }
]

Serialized CloudEvent Type

When the message payload is a byte[] containing a serialized CloudEvent, the transformer:

  1. Uses the content-type header to resolve the appropriate EventFormat via EventFormatProvider.

  2. Deserializes the payload to a CloudEvent object using the resolved format.

  3. Follows the same steps enumerated in the CloudEvent Object Type section.

Information on supported content types is discussed in the EventFormats section.

FromCloudEventTransformer allows the user to set an EventFormat that will be used when the EventFormatProvider fails to find an EventFormat for the contentType header or if the message does not contain a contentType header. If not set and an EventFormat is not found by the EventFormatProvider, a MessageTransformationException will be thrown.

Example:

byte[] serializedCloudEvent = """
				{
					"specversion": "1.0",
					"id": "316b0cf3-0c4d-5858-6bd2-863a2042f442",
					"source": "/spring/testapp.jsonTransformerWithExtensions",
					"type": "spring.message",
					"subject": "test.subject",
					"datacontenttype": "text/plain",
					"time": "2026-01-30T08:53:06.099486-05:00",
					"traceid": "trace-123",
					"data": "Hello, World!"
				}
				""";

Message<byte[]> inputMessage = MessageBuilder
    .withPayload(serializedCloudEvent)
    .setHeader(MessageHeaders.CONTENT_TYPE, "application/cloudevents+json")
    .build();

FromCloudEventTransformer transformer = new FromCloudEventTransformer();
Message<?> outputMessage = transformer.transform(inputMessage);

The outputMessage from the example above produces output similar to the following:

GenericMessage [
    payload = byte[13],
    headers = {
        ce-source           = /spring/testapp.jsonTransformerWithExtensions,
        ce-datacontenttype  = text/plain,
        ce-subject          = test.subject,
        ce-type             = spring.message,
        ce-id               = 316b0cf3-0c4d-5858-6bd2-863a2042f442,
        ce-traceid          = trace-123,
        ce-time             = 2026-01-30T08:53:06.099486-05:00,
        id                  = 463c0878-a9cb-7269-a503-b4224088cd42,
        contentType         = text/plain,
        timestamp           = 1770392214225
    }
]

CloudEvent Attribute Mapping

The transformer maps CloudEvent attributes to message headers using the following CloudEventHeaders constants:

CloudEvent Attribute Message Header Key Required

id

ce-id

Yes

source

ce-source

Yes

type

ce-type

Yes

time

ce-time

No

subject

ce-subject

No

datacontenttype

ce-datacontenttype

No

dataschema

ce-dataschema

No

extensions

ce-{extensionName}

No

The contentType header in the output message is always set to the CloudEvent’s datacontenttype value.

Configuration with DSL

Use the CloudEvents factory to add the FromCloudEventTransformer to flows using the Java DSL.

@Bean
public FromCloudEventTransformer fromCloudEventTransformer() {
    return new FromCloudEventTransformer();
}

@Bean
public IntegrationFlow fromCloudEventFlow(FromCloudEventTransformer fromCloudEventTransformer) {
    return IntegrationFlows
        .from("cloudEventInputChannel")
        .transform(CloudEvents.fromCloudEventTransformer())
        .channel("messageOutputChannel")
        .get();
}