Spring-Modulith Events Externalizer that uses Spring Cloud Stream supporting both JSON and Avro serialization formats.
Add the following Maven dependency to your project:
<dependency>
<groupId>io.zenwave360.sdk</groupId>
<artifactId>spring-modulith-events-scs</artifactId>
<version>${spring-modulith-events-scs.version}</version>
</dependency>
Use @EnableSpringCloudStreamEventExternalization
annotation to enable Spring Cloud Stream event externalization in your Spring configuration:
@Configuration
@EnableSpringCloudStreamEventExternalization
public class SpringCloudStreamEventsConfig {
// Additional configurations (if needed)
}
This configuration ensures that, in addition to events annotated with @Externalized
, all events of type org.springframework.messaging.Message
with a header named SpringCloudStreamEventExternalizer.SPRING_CLOUD_STREAM_EVENT_HEADER
will be externalized and routed to their specified destination using the value of this header as the routing target.
Using the transactional event publication log requires serializing events to a format that can be stored in a database. Since the generic type of Message<?>
payload is lost when using the default JacksonEventSerializer
, this library adds an extra _class
field to preserve payload type information, allowing for complete deserialization to its original type.
This library provides support for POJO (JSON) and Avro serialization formats for Message<?>
payloads.
Avro serialization needs com.fasterxml.jackson.dataformat.avro.AvroMapper
class present in the classpath. In order to use Avro serialization, you need to add the following dependency to your project:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-avro</artifactId>
</dependency>
You can define routing targets programmatically using a Message header:
public class CustomerEventsProducer implements ICustomerEventsProducer {
private final ApplicationEventPublisher applicationEventPublisher;
public void onCustomerCreated(CustomerCreated event) {
Message<CustomerCreated> message = MessageBuilder.withPayload(event)
.setHeader(
SpringCloudStreamEventExternalizer.SPRING_CLOUD_STREAM_SENDTO_DESTINATION_HEADER,
"customer-created") // <- target binding name
.build();
applicationEventPublisher.publishEvent(message);
}
}
Leverage the @Externalized
annotation to define the target binding name and routing key:
@Externalized("customer-created::#{#this.getLastname()}")
class CustomerCreated {
public String getLastname() {
// Return the customer's last name
}
}
Configure Spring Cloud Stream destination for your bindings as usual in application.yml
:
spring:
cloud:
stream:
bindings:
customer-created:
destination: customer-created-topic
SpringCloudStreamEventExternalizer
dynamically sets the appropriate Message header (e.g., kafka_messageKey
or rabbit_routingKey
) from your routing key based on the channel binder type, if the routing header is not already present.
- KafkaMessageChannelBinder:
kafka_messageKey
- RabbitMessageChannelBinder:
rabbit_routingKey
- KinesisMessageChannelBinder:
partitionKey
- PubSubMessageChannelBinder:
pubsub_orderingKey
- EventHubsMessageChannelBinder:
partitionKey
- SolaceMessageChannelBinder:
solace_messageKey
- PulsarMessageChannelBinder:
pulsar_key
In order to test snapshot versions of this library, add the following repository to your Maven configuration:
<repository>
<id>gh</id>
<url>https://raw.githubusercontent.com/ZenWave360/maven-snapshots/refs/heads/main</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>