Skip to content

Commit a8835b2

Browse files
committed
GH-869 - Polishing.
Tweak header population to use the raw routing target. Expand test case to make sure it's retained as message header.
1 parent 41aad24 commit a8835b2

File tree

8 files changed

+45
-24
lines changed

8 files changed

+45
-24
lines changed

spring-modulith-bom/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@
9494
<artifactId>spring-modulith-events-kafka</artifactId>
9595
<version>1.3.0-SNAPSHOT</version>
9696
</dependency>
97+
<dependency>
98+
<groupId>org.springframework.modulith</groupId>
99+
<artifactId>spring-modulith-events-messaging</artifactId>
100+
<version>1.3.0-SNAPSHOT</version>
101+
</dependency>
97102
<dependency>
98103
<groupId>org.springframework.modulith</groupId>
99104
<artifactId>spring-modulith-events-mongodb</artifactId>

spring-modulith-events/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
<module>spring-modulith-events-jms</module>
2525
<module>spring-modulith-events-jpa</module>
2626
<module>spring-modulith-events-kafka</module>
27+
<module>spring-modulith-events-messaging</module>
2728
<module>spring-modulith-events-mongodb</module>
2829
<module>spring-modulith-events-neo4j</module>
29-
<module>spring-modulith-events-messaging</module>
3030
</modules>
3131

3232
<profiles>

