Skip to content

Commit 80dd083

Browse files
authored
Improved examples by improving output and demonstrating some use cases through tests. (apache#48)
1 parent c18ebd1 commit 80dd083

15 files changed

+432
-53
lines changed

dynamic-router-eip/README.adoc

+12
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ If you want to run the Dynamic Router in "allMatch" receiver mode, run the examp
110110

111111
The results should show up in less than ten seconds, and the program will immediately terminate.
112112

113+
=== Run Tests
114+
115+
You can run the tests using:
116+
117+
$mvn test
118+
119+
There are some demos that run during the test phase. Currently, there are three:
120+
121+
1. AllRecipientsApplicationTest: the recipient mode is set to "allMatch" and 1,000,000 messages are sent through the router.
122+
2. FirstRecipientApplicationTest: the recipient mode is set to "firstMatch" and 1,000,000 messages are sent through the router.
123+
3. LessExpectedApplicationTest: the recipient mode is set to "firstMatch", and 10,000 messages are sent through the router. The difference, here, is that the expected count is set to only 1,000 messages, so the results are calculated and displayed before all 10,000 messages are routed.
124+
113125
=== Help and contributions
114126

115127
If you hit any problem using Camel or have some feedback, then please

dynamic-router-eip/pom.xml

+15-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,21 @@
7676
<artifactId>spring-boot-configuration-processor</artifactId>
7777
<optional>true</optional>
7878
</dependency>
79-
79+
<dependency>
80+
<groupId>org.junit.jupiter</groupId>
81+
<artifactId>junit-jupiter-engine</artifactId>
82+
<scope>test</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.junit.platform</groupId>
86+
<artifactId>junit-platform-launcher</artifactId>
87+
<scope>test</scope>
88+
</dependency>
89+
<dependency>
90+
<groupId>org.springframework.boot</groupId>
91+
<artifactId>spring-boot-starter-test</artifactId>
92+
<scope>test</scope>
93+
</dependency>
8094
</dependencies>
8195

8296
<build>

dynamic-router-eip/src/main/java/org/apache/camel/example/springboot/numbers/config/DynamicRouterComponentConfig.java

+28
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,19 @@
1919
import org.apache.camel.ConsumerTemplate;
2020
import org.apache.camel.ProducerTemplate;
2121
import org.apache.camel.builder.RouteBuilder;
22+
import org.apache.camel.component.dynamicrouter.DynamicRouterConfiguration;
23+
import org.apache.camel.component.dynamicrouter.DynamicRouterConstants;
2224
import org.apache.camel.example.springboot.numbers.participants.PredicateConstants;
2325
import org.apache.camel.example.springboot.numbers.participants.RoutingParticipant;
2426
import org.apache.camel.example.springboot.numbers.service.ResultsService;
2527
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2628
import org.springframework.context.annotation.Bean;
2729
import org.springframework.context.annotation.Configuration;
2830

31+
import java.util.concurrent.CountDownLatch;
32+
2933
import static org.apache.camel.component.dynamicrouter.DynamicRouterConstants.COMPONENT_SCHEME;
34+
import static org.apache.camel.component.dynamicrouter.DynamicRouterConstants.MODE_FIRST_MATCH;
3035
import static org.apache.camel.example.springboot.numbers.participants.PredicateConstants.PREDICATE_EIGHTS;
3136
import static org.apache.camel.example.springboot.numbers.participants.PredicateConstants.PREDICATE_EVEN;
3237
import static org.apache.camel.example.springboot.numbers.participants.PredicateConstants.PREDICATE_FIVES;
@@ -78,6 +83,29 @@ public void configure() {
7883
};
7984
}
8085

