Skip to content

Commit d76aa72

Browse files
committed
Add Java configuration and fix gateway mapping
Introduce Java-based configuration as an alternative to the existing XML configuration for the barrier sample application. Provide developers with a modern, type-safe approach to configuring the barrier pattern while maintaining backward compatibility. Java-based configuration will be the default. Allow user to specify either `java-config` or `xml-config` profile to determine how app is configured. Add three new `@Configuration` classes activated via profiles: - ClientConfiguration: Configure HTTP outbound gateway - ServerConfiguration: Implement complete barrier pattern flow - ErrorHandlingConfiguration: Handle error scenarios Fix barrier2 gateway parameter mapping by adding Spring Integration as the current XML configuration does not work. Add comprehensive Javadoc documentation in imperative voice for all configuration classes, explaining the barrier pattern implementation, message flows, and component interactions. Update README.md to document profile-based configuration selection (xml-config vs java-config) and provide commands for running error handling examples. Remove unused namespaces from XML files
1 parent 527cb55 commit d76aa72

File tree

12 files changed

+769
-27
lines changed

12 files changed

+769
-27
lines changed

basic/barrier/README.md

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ Barrier Sample
22
==============
33

44
This example demonstrates the use of a process barrier component to suspend a thread until some asynchronous operation
5-
completes. The first example uses an **HTTP Inbound Gateway**, splits the request, sends the splits to rabbitmq and then
6-
waits for
7-
the publisher confirms. Finally, the results are returned to the caller.
5+
completes. The first example uses an **HTTP Inbound Gateway**, splits the request, sends the splits to RabbitMQ and then
6+
waits for the publisher confirms. Finally, the results are returned to the caller.
87

98
The sample is a Spring Boot application that loads 2 contexts:
109