spring-modulith-events/spring-modulith-events-api/src/main/java/org/springframework/modulith/events/RoutingTarget.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ RoutingTarget verify() {
174174
*/
175175
@Override
176176
public String toString() {
177-
return target + "::" + (key == null ? "" : key);
177+
return target + (key == null ? "" : "::" + key);
178178
}
179179

180180
/*

spring-modulith-events/spring-modulith-events-messaging/src/main/java/org/springframework/modulith/events/messaging/SpringMessagingEventExternalizerConfiguration.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,28 @@
3131
import org.springframework.messaging.support.MessageBuilder;
3232
import org.springframework.modulith.events.EventExternalizationConfiguration;
3333
import org.springframework.modulith.events.config.EventExternalizationAutoConfiguration;
34-
import org.springframework.modulith.events.support.BrokerRouting;
3534
import org.springframework.modulith.events.support.DelegatingEventExternalizer;
3635

3736
/**
3837
* Auto-configuration to set up a {@link DelegatingEventExternalizer} to externalize events to a Spring Messaging
39-
* {@link MessageChannel message channel}.
38+
* {@link MessageChannel}.
4039
*
4140
* @author Josh Long
41+
* @author Oliver Drotbohm
4242
*/
4343
@AutoConfiguration
4444
@AutoConfigureAfter(EventExternalizationAutoConfiguration.class)
4545
@ConditionalOnClass(MessageChannel.class)
46-
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled",
47-
havingValue = "true",
46+
@ConditionalOnProperty(name = "spring.modulith.events.externalization.enabled", havingValue = "true",
4847
matchIfMissing = true)
4948
class SpringMessagingEventExternalizerConfiguration {
5049

5150
private static final Logger logger = LoggerFactory.getLogger(SpringMessagingEventExternalizerConfiguration.class);
5251

53-
public static final String MODULITH_ROUTING_HEADER = "modulithRouting";
52+
public static final String MODULITH_ROUTING_HEADER = "springModulith_routingTarget";
5453

5554
@Bean
56-
DelegatingEventExternalizer springMessagingEventExternalizer(
57-
EventExternalizationConfiguration configuration,
55+
DelegatingEventExternalizer springMessagingEventExternalizer(EventExternalizationConfiguration configuration,
5856
BeanFactory factory) {
5957

6058
logger.debug("Registering domain event externalization for Spring Messaging…");
@@ -63,16 +61,19 @@ DelegatingEventExternalizer springMessagingEventExternalizer(
6361
context.setBeanResolver(new BeanFactoryResolver(factory));
6462

6563
return new DelegatingEventExternalizer(configuration, (target, payload) -> {
66-
var routing = BrokerRouting.of(target, context);
64+
65+
var targetChannel = target.getTarget();
6766
var message = MessageBuilder
6867
.withPayload(payload)
69-
.setHeader(MODULITH_ROUTING_HEADER, routing)
68+
.setHeader(MODULITH_ROUTING_HEADER, target.toString())
7069
.build();
70+
7171
if (logger.isDebugEnabled()) {
72-
logger.info("trying to find a {} with name {}", MessageChannel.class.getName(), routing.getTarget());
72+
logger.debug("trying to find a {} with name {}", MessageChannel.class.getName(), targetChannel);
7373
}
74-
var bean = factory.getBean(routing.getTarget(), MessageChannel.class);
75-
bean.send(message);
74+
75+
factory.getBean(targetChannel, MessageChannel.class).send(message);
76+
7677
return CompletableFuture.completedFuture(null);
7778
});
7879
}

spring-modulith-events/spring-modulith-events-messaging/src/test/java/org/springframework/modulith/events/messaging/SpringMessagingEventPublicationIntegrationTests.java

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023-2024 the original author or authors.
2+
* Copyright 2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
2929
import org.springframework.boot.test.context.SpringBootTest;
3030
import org.springframework.context.ApplicationEventPublisher;
3131
import org.springframework.context.annotation.Bean;
32-
import org.springframework.integration.core.GenericHandler;
3332
import org.springframework.integration.dsl.DirectChannelSpec;
3433
import org.springframework.integration.dsl.IntegrationFlow;
3534
import org.springframework.integration.dsl.MessageChannels;
@@ -42,12 +41,14 @@
4241
* Integration tests for Spring Messaging-based event publication.
4342
*
4443
* @author Josh Long
44+
* @author Oliver Drotbohm
45+
* @since 1.3
4546
*/
4647
@SpringBootTest
4748
class SpringMessagingEventPublicationIntegrationTests {
4849

50+
private static final String TARGET = "target::#{someExpression}";
4951
private static final String CHANNEL_NAME = "target";
50-
5152
private static final AtomicInteger COUNTER = new AtomicInteger();
5253

5354
@Autowired TestPublisher publisher;
@@ -62,12 +63,15 @@ TestPublisher testPublisher(ApplicationEventPublisher publisher) {
6263
}
6364

6465
@Bean
65-
IntegrationFlow inboundIntegrationFlow(
66-
@Qualifier(CHANNEL_NAME) MessageChannel inbound) {
66+
IntegrationFlow inboundIntegrationFlow(@Qualifier(CHANNEL_NAME) MessageChannel inbound) {
6767

6868
return IntegrationFlow
6969
.from(inbound)
70-
.handle((GenericHandler<TestEvent>) (payload, headers) -> {
70+
.handle((__, headers) -> {
71+
72+
assertThat(headers.get(SpringMessagingEventExternalizerConfiguration.MODULITH_ROUTING_HEADER))
73+
.isEqualTo(TARGET);
74+
7175
COUNTER.incrementAndGet();
7276
return null;
7377
})
@@ -83,16 +87,20 @@ DirectChannelSpec target() {
8387

8488
@Test
8589
void publishesEventToSpringMessaging() throws Exception {
90+
8691
var publishes = 2;
92+
8793
for (var i = 0; i < publishes; i++) {
8894
publisher.publishEvent();
8995
}
96+
9097
Thread.sleep(200);
98+
9199
assertThat(COUNTER.get()).isEqualTo(publishes);
92100
assertThat(completed.findAll()).hasSize(publishes);
93101
}
94102

95-
@Externalized(CHANNEL_NAME)
103+
@Externalized(TARGET)
96104
static class TestEvent {}
97105

98106
@RequiredArgsConstructor
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
spring.modulith.events.jdbc.schema-initialization.enabled=true
2+
spring.main.banner-mode=OFF

src/docs/antora/modules/ROOT/pages/appendix.adoc

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ a|* `spring-modulith-docs`
167167
|`spring-modulith-events-jms`|`runtime`|Event externalization support for JMS.
168168
|`spring-modulith-events-jpa`|`runtime`|A JPA-based implementation of the `EventPublicationRegistry`.
169169
|`spring-modulith-events-kafka`|`runtime`|Event externalization support for Kafka.
170+
|`spring-modulith-events-messaging`|`runtime`|Event externalization support into Spring Messaging ``MessageChannel``s.
170171
|`spring-modulith-events-mongodb`|`runtime`|A MongoDB-based implementation of the `EventPublicationRegistry`.
171172
|`spring-modulith-events-neo4j`|`runtime`|A Neo4j-based implementation of the `EventPublicationRegistry`.
172173
|`spring-modulith-junit`|`test`|Test execution optimizations based on the application module structure. Find more details xref:testing.adoc#change-aware-test-execution[here].

src/docs/antora/modules/ROOT/pages/events.adoc

+8-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ To keep application modules as decoupled as possible from each other, their prim
77
This avoids the originating module to know about all potentially interested parties, which is a key aspect to enable application module integration testing (see xref:testing.adoc[Integration Testing Application Modules]).
88

99
Often we will find application components defined like this:
10+
1011
[tabs]
1112
======
1213
Java::
@@ -124,6 +125,7 @@ class InventoryManagement {
124125
}
125126
----
126127
======
128+
127129
This now effectively decouples the original transaction from the execution of the listener.
128130
While this avoids the expansion of the original business transaction, it also creates a risk: if the listener fails for whatever reason, the event publication is lost, unless each listener actually implements its own safety net.
129131
Even worse, that doesn't even fully work, as the system might fail before the method is even invoked.
@@ -212,7 +214,9 @@ image::event-publication-registry-end.png[]
212214
[[publication-registry.starters]]
213215
=== Spring Boot Event Registry Starters
214216

215-
Using the transactional event publication log requires a combination of artifacts added to your application. To ease that task, Spring Modulith provides starter POMs that are centered around the <<publication-registry.publication-repositories, persistence technology>> to be used and default to the Jackson-based <<publication-registry.serialization, EventSerializer>> implementation. The following starters are available:
217+
Using the transactional event publication log requires a combination of artifacts added to your application.
218+
To ease that task, Spring Modulith provides starter POMs that are centered around the <<publication-registry.publication-repositories, persistence technology>> to be used and default to the Jackson-based <<publication-registry.serialization, EventSerializer>> implementation.
219+
The following starters are available:
216220

217221
[%header,cols="1,3,6"]
218222
|===
@@ -306,6 +310,7 @@ Spring Modulith provides a Jackson-based JSON implementation through the `spring
306310

307311
[[publication-registry.customize-publication-date]]
308312
=== Customizing the Event Publication Date
313+
309314
By default, the Event Publication Registry will use the date returned by the `Clock.systemUTC()` as event publication date.
310315
If you want to customize this, register a bean of type clock with the application context:
311316

@@ -372,7 +377,8 @@ When routing key is set, requires SNS to be configured as a FIFO topic with cont
372377
|Spring Messaging
373378
|`spring-modulith-events-messaging`
374379
|Uses Spring's core `Message` and `MessageChannel` support.
375-
Resolves the target `MessageChannel` by its bean name given the `target` in the `Externalized` annotation. Forwards routing information as a header - called `modulithRouting` - to be processed in whatever way by downstream components, typically in a Spring Integration `IntegrationFlow`.
380+
Resolves the target `MessageChannel` by its bean name given the `target` in the `Externalized` annotation.
381+
Forwards routing information as a header - called `springModulith_routingTarget` - to be processed in whatever way by downstream components, typically in a Spring Integration `IntegrationFlow`.
376382

377383
|===
378384

@@ -453,7 +459,6 @@ Kotlin::
453459
[[externalization.api]]
454460
=== Programmatic Event Externalization Configuration
455461

456-
457462
The `spring-modulith-events-api` artifact contains `EventExternalizationConfiguration` that allows developers to customize all of the above mentioned steps.
458463

459464
.Programmatically configuring event externalization

0 commit comments

Comments
 (0)