86+
/**
87+
* Create a {@link CountDownLatch} so that we can wait on it for the total
88+
* expected number of messages to be received. Depending on the configured
89+
* value of {@link ExampleConfig#getRecipientMode()}, this latch will be
90+
* created with {@link ExampleConfig#getExpectedAllMatchMessageCount()} or
91+
* {@link ExampleConfig#getExpectedFirstMatchMessageCount()}.
92+
*
93+
* @see DynamicRouterConstants#MODE_ALL_MATCH
94+
* @see DynamicRouterConstants#MODE_FIRST_MATCH
95+
* @see DynamicRouterConfiguration#getRecipientMode()
96+
* @see ExampleConfig#getRecipientMode()
97+
* @see ExampleConfig#getExpectedAllMatchMessageCount()
98+
* @see ExampleConfig#getExpectedFirstMatchMessageCount()
99+
*
100+
* @return a countdown latch set to the number of expected messages
101+
*/
102+
@Bean
103+
CountDownLatch countDownLatch() {
104+
return new CountDownLatch(MODE_FIRST_MATCH.equals(exampleConfig.getRecipientMode()) ?
105+
exampleConfig.getExpectedFirstMatchMessageCount() :
106+
exampleConfig.getExpectedAllMatchMessageCount());
107+
}
108+
81109
/**
82110
* Create a {@link RoutingParticipant} that handles messages where the body is comprised of a number that is
83111
* a multiple of 10.

dynamic-router-eip/src/main/java/org/apache/camel/example/springboot/numbers/config/ExampleConfig.java

+82
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import org.springframework.boot.context.properties.ConfigurationProperties;
2020

21+
import java.util.concurrent.CountDownLatch;
22+
2123
/**
2224
* The config properties object from the application.yml file.
2325
*/
@@ -50,6 +52,33 @@ public class ExampleConfig {
5052
*/
5153
private String recipientMode;
5254

55+
/**
56+
* The number of messages to send.
57+
*/
58+
private int sendMessageCount;
59+
60+
/**
61+
* If the recipient mode is "firstMatch", then this is the number of
62+
* messages that are expected to be received. This value is also used
63+
* to create a {@link CountDownLatch} so that all messages can be
64+
* received before printing out messaging statistics.
65+
*/
66+
private int expectedFirstMatchMessageCount;
67+
68+
/**
69+
* If the recipient mode is "allMatch", then this is the number of
70+
* messages that are expected to be received. There is probably not an
71+
* easy way to calculate this number, so the number needs to be known
72+
* for a given {@link #sendMessageCount} value. This value is also used
73+
* to create a {@link CountDownLatch} so that all messages can be
74+
* received before printing out messaging statistics.
75+
*/
76+
private int expectedAllMatchMessageCount;
77+
78+
/**
79+
* The URI where messages will be sent to as the starting point for the
80+
* route that feeds the dynamic router.
81+
*/
5382
public String getStartUri() {
5483
return startUri;
5584
}
@@ -58,6 +87,9 @@ public void setStartUri(String startUri) {
5887
this.startUri = startUri;
5988
}
6089

90+
/**
91+
* The dynamic router channel.
92+
*/
6193
public String getRoutingChannel() {
6294
return routingChannel;
6395
}
@@ -66,6 +98,9 @@ public void setRoutingChannel(String routingChannel) {
6698
this.routingChannel = routingChannel;
6799
}
68100

101+
/**
102+
* The dynamic router control channel URI
103+
*/
69104
public String getSubscribeUri() {
70105
return subscribeUri;
71106
}
@@ -74,6 +109,9 @@ public void setSubscribeUri(String subscribeUri) {
74109
this.subscribeUri = subscribeUri;
75110
}
76111

112+
/**
113+
* The scheme that routing participants will use to listen for messages.
114+
*/
77115
public String getReceiverScheme() {
78116
return receiverScheme;
79117
}
@@ -82,11 +120,55 @@ public void setReceiverScheme(String receiverScheme) {
82120
this.receiverScheme = receiverScheme;
83121
}
84122

123+
/**
124+
* The recipient mode -- first matching filter only, or all matching filters.
125+
*/
85126
public String getRecipientMode() {
86127
return this.recipientMode;
87128
}
88129

89130
public void setRecipientMode(String recipientMode) {
90131
this.recipientMode = recipientMode;
91132
}
133+
134+
/**
135+
* The number of messages to send.
136+
*/
137+
public int getSendMessageCount() {
138+
return sendMessageCount;
139+
}
140+
141+
public void setSendMessageCount(int sendMessageCount) {
142+
this.sendMessageCount = sendMessageCount;
143+
}
144+
145+
/**
146+
* If the recipient mode is "firstMatch", then this is the number of
147+
* messages that are expected to be received. This value is also used
148+
* to create a {@link CountDownLatch} so that all messages can be
149+
* received before printing out messaging statistics.
150+
*/
151+
public int getExpectedFirstMatchMessageCount() {
152+
return expectedFirstMatchMessageCount;
153+
}
154+
155+
public void setExpectedFirstMatchMessageCount(int expectedFirstMatchMessageCount) {
156+
this.expectedFirstMatchMessageCount = expectedFirstMatchMessageCount;
157+
}
158+
159+
/**
160+
* If the recipient mode is "allMatch", then this is the number of
161+
* messages that are expected to be received. There is probably not an
162+
* easy way to calculate this number, so the number needs to be known
163+
* for a given {@link #sendMessageCount} value. This value is also used
164+
* to create a {@link CountDownLatch} so that all messages can be
165+
* received before printing out messaging statistics.
166+
*/
167+
public int getExpectedAllMatchMessageCount() {
168+
return expectedAllMatchMessageCount;
169+
}
170+
171+
public void setExpectedAllMatchMessageCount(int expectedAllMatchMessageCount) {
172+
this.expectedAllMatchMessageCount = expectedAllMatchMessageCount;
173+
}
92174
}