@@ -19,19 +18,35 @@ http -> splitter -> amqp
1918
2019
amqp(Acks) -> aggregator -> barrier (release)
2120
22-
qmqp(inbound) -> nullChannel
21+
amqp(inbound) -> nullChannel
2322
```
2423

2524
The last flow drains the messages and allows the auto-delete queue to be removed when the application is closed.
2625

26+
## Configuration Options
27+
28+
This sample supports both **XML-based** and **Java-based** Spring Integration configurations. You can select which configuration to use by setting the active profile in `application.properties`:
29+
30+
* `spring.profiles.active=xml-config` - Uses XML configuration files from `META-INF/spring/integration/`
31+
* `spring.profiles.active=java-config` - Uses Java `@Configuration` classes from the `configuration` package
32+
2733
## Running the sample
2834

35+
### Using Maven
36+
37+
$ mvn spring-boot:run
38+
39+
Or with a specific profile:
40+
41+
$ mvn spring-boot:run -Dspring-boot.run.arguments=--spring.profiles.active=java-config
42+
43+
### Using Gradle
2944

3045
$ gradlew :barrier:run
3146

3247
This will package the application and run it using the [Gradle Application Plugin](https://www.gradle.org/docs/current/userguide/application_plugin.html)
3348

34-
#### Using an IDE such as SpringSource Tool Suite™ (STS)
49+
### Using an IDE such as SpringSource Tool Suite™ (STS)
3550

3651
In STS (Eclipse), go to package **org.springframework.integration.samples.barrier**, right-click **Application** and select **Run as** --> **Java Application** (or Spring Boot Application).
3752

@@ -52,8 +67,14 @@ An aggregator is used to aggregate the results; if there are no errors, the resu
5267
errors occurred, an exception is sent to release the barrier; this is thrown to the caller and has all the consolidated
5368
results in a property.
5469

70+
#### Running the Error Handling Example
71+
5572
You can run this example from an IDE, such as STS using the technique above; in this case, the class is
56-
**ErrorHandlingApplication** in the **org.springframework.integration.samples.barrier** package.
73+
**ErrorHandlingApplication** in the **org.springframework.integration.samples.barrier2** package.
74+
75+
Or using Maven:
76+
77+
$ mvn spring-boot:run -Dspring-boot.run.main-class=org.springframework.integration.samples.barrier2.ErrorHandlingApplication
5778

5879
It sends a list of integers to the flow:
5980

basic/barrier/src/main/java/org/springframework/integration/samples/barrier/Application.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@
2525
import org.springframework.boot.builder.SpringApplicationBuilder;
2626
import org.springframework.context.ConfigurableApplicationContext;
2727
import org.springframework.context.annotation.ImportResource;
28+
import org.springframework.core.env.Environment;
2829

2930
/**
3031
* @author Gary Russell
32+
* @author Glenn Renfro
33+
*
3134
* @since 4.2
3235
*/
3336
@SpringBootApplication
@@ -37,11 +40,22 @@ public class Application {
3740
public static void main(String[] args) {
3841
ConfigurableApplicationContext server = SpringApplication.run(Application.class, args);
3942

40-
runClient(args);
41-
server.close();
43+
Environment env = server.getEnvironment();
44+
45+
// Get configurationType via profile
46+
String configurationType = env.getProperty("spring.profiles.active");
47+
System.out.println("Configuration-Type: " + configurationType);
48+
if (configurationType == null || configurationType.equals("xml-config")) {
49+
runClientWithXMLConfig(args);
50+
}
51+
else {
52+
RequestGateway requestGateway = server.getBean("requestGateway", RequestGateway.class);
53+
echoMessage(requestGateway);
54+
}
55+
System.exit(0);
4256
}
4357

44-
static void runClient(String[] args) {
58+
static void runClientWithXMLConfig(String[] args) {
4559
SpringApplication application = new SpringApplicationBuilder()
4660
.web(WebApplicationType.NONE)
4761
.bannerMode(Mode.OFF)
@@ -52,11 +66,15 @@ static void runClient(String[] args) {
5266
ConfigurableApplicationContext client = application.run(args);
5367

5468
RequestGateway requestGateway = client.getBean("requestGateway", RequestGateway.class);
69+
echoMessage(requestGateway);
70+
client.close();
71+
}
72+
73+
private static void echoMessage(RequestGateway requestGateway) {
5574
String request = "A,B,C";
5675
System.out.println("\n\n++++++++++++ Sending: " + request + " ++++++++++++\n");
5776
String reply = requestGateway.echo(request);
5877
System.out.println("\n\n++++++++++++ Replied with: " + reply + " ++++++++++++\n");
59-
client.close();
6078
}
6179

6280

basic/barrier/src/main/java/org/springframework/integration/samples/barrier/RequestGateway.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
*/
1616
package org.springframework.integration.samples.barrier;
1717

18+
import org.springframework.integration.annotation.MessagingGateway;
1819

1920
/**
2021
* @author Oleg Zhurakousky
2122
* @author Gunnar Hillert
23+
* @author Glenn Renfro
2224
*
2325
*/
26+
27+
@MessagingGateway(defaultRequestChannel = "requestChannel")
2428
public interface RequestGateway {
2529

2630
String echo(String request);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.springframework.integration.samples.barrier.configuration;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.context.annotation.Profile;
7+
import org.springframework.http.HttpMethod;
8+
import org.springframework.integration.channel.DirectChannel;
9+
import org.springframework.integration.dsl.IntegrationFlow;
10+
import org.springframework.integration.http.dsl.Http;
11+
import org.springframework.messaging.MessageChannel;
12+
13+
/**
14+
* Configure client-side Spring Integration flows for the Barrier pattern sample.
15+
* <p>
16+
* Define the integration flow for sending HTTP requests to the server endpoint.
17+
* Demonstrate how to configure an HTTP outbound gateway that sends POST requests
18+
* and waits for responses.
19+
* <p>
20+
* Activate this configuration using the "java-config" profile.
21+
*
22+
* @author Glenn Renfro
23+
*/
24+
@Configuration
25+
@Profile("java-config")
26+
public class ClientConfiguration {
27+
28+
/**
29+
* The URL endpoint of the server's HTTP inbound gateway.
30+
* Defaults to http://localhost:8080/postGateway if not configured.
31+
*/
32+
@Value("${barrier.url:http://localhost:8080/postGateway}")
33+
private String url;
34+
35+
/**
36+
* Define the main client integration flow.
37+
* <p>
38+
* Receive messages from the {@link #requestChannel()} and send them
39+
* via HTTP POST to the configured server URL. Wait for and return
40+
* the HTTP response as a String.
41+
*
42+
* @return the integration flow definition
43+
*/
44+
@Bean
45+
public IntegrationFlow clientFlow() {
46+
return IntegrationFlow.from(requestChannel())
47+
.handle(Http.outboundGateway(url)
48+
.httpMethod(HttpMethod.POST)
49+
.expectedResponseType(String.class))
50+
.get();
51+
}
52+
53+
/**
54+
* Create the request channel that feeds messages into the client flow.
55+
* <p>
56+
* Use a direct channel that provides point-to-point semantics,
57+
* delivering messages to a single subscriber.
58+
*
59+
* @return a new DirectChannel instance
60+
*/
61+
@Bean
62+
public MessageChannel requestChannel() {
63+
return new DirectChannel();
64+
}
65+
66+
}

0 commit comments

Comments
 (0)