dynamic-router-eip/src/main/java/org/apache/camel/example/springboot/numbers/service/NumbersService.java

+34-21
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,19 @@
2323
import org.apache.camel.util.StopWatch;
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
26-
import org.springframework.boot.SpringApplication;
2726
import org.springframework.boot.context.event.ApplicationReadyEvent;
28-
import org.springframework.context.ApplicationContext;
2927
import org.springframework.context.event.EventListener;
3028
import org.springframework.stereotype.Service;
3129

30+
import java.text.NumberFormat;
3231
import java.util.List;
32+
import java.util.concurrent.CompletableFuture;
33+
import java.util.concurrent.CountDownLatch;
34+
import java.util.concurrent.Executors;
3335
import java.util.stream.IntStream;
3436

37+
import static java.util.concurrent.TimeUnit.*;
38+
3539
/**
3640
* Create numbers and send them to the dynamic router so that they can be
3741
* processed and binned to demonstrate the usage of the dynamic router
@@ -42,6 +46,8 @@ public class NumbersService {
4246

4347
private static final Logger LOG = LoggerFactory.getLogger(NumbersService.class);
4448

49+
private final NumberFormat numberFormat = NumberFormat.getIntegerInstance();
50+
4551
/**
4652
* The URI to send the messages to. This URI feeds the dynamic router in a
4753
* Camel route.
@@ -67,32 +73,37 @@ public class NumbersService {
6773
private final ResultsService resultsService;
6874

6975
/**
70-
* The Spring Boot {@link ApplicationContext} so that the app can be
71-
* programmatically shut down when we are finished processing all
72-
* messages and displaying results.
76+
* The {@link CountDownLatch} to wait for the total expected number of
77+
* messages to be received.
78+
*/
79+
final CountDownLatch countDownLatch;
80+
81+
/**
82+
* The number of messages to generate.
7383
*/
74-
private final ApplicationContext applicationContext;
84+
final int numberOfMessages;
7585

7686
/**
77-
* Create this service with all of the things.
87+
* Create this service with everything.
7888
*
79-
* @param config the configuration object representing the config properties
80-
* @param participants the dynamic router participants
81-
* @param start the producer template to send messages to the start endpoint
82-
* @param resultsService the service that compiles routing results
83-
* @param applicationContext the Spring app context for exiting when processing is complete
89+
* @param config the configuration object representing the config properties
90+
* @param participants the dynamic router participants
91+
* @param start the producer template to send messages to the start endpoint
92+
* @param resultsService the service that compiles routing results
93+
* @param countDownLatch the latch to wait for all messages to be received
8494
*/
8595
public NumbersService(
8696
final ExampleConfig config,
8797
final List<RoutingParticipant> participants,
8898
final ProducerTemplate start,
8999
final ResultsService resultsService,
90-
final ApplicationContext applicationContext) {
100+
final CountDownLatch countDownLatch) {
91101
this.startUri = config.getStartUri();
92102
this.participants = participants;
93103
this.start = start;
94104
this.resultsService = resultsService;
95-
this.applicationContext = applicationContext;
105+
this.countDownLatch = countDownLatch;
106+
this.numberOfMessages = config.getSendMessageCount();
96107
}
97108

98109
/**
@@ -101,21 +112,23 @@ public NumbersService(
101112
* display the results and exit the app.
102113
*/
103114
@EventListener(ApplicationReadyEvent.class)
104-
public void start() {
105-
LOG.info("Subscribing participants");
115+
public void start() throws InterruptedException {
116+
LOG.info("Subscribing {} participants", participants.size());
106117
participants.forEach(RoutingParticipant::subscribe);
107-
StopWatch watch = new StopWatch();
108-
LOG.info("Sending messages to the dynamic router");
109-
sendMessages();
118+
final StopWatch watch = new StopWatch();
119+
LOG.info("Sending {} messages to the dynamic router: {}", numberFormat.format(numberOfMessages), getStartUri());
120+
CompletableFuture.runAsync(this::sendMessages, Executors.newSingleThreadExecutor());
121+
if (!countDownLatch.await(1, MINUTES)) {
122+
LOG.warn("Statistics may be inaccurate, since the operation timed out");
123+
}
110124
LOG.info(resultsService.getStatistics(watch));
111-
SpringApplication.exit(applicationContext);
112125
}
113126

114127
/**
115128
* Sends the messages to the starting endpoint of the route.
116129
*/
117130
public void sendMessages() {
118-
IntStream.rangeClosed(1, 1000000).forEach(start::sendBody);
131+
IntStream.rangeClosed(1, numberOfMessages).forEach(start::sendBody);
119132
}
120133

121134
/**

0 commit comments

Comments
 (0)