├── .DS_Store
├── .gitignore
├── .mvn
└── wrapper
│ └── maven-wrapper.properties
├── README.md
├── helloworld
├── .springBeans
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── springframework
│ │ └── amqp
│ │ └── helloworld
│ │ ├── BrokerConfigurationApplication.java
│ │ ├── Consumer.java
│ │ ├── HelloWorldConfiguration.java
│ │ ├── Producer.java
│ │ └── async
│ │ ├── Consumer.java
│ │ ├── ConsumerConfiguration.java
│ │ ├── HelloWorldHandler.java
│ │ ├── Producer.java
│ │ └── ProducerConfiguration.java
│ └── resources
│ ├── log4j2.xml
│ └── rabbitConfiguration.xml
├── log4j2
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── springframework
│ │ └── amqp
│ │ └── samples
│ │ └── log4j2
│ │ └── SpringBootAmqpAppenderApplication.java
│ └── resources
│ └── log4j2.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
├── rabbitmq-tutorials
└── README.md
├── spring-rabbit-confirms-returns
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.adoc
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── amqp
│ │ │ └── samples
│ │ │ └── confirms
│ │ │ └── SpringRabbitConfirmsReturnsApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── org
│ └── springframework
│ └── amqp
│ └── samples
│ └── confirms
│ └── SpringRabbitConfirmsReturnsApplicationTests.java
├── spring-rabbit-global-errorhandler
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.adoc
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── amqp
│ │ │ └── samples
│ │ │ └── errorhandler
│ │ │ └── Application.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── org
│ └── springframework
│ └── amqp
│ └── samples
│ └── errorhandler
│ └── ApplicationTests.java
├── spring-rabbit-json
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.adoc
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── amqp
│ │ │ └── samples
│ │ │ └── json
│ │ │ └── Application.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── org
│ └── springframework
│ └── amqp
│ └── samples
│ └── json
│ └── ApplicationTests.java
├── spring-rabbit-streams
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.adoc
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── amqp
│ │ │ └── samples
│ │ │ └── streams
│ │ │ └── SpringRabbitStreamsApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── org
│ └── springframework
│ └── amqp
│ └── samples
│ └── streams
│ └── SpringRabbitStreamsApplicationTests.java
└── stocks
├── .DS_Store
├── pom.xml
└── src
├── main
├── java
│ └── org
│ │ └── springframework
│ │ └── amqp
│ │ └── rabbit
│ │ └── stocks
│ │ ├── config
│ │ ├── AbstractStockAppRabbitConfiguration.java
│ │ ├── RoutingKey.java
│ │ ├── client
│ │ │ └── RabbitClientConfiguration.java
│ │ └── server
│ │ │ └── RabbitServerConfiguration.java
│ │ ├── domain
│ │ ├── Quote.java
│ │ ├── Stock.java
│ │ ├── StockExchange.java
│ │ ├── TradeRequest.java
│ │ └── TradeResponse.java
│ │ ├── gateway
│ │ ├── MarketDataGateway.java
│ │ ├── RabbitMarketDataGateway.java
│ │ ├── RabbitStockServiceGateway.java
│ │ └── StockServiceGateway.java
│ │ ├── handler
│ │ ├── ClientHandler.java
│ │ └── ServerHandler.java
│ │ ├── service
│ │ ├── CreditCheckService.java
│ │ ├── ExecutionVenueService.java
│ │ ├── TradingService.java
│ │ └── stubs
│ │ │ ├── CreditCheckServiceStub.java
│ │ │ ├── ExecutionVenueServiceStub.java
│ │ │ └── TradingServiceStub.java
│ │ ├── ui
│ │ ├── StockController.java
│ │ └── StockPanel.java
│ │ └── web
│ │ └── QuoteController.java
├── resources
│ ├── client-bootstrap-config.xml
│ ├── client-handlers.xml
│ ├── client-messaging.xml
│ ├── client.properties
│ ├── log4j2.xml
│ ├── server-bootstrap-config.xml
│ ├── server-handlers.xml
│ ├── server-jmx.xml
│ ├── server-messaging.xml
│ ├── server-services.xml
│ ├── servlet-config.xml
│ └── static
│ │ ├── css
│ │ ├── colors.css
│ │ ├── local.css
│ │ └── main.css
│ │ ├── images
│ │ ├── ajax-loader.gif
│ │ ├── delete.png
│ │ ├── favicon.ico
│ │ ├── footer-left.png
│ │ ├── footer-right.png
│ │ ├── footer-stretch.png
│ │ ├── header-left.png
│ │ ├── header-right.png
│ │ ├── header-stretch.png
│ │ ├── help.png
│ │ ├── issues.gif
│ │ ├── module-icon.png
│ │ ├── powered-by-spring.png
│ │ ├── primary-item-background.png
│ │ ├── primary-menu-stretch.png
│ │ ├── primary-wrapper-left.png
│ │ ├── primary-wrapper-right.png
│ │ ├── springsource_logo.png
│ │ ├── table-header-background.png
│ │ ├── table-header-bottom-background.png
│ │ └── table-header-top-background.png
│ │ └── js
│ │ ├── jquery.min.js
│ │ └── jquery.mustache.js
└── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
└── test
├── java
└── org
│ └── springframework
│ └── amqp
│ └── rabbit
│ └── stocks
│ ├── Client.java
│ ├── Server.java
│ └── web
│ └── ServletConfigurationTests.java
└── resources
└── test.yaml
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | bin
3 | .classpath
4 | .project
5 | .settings
6 | .springBeans
7 | .ant-targets-build.xml
8 | src/ant/.ant-targets-upload-dist.xml
9 | *.swp
10 | */src/main/java/META-INF
11 | */src/main/webapp/META-INF
12 | erl_crash.dump
13 | nohup.out
14 | jredis.log
15 | .idea
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .sts4-cache
20 | .factorypath
21 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This project hosts some samples that complement [Spring AMQP](https://github.com/SpringSource/spring-amqp), showing you how to get started with Spring and AMQP.
2 |
3 | # Build Instructions #
4 |
5 | Install the [RabbitMQ](https://www.rabbitmq.com) broker first (version
6 | 2.3.1 or better). Then clone from GIT and then use Maven (2.1.*):
7 |
8 | $ git clone ...
9 | $ mvn install
10 |
11 | SpringSource ToolSuite users (or Eclipse users with the latest
12 | m2eclipse plugin) can import the projects as existing Maven projects.
13 |
14 | The basic HelloWorld sample has two versions (with synchronous and
15 | asynchronous consumers). Both have two Java classes called `Producer`
16 | and `Consumer` with main methods to launch. Run the producer first
17 | and ensure that the broker is already running.
18 |
19 | The Stocks sample has a UI that can be launched as a Java main, and a
20 | daemon server process with the same properties. You can run them from
21 | an IDE easily. Run the `Server` and then the `Client` and you should
22 | see a swing client pop up and stock tickers appearing. To run from
23 | the command line you can use the Maven exec plugin:
24 |
25 | $ mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass=org.springframework.amqp.rabbit.stocks.Server &
26 | $ mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass=org.springframework.amqp.rabbit.stocks.Client
27 |
28 | In the example above we backgrounded the server process, or you could
29 | run it in a different window to make things clearer in the console
30 | logs.
31 |
32 | ## Web UI
33 |
34 | The Stocks sample is also a web application. You should be able to run it in your IDE, e.g. if you imported the project into STS (or Eclipse with Maven support) you can drag it onto a server, or use `Run As...->On Server`. From the command line you can use
35 |
36 | $ mvn jetty:run
37 |
38 | The web UI is designed like the swing client - it has a ticker table
39 | that updates every second (if there is any new data), and an order
40 | entry form. The `QuoteController` manages the interaction between the
41 | browser and the application and between the application and the AMQP
42 | broker.
43 |
44 | ## RabbitMQ Tutorials
45 |
46 | Spring Boot versions of the [6 standard RabbitMQ tutorials](https://www.rabbitmq.com/getstarted.html) are provided in `rabbitmq-tutorials`.
47 |
48 | ## Spring Boot Applications
49 |
50 | Several Spring Boot applications are also provided, with names `spring-rabbit-...`.
51 | Explore their individual READMEs for more information.
52 |
53 | # Contributing to Spring AMQP Samples
54 |
55 | Here are some ways for you to get involved in the community:
56 |
57 | * Get involved with the Spring community on the Spring Community Forums. Please help out on the [forum](https://forum.spring.io/) by responding to questions and joining the debate.
58 | * Create [JIRA](https://jira.springsource.org/browse/AMQP) tickets for bugs and new features and comment and vote on the ones that you are interested in.
59 | * Github is for social coding: if you want to write code, we encourage contributions through pull requests from [forks of this repository](https://help.github.com/forking/). If you want to contribute code this way, please reference a JIRA ticket as well covering the specific issue you are addressing.
60 | * Watch for upcoming articles on Spring by [subscribing](https://www.springsource.org/node/feed) to springframework.org
61 |
62 | Refer to the spring-amqp [Contributor's Guidelines](https://github.com/spring-projects/spring-amqp/blob/master/CONTRIBUTING.adoc) for complete information about the necessary steps.
63 |
64 | ## Code Conventions and Housekeeping
65 | None of these is essential for a pull request, but they will all help. They can also be added after the original pull request but before a merge.
66 |
67 | * Use the Spring Framework code format conventions (import `eclipse-code-formatter.xml` from the root of the project if you are using Eclipse).
68 | * Make sure all new .java files to have a simple Javadoc class comment with at least an @author tag identifying you, and preferably at least a paragraph on what the class is for.
69 | * Add the ASF license header comment to all new .java files (copy from existing files in the project)
70 | * Add yourself as an @author to the .java files that you modify substantially (more than cosmetic changes).
71 | * Add some Javadocs and, if you change the namespace, some XSD doc elements (Spring AMQP is not stellar in this area yet, but it will have to come up to scratch one day, so you will be helping a lot).
72 | * A few unit tests would help a lot as well - someone has to do it.
73 | * If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project).
74 |
--------------------------------------------------------------------------------
/helloworld/.springBeans:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1
4 |
5 |
6 |
7 |
8 |
9 |
10 | src/main/resources/rabbitConfiguration.xml
11 |
12 |
13 |
14 |
15 | true
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/helloworld/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | org.springframework.samples.spring
7 | spring-rabbit-helloworld
8 | 3.2.0
9 | jar
10 | Spring AMQP Hello World
11 | https://www.spring.io
12 |
13 |
16 |
17 |
18 | true
19 | ${project.version}
20 | UTF-8
21 | 17
22 | false
23 |
24 |
25 |
26 |
27 | org.springframework.amqp
28 | spring-rabbit
29 | ${spring-amqp.version}
30 |
31 |
32 |
33 | org.apache.logging.log4j
34 | log4j-jcl
35 | 2.12.0
36 | runtime
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | maven-assembly-plugin
46 | false
47 |
48 |
49 | project
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.apache.maven.plugins
58 | maven-compiler-plugin
59 | 3.8.1
60 |
61 | 17
62 | 17
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-surefire-plugin
68 | 2.22.2
69 |
70 |
71 |
72 | **/*Tests.java
73 |
74 |
75 | **/Abstract*.java
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/BrokerConfigurationApplication.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld;
2 |
3 | import org.springframework.amqp.core.AmqpAdmin;
4 | import org.springframework.amqp.core.Queue;
5 | import org.springframework.context.ApplicationContext;
6 | import org.springframework.context.support.ClassPathXmlApplicationContext;
7 |
8 | public class BrokerConfigurationApplication {
9 |
10 | /**
11 | * An example application that only configures the AMQP broker
12 | */
13 | public static void main(String[] args) throws Exception {
14 | ApplicationContext context = new ClassPathXmlApplicationContext("rabbitConfiguration.xml");
15 | AmqpAdmin amqpAdmin = context.getBean(AmqpAdmin.class);
16 | Queue helloWorldQueue = new Queue("hello.world.queue");
17 |
18 | amqpAdmin.declareQueue(helloWorldQueue);
19 |
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/Consumer.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld;
2 |
3 | import org.springframework.amqp.core.AmqpTemplate;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
6 |
7 | public class Consumer {
8 |
9 | public static void main(String[] args) {
10 | ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
11 | AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
12 | System.out.println("Received: " + amqpTemplate.receiveAndConvert());
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/HelloWorldConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld;
2 |
3 | import org.springframework.amqp.core.AmqpAdmin;
4 | import org.springframework.amqp.core.Queue;
5 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
6 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
7 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
8 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
9 | import org.springframework.context.annotation.Bean;
10 | import org.springframework.context.annotation.Configuration;
11 |
12 | @Configuration
13 | public class HelloWorldConfiguration {
14 |
15 | protected final String helloWorldQueueName = "hello.world.queue";
16 |
17 | @Bean
18 | public ConnectionFactory connectionFactory() {
19 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
20 | connectionFactory.setUsername("guest");
21 | connectionFactory.setPassword("guest");
22 | return connectionFactory;
23 | }
24 |
25 | @Bean
26 | public AmqpAdmin amqpAdmin() {
27 | return new RabbitAdmin(connectionFactory());
28 | }
29 |
30 | @Bean
31 | public RabbitTemplate rabbitTemplate() {
32 | RabbitTemplate template = new RabbitTemplate(connectionFactory());
33 | //The routing key is set to the name of the queue by the broker for the default exchange.
34 | template.setRoutingKey(this.helloWorldQueueName);
35 | //Where we will synchronously receive messages from
36 | template.setDefaultReceiveQueue(this.helloWorldQueueName);
37 | return template;
38 | }
39 |
40 | @Bean
41 | // Every queue is bound to the default direct exchange
42 | public Queue helloWorldQueue() {
43 | return new Queue(this.helloWorldQueueName);
44 | }
45 |
46 | /*
47 | @Bean
48 | public Binding binding() {
49 | return declare(new Binding(helloWorldQueue(), defaultDirectExchange()));
50 | }*/
51 |
52 | /*
53 | @Bean
54 | public TopicExchange helloExchange() {
55 | return declare(new TopicExchange("hello.world.exchange"));
56 | }*/
57 |
58 | /*
59 | public Queue declareUniqueQueue(String namePrefix) {
60 | Queue queue = new Queue(namePrefix + "-" + UUID.randomUUID());
61 | rabbitAdminTemplate().declareQueue(queue);
62 | return queue;
63 | }
64 |
65 | // if the default exchange isn't configured to your liking....
66 | @Bean Binding declareP2PBinding(Queue queue, DirectExchange exchange) {
67 | return declare(new Binding(queue, exchange, queue.getName()));
68 | }
69 |
70 | @Bean Binding declarePubSubBinding(String queuePrefix, FanoutExchange exchange) {
71 | return declare(new Binding(declareUniqueQueue(queuePrefix), exchange));
72 | }
73 |
74 | @Bean Binding declarePubSubBinding(UniqueQueue uniqueQueue, TopicExchange exchange) {
75 | return declare(new Binding(uniqueQueue, exchange));
76 | }
77 |
78 | @Bean Binding declarePubSubBinding(String queuePrefix, TopicExchange exchange, String routingKey) {
79 | return declare(new Binding(declareUniqueQueue(queuePrefix), exchange, routingKey));
80 | }*/
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/Producer.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld;
2 |
3 | import org.springframework.amqp.core.AmqpTemplate;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
6 |
7 | public class Producer {
8 |
9 | public static void main(String[] args) {
10 | ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
11 | AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
12 | amqpTemplate.convertAndSend("Hello World");
13 | System.out.println("Sent: Hello World");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/async/Consumer.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld.async;
2 |
3 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4 |
5 | public class Consumer {
6 |
7 | public static void main(String[] args) {
8 | new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/async/ConsumerConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld.async;
2 |
3 | import org.springframework.amqp.helloworld.HelloWorldConfiguration;
4 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
5 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | @Configuration
10 | public class ConsumerConfiguration extends HelloWorldConfiguration {
11 |
12 | @Bean
13 | public SimpleMessageListenerContainer listenerContainer() {
14 | SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
15 | container.setConnectionFactory(connectionFactory());
16 | container.setQueueNames(this.helloWorldQueueName);
17 | container.setMessageListener(new MessageListenerAdapter(new HelloWorldHandler()));
18 | return container;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/async/HelloWorldHandler.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld.async;
2 |
3 | public class HelloWorldHandler {
4 |
5 | public void handleMessage(String text) {
6 | System.out.println("Received: " + text);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/async/Producer.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld.async;
2 |
3 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
4 |
5 | public class Producer {
6 |
7 | public static void main(String[] args) throws Exception {
8 | new AnnotationConfigApplicationContext(ProducerConfiguration.class);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/helloworld/src/main/java/org/springframework/amqp/helloworld/async/ProducerConfiguration.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.helloworld.async;
2 |
3 | import java.util.concurrent.atomic.AtomicInteger;
4 |
5 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
6 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
7 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.config.BeanPostProcessor;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.scheduling.annotation.Scheduled;
13 | import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
14 |
15 | @Configuration
16 | public class ProducerConfiguration {
17 |
18 | protected final String helloWorldQueueName = "hello.world.queue";
19 |
20 | @Bean
21 | public RabbitTemplate rabbitTemplate() {
22 | RabbitTemplate template = new RabbitTemplate(connectionFactory());
23 | template.setRoutingKey(this.helloWorldQueueName);
24 | return template;
25 | }
26 |
27 | @Bean
28 | public ConnectionFactory connectionFactory() {
29 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
30 | connectionFactory.setUsername("guest");
31 | connectionFactory.setPassword("guest");
32 | return connectionFactory;
33 | }
34 |
35 | @Bean
36 | public ScheduledProducer scheduledProducer() {
37 | return new ScheduledProducer();
38 | }
39 |
40 | @Bean
41 | public BeanPostProcessor postProcessor() {
42 | return new ScheduledAnnotationBeanPostProcessor();
43 | }
44 |
45 |
46 | static class ScheduledProducer {
47 |
48 | @Autowired
49 | private volatile RabbitTemplate rabbitTemplate;
50 |
51 | private final AtomicInteger counter = new AtomicInteger();
52 |
53 | @Scheduled(fixedRate = 3000)
54 | public void sendMessage() {
55 | rabbitTemplate.convertAndSend("Hello World " + counter.incrementAndGet());
56 | }
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/helloworld/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/helloworld/src/main/resources/rabbitConfiguration.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/log4j2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.amqp.samples
7 | log4j2
8 | 3.2.0
9 | jar
10 |
11 | log4j2
12 | Spring Boot with Spring AMQP Log4J2 Appender
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 3.4.0
18 |
19 |
20 |
21 |
22 | UTF-8
23 | 17
24 | ${project.version}
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-amqp
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-logging
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-log4j2
42 |
43 |
44 |
45 | org.springframework
46 | spring-jcl
47 |
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-test
52 | test
53 |
54 |
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-maven-plugin
61 |
62 |
63 |
64 |
65 |
66 |
67 | spring-snapshots
68 | Spring Snapshots
69 | https://repo.spring.io/snapshot
70 |
71 | true
72 |
73 |
74 |
75 |
76 |
77 | spring-snapshots
78 | Spring Snapshots
79 | https://repo.spring.io/snapshot
80 |
81 | true
82 |
83 |
84 |
85 | spring-milestones
86 | Spring Milestones
87 | https://repo.spring.io/milestone
88 |
89 | false
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/log4j2/src/main/java/org/springframework/amqp/samples/log4j2/SpringBootAmqpAppenderApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.samples.log4j2;
18 |
19 | import java.io.IOException;
20 | import java.util.Date;
21 |
22 | import org.apache.commons.logging.Log;
23 | import org.apache.commons.logging.LogFactory;
24 |
25 | import org.springframework.amqp.core.ExchangeTypes;
26 | import org.springframework.amqp.rabbit.annotation.Exchange;
27 | import org.springframework.amqp.rabbit.annotation.QueueBinding;
28 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
29 | import org.springframework.boot.SpringApplication;
30 | import org.springframework.boot.autoconfigure.SpringBootApplication;
31 | import org.springframework.context.ConfigurableApplicationContext;
32 | import org.springframework.scheduling.annotation.EnableScheduling;
33 | import org.springframework.scheduling.annotation.Scheduled;
34 |
35 | /**
36 | * @author Artem Bilan
37 | * @since 1.6
38 | */
39 | @SpringBootApplication
40 | @EnableScheduling
41 | public class SpringBootAmqpAppenderApplication {
42 |
43 | private static final Log logger = LogFactory.getLog(SpringBootAmqpAppenderApplication.class);
44 |
45 | public static void main(String[] args) throws IOException {
46 | ConfigurableApplicationContext ctx = SpringApplication.run(SpringBootAmqpAppenderApplication.class, args);
47 | System.out.println("Hit 'Enter' to terminate");
48 | System.in.read();
49 | ctx.close();
50 | }
51 |
52 | @Scheduled(fixedDelay = 1000, initialDelay = 2000)
53 | public void generateLog() {
54 | logger.info("Log via AmqpAppender: " + new Date());
55 | }
56 |
57 | @RabbitListener(bindings = @QueueBinding(
58 | exchange = @Exchange(value = "log4j2Sample", type = ExchangeTypes.FANOUT),
59 | value = @org.springframework.amqp.rabbit.annotation.Queue))
60 | public void echoLogs(String logMessage) {
61 | System.out.println("Logs over Log4J AmqpAppender: " + logMessage);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/log4j2/src/main/resources/log4j2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | <# : batch portion
2 | @REM ----------------------------------------------------------------------------
3 | @REM Licensed to the Apache Software Foundation (ASF) under one
4 | @REM or more contributor license agreements. See the NOTICE file
5 | @REM distributed with this work for additional information
6 | @REM regarding copyright ownership. The ASF licenses this file
7 | @REM to you under the Apache License, Version 2.0 (the
8 | @REM "License"); you may not use this file except in compliance
9 | @REM with the License. You may obtain a copy of the License at
10 | @REM
11 | @REM http://www.apache.org/licenses/LICENSE-2.0
12 | @REM
13 | @REM Unless required by applicable law or agreed to in writing,
14 | @REM software distributed under the License is distributed on an
15 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | @REM KIND, either express or implied. See the License for the
17 | @REM specific language governing permissions and limitations
18 | @REM under the License.
19 | @REM ----------------------------------------------------------------------------
20 |
21 | @REM ----------------------------------------------------------------------------
22 | @REM Apache Maven Wrapper startup batch script, version 3.3.2
23 | @REM
24 | @REM Optional ENV vars
25 | @REM MVNW_REPOURL - repo url base for downloading maven distribution
26 | @REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
27 | @REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
28 | @REM ----------------------------------------------------------------------------
29 |
30 | @IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
31 | @SET __MVNW_CMD__=
32 | @SET __MVNW_ERROR__=
33 | @SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
34 | @SET PSModulePath=
35 | @FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
36 | IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
37 | )
38 | @SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
39 | @SET __MVNW_PSMODULEP_SAVE=
40 | @SET __MVNW_ARG0_NAME__=
41 | @SET MVNW_USERNAME=
42 | @SET MVNW_PASSWORD=
43 | @IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
44 | @echo Cannot start maven from wrapper >&2 && exit /b 1
45 | @GOTO :EOF
46 | : end batch / begin powershell #>
47 |
48 | $ErrorActionPreference = "Stop"
49 | if ($env:MVNW_VERBOSE -eq "true") {
50 | $VerbosePreference = "Continue"
51 | }
52 |
53 | # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
54 | $distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
55 | if (!$distributionUrl) {
56 | Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
57 | }
58 |
59 | switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
60 | "maven-mvnd-*" {
61 | $USE_MVND = $true
62 | $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
63 | $MVN_CMD = "mvnd.cmd"
64 | break
65 | }
66 | default {
67 | $USE_MVND = $false
68 | $MVN_CMD = $script -replace '^mvnw','mvn'
69 | break
70 | }
71 | }
72 |
73 | # apply MVNW_REPOURL and calculate MAVEN_HOME
74 | # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
75 | if ($env:MVNW_REPOURL) {
76 | $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
77 | $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
78 | }
79 | $distributionUrlName = $distributionUrl -replace '^.*/',''
80 | $distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
81 | $MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
82 | if ($env:MAVEN_USER_HOME) {
83 | $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
84 | }
85 | $MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
86 | $MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
87 |
88 | if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
89 | Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
90 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
91 | exit $?
92 | }
93 |
94 | if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
95 | Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
96 | }
97 |
98 | # prepare tmp dir
99 | $TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
100 | $TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
101 | $TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
102 | trap {
103 | if ($TMP_DOWNLOAD_DIR.Exists) {
104 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
105 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
106 | }
107 | }
108 |
109 | New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
110 |
111 | # Download and Install Apache Maven
112 | Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
113 | Write-Verbose "Downloading from: $distributionUrl"
114 | Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
115 |
116 | $webclient = New-Object System.Net.WebClient
117 | if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
118 | $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
119 | }
120 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
121 | $webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
122 |
123 | # If specified, validate the SHA-256 sum of the Maven distribution zip file
124 | $distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
125 | if ($distributionSha256Sum) {
126 | if ($USE_MVND) {
127 | Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
128 | }
129 | Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
130 | if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
131 | Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
132 | }
133 | }
134 |
135 | # unzip and move
136 | Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
137 | Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
138 | try {
139 | Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
140 | } catch {
141 | if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
142 | Write-Error "fail to move MAVEN_HOME"
143 | }
144 | } finally {
145 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
146 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
147 | }
148 |
149 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
150 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.springframework.amqp
5 | spring-amqp-samples
6 | Spring AMQP Samples
7 | 3.2.0
8 | pom
9 |
10 | helloworld
11 | stocks
12 | log4j2
13 | spring-rabbit-confirms-returns
14 | spring-rabbit-json
15 | spring-rabbit-global-errorhandler
16 | spring-rabbit-streams
17 |
18 |
19 | UTF-8
20 |
21 |
22 |
23 | https://github.com/SpringSource/spring-amqp-samples
24 | scm:git:git://github.com/SpringSource/spring-amqp-samples.git
25 | scm:git:git://github.com/SpringSource/spring-amqp-samples.git
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/rabbitmq-tutorials/README.md:
--------------------------------------------------------------------------------
1 | # RabbitMQ Tutorial Sample Application
2 |
3 | We are pleased to announce that the Spring AMQP implementations of the [6 RabbitMQ Tutorials][1] are now integrated into that site along with other implementations.
4 |
5 | [1]: https://www.rabbitmq.com/getstarted.html
6 |
7 | For each tutorial, click the `Spring AMQP` link.
8 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/spring-rabbit-confirms-returns/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
2 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/README.adoc:
--------------------------------------------------------------------------------
1 | # Configuring for Publisher Confirms and Returns
2 |
3 | This sample demonstrates how to use publisher confirms and returns.
4 |
5 | It uses an auto-delete queue that will be removed after the demo completes.
6 |
7 | It is a Spring Boot application and can be run with normal boot run methods, e.g.: `./mvnw spring-boot:run`
8 |
9 | It shows how to use the `Future` to wait for a delivery confirmation or returned message.
10 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | #
58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look
59 | # for the new JDKs provided by Oracle.
60 | #
61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
62 | #
63 | # Apple JDKs
64 | #
65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
66 | fi
67 |
68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
69 | #
70 | # Apple JDKs
71 | #
72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
73 | fi
74 |
75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
76 | #
77 | # Oracle JDKs
78 | #
79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
80 | fi
81 |
82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
83 | #
84 | # Apple JDKs
85 | #
86 | export JAVA_HOME=`/usr/libexec/java_home`
87 | fi
88 | ;;
89 | esac
90 |
91 | if [ -z "$JAVA_HOME" ] ; then
92 | if [ -r /etc/gentoo-release ] ; then
93 | JAVA_HOME=`java-config --jre-home`
94 | fi
95 | fi
96 |
97 | if [ -z "$M2_HOME" ] ; then
98 | ## resolve links - $0 may be a link to maven's home
99 | PRG="$0"
100 |
101 | # need this for relative symlinks
102 | while [ -h "$PRG" ] ; do
103 | ls=`ls -ld "$PRG"`
104 | link=`expr "$ls" : '.*-> \(.*\)$'`
105 | if expr "$link" : '/.*' > /dev/null; then
106 | PRG="$link"
107 | else
108 | PRG="`dirname "$PRG"`/$link"
109 | fi
110 | done
111 |
112 | saveddir=`pwd`
113 |
114 | M2_HOME=`dirname "$PRG"`/..
115 |
116 | # make it fully qualified
117 | M2_HOME=`cd "$M2_HOME" && pwd`
118 |
119 | cd "$saveddir"
120 | # echo Using m2 at $M2_HOME
121 | fi
122 |
123 | # For Cygwin, ensure paths are in UNIX format before anything is touched
124 | if $cygwin ; then
125 | [ -n "$M2_HOME" ] &&
126 | M2_HOME=`cygpath --unix "$M2_HOME"`
127 | [ -n "$JAVA_HOME" ] &&
128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
129 | [ -n "$CLASSPATH" ] &&
130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
131 | fi
132 |
133 | # For Migwn, ensure paths are in UNIX format before anything is touched
134 | if $mingw ; then
135 | [ -n "$M2_HOME" ] &&
136 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
137 | [ -n "$JAVA_HOME" ] &&
138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
139 | # TODO classpath?
140 | fi
141 |
142 | if [ -z "$JAVA_HOME" ]; then
143 | javaExecutable="`which javac`"
144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
145 | # readlink(1) is not available as standard on Solaris 10.
146 | readLink=`which readlink`
147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
148 | if $darwin ; then
149 | javaHome="`dirname \"$javaExecutable\"`"
150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
151 | else
152 | javaExecutable="`readlink -f \"$javaExecutable\"`"
153 | fi
154 | javaHome="`dirname \"$javaExecutable\"`"
155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
156 | JAVA_HOME="$javaHome"
157 | export JAVA_HOME
158 | fi
159 | fi
160 | fi
161 |
162 | if [ -z "$JAVACMD" ] ; then
163 | if [ -n "$JAVA_HOME" ] ; then
164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
165 | # IBM's JDK on AIX uses strange locations for the executables
166 | JAVACMD="$JAVA_HOME/jre/sh/java"
167 | else
168 | JAVACMD="$JAVA_HOME/bin/java"
169 | fi
170 | else
171 | JAVACMD="`which java`"
172 | fi
173 | fi
174 |
175 | if [ ! -x "$JAVACMD" ] ; then
176 | echo "Error: JAVA_HOME is not defined correctly." >&2
177 | echo " We cannot execute $JAVACMD" >&2
178 | exit 1
179 | fi
180 |
181 | if [ -z "$JAVA_HOME" ] ; then
182 | echo "Warning: JAVA_HOME environment variable is not set."
183 | fi
184 |
185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
186 |
187 | # For Cygwin, switch paths to Windows format before running java
188 | if $cygwin; then
189 | [ -n "$M2_HOME" ] &&
190 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
191 | [ -n "$JAVA_HOME" ] &&
192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
193 | [ -n "$CLASSPATH" ] &&
194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
195 | fi
196 |
197 | # traverses directory structure from process work directory to filesystem root
198 | # first directory with .mvn subdirectory is considered project base directory
199 | find_maven_basedir() {
200 | local basedir=$(pwd)
201 | local wdir=$(pwd)
202 | while [ "$wdir" != '/' ] ; do
203 | if [ -d "$wdir"/.mvn ] ; then
204 | basedir=$wdir
205 | break
206 | fi
207 | wdir=$(cd "$wdir/.."; pwd)
208 | done
209 | echo "${basedir}"
210 | }
211 |
212 | # concatenates all lines of a file
213 | concat_lines() {
214 | if [ -f "$1" ]; then
215 | echo "$(tr -s '\n' ' ' < "$1")"
216 | fi
217 | }
218 |
219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
221 |
222 | # Provide a "standardized" way to retrieve the CLI args that will
223 | # work with both Windows and non-Windows executions.
224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
225 | export MAVEN_CMD_LINE_ARGS
226 |
227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
228 |
229 | exec "$JAVACMD" \
230 | $MAVEN_OPTS \
231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
233 | ${WRAPPER_LAUNCHER} "$@"
234 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | set MAVEN_CMD_LINE_ARGS=%*
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 |
121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
123 |
124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
125 | if ERRORLEVEL 1 goto error
126 | goto end
127 |
128 | :error
129 | set ERROR_CODE=1
130 |
131 | :end
132 | @endlocal & set ERROR_CODE=%ERROR_CODE%
133 |
134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
138 | :skipRcPost
139 |
140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
142 |
143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
144 |
145 | exit /B %ERROR_CODE%
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.amqp.samples
7 | spring-rabbit-confirms-returns
8 | 3.2.0
9 | jar
10 |
11 | spring-rabbit-confirms-returns
12 | Demonstrates Configuration for Confirms and Returns
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 3.4.0
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 17
25 | ${project.version}
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-amqp
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-test
37 | test
38 |
39 |
40 |
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-maven-plugin
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/src/main/java/org/springframework/amqp/samples/confirms/SpringRabbitConfirmsReturnsApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.samples.confirms;
18 |
19 | import java.util.UUID;
20 | import java.util.concurrent.CountDownLatch;
21 | import java.util.concurrent.TimeUnit;
22 |
23 | import org.springframework.amqp.core.Queue;
24 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
25 | import org.springframework.amqp.rabbit.connection.CorrelationData;
26 | import org.springframework.amqp.rabbit.connection.CorrelationData.Confirm;
27 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
28 | import org.springframework.beans.factory.annotation.Autowired;
29 | import org.springframework.boot.ApplicationRunner;
30 | import org.springframework.boot.SpringApplication;
31 | import org.springframework.boot.autoconfigure.SpringBootApplication;
32 | import org.springframework.context.ConfigurableApplicationContext;
33 | import org.springframework.context.annotation.Bean;
34 |
35 | @SpringBootApplication
36 | public class SpringRabbitConfirmsReturnsApplication {
37 |
38 | private static final String QUEUE = "spring.publisher.sample";
39 |
40 | public static void main(String[] args) throws Exception {
41 | ConfigurableApplicationContext context = SpringApplication.run(SpringRabbitConfirmsReturnsApplication.class,
42 | args);
43 | context.close();
44 | }
45 |
46 | @Autowired
47 | private RabbitTemplate rabbitTemplate;
48 |
49 | private final CountDownLatch listenLatch = new CountDownLatch(1);
50 |
51 | private void runDemo() throws Exception {
52 | setupCallbacks();
53 | // send a message to the default exchange to be routed to the queue
54 | CorrelationData correlationData = new CorrelationData("Correlation for message 1");
55 | this.rabbitTemplate.convertAndSend("", QUEUE, "foo", correlationData);
56 | Confirm confirm = correlationData.getFuture().get(10, TimeUnit.SECONDS);
57 | System.out.println("Confirm received for good delivery, ack = " + confirm.isAck());
58 | if (this.listenLatch.await(10, TimeUnit.SECONDS)) {
59 | System.out.println("Message received by listener");
60 | }
61 | else {
62 | System.out.println("Message NOT received by listener");
63 | }
64 | // send a message to the default exchange to be routed to a non-existent queue
65 | correlationData = new CorrelationData("Correlation for message 2");
66 | this.rabbitTemplate.convertAndSend("", QUEUE + QUEUE, "bar", message -> {
67 | System.out.println("Message after conversion: " + message);
68 | return message;
69 | }, correlationData);
70 | confirm = correlationData.getFuture().get(10, TimeUnit.SECONDS);
71 | System.out.println("Confirm received for send to missing queue, ack = " + confirm.isAck());
72 | System.out.println("Return received:" + correlationData.getReturned());
73 | correlationData = new CorrelationData("Correlation for message 3");
74 | // send to non-existent exchange - expect nack
75 | this.rabbitTemplate.convertAndSend(UUID.randomUUID().toString(), QUEUE, "baz", correlationData);
76 | confirm = correlationData.getFuture().get(10, TimeUnit.SECONDS);
77 | System.out.println("Confirm received for send to missing exchange, ack = " + confirm.isAck());
78 | }
79 |
80 | private void setupCallbacks() {
81 | /*
82 | * Confirms/returns enabled in application.properties - add the callbacks here.
83 | */
84 | this.rabbitTemplate.setConfirmCallback((correlation, ack, reason) -> {
85 | if (correlation != null) {
86 | System.out.println("Received " + (ack ? " ack " : " nack ") + "for correlation: " + correlation);
87 | }
88 | });
89 | this.rabbitTemplate.setReturnsCallback(returned -> {
90 | System.out.println("Returned: " + returned.getMessage() + "\nreplyCode: " + returned.getReplyCode()
91 | + "\nreplyText: " + returned.getReplyText() + "\nexchange/rk: "
92 | + returned.getExchange() + "/" + returned.getRoutingKey());
93 | });
94 | }
95 |
96 |
97 | @Bean
98 | public ApplicationRunner runner() {
99 | return args -> runDemo();
100 | }
101 |
102 | @Bean
103 | public Queue queue() {
104 | return new Queue(QUEUE, false, false, true);
105 | }
106 |
107 | @RabbitListener(queues = QUEUE)
108 | public void listen(String in) {
109 | System.out.println("Listener received: " + in);
110 | this.listenLatch.countDown();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rabbitmq.publisher-confirm-type=correlated
2 | spring.rabbitmq.publisher-returns=true
3 |
4 | spring.rabbitmq.template.mandatory=true
5 |
--------------------------------------------------------------------------------
/spring-rabbit-confirms-returns/src/test/java/org/springframework/amqp/samples/confirms/SpringRabbitConfirmsReturnsApplicationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.samples.confirms;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import org.springframework.boot.test.context.SpringBootTest;
22 |
23 | @SpringBootTest
24 | public class SpringRabbitConfirmsReturnsApplicationTests {
25 |
26 | @Test
27 | public void contextLoads() {
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/spring-rabbit-global-errorhandler/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
2 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/README.adoc:
--------------------------------------------------------------------------------
1 | # Configuring a Global Error Handler for @RabbitListener s
2 |
3 | This sample demonstrates how to add a global error handler to `@RabbitListener` methods.
4 |
5 | It uses an auto-delete queue that will be removed after the demo completes.
6 |
7 | The error handler is the same as the default (`ConditionalRejectingErrorHandler`) but with a custom `FatalExceptionStrategy`
8 | that extends the default and logs the failed message.
9 |
10 | NOTE: Such a simple handler is not generally needed since the framework will log the failed message itself; for a real
11 | application, some additional action might be taken, for example write the bad message to a database.
12 |
13 | A JSON message converter is used; the sample sends one "good" message, and one bad one, which fails message conversion.
14 | Message conversion is considered fatal and the message is not requeued.
15 |
16 | It is a Spring Boot application and can be run with normal boot run methods, e.g.: `./mvnw spring-boot:run`
17 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | #
58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look
59 | # for the new JDKs provided by Oracle.
60 | #
61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
62 | #
63 | # Apple JDKs
64 | #
65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
66 | fi
67 |
68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
69 | #
70 | # Apple JDKs
71 | #
72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
73 | fi
74 |
75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
76 | #
77 | # Oracle JDKs
78 | #
79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
80 | fi
81 |
82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
83 | #
84 | # Apple JDKs
85 | #
86 | export JAVA_HOME=`/usr/libexec/java_home`
87 | fi
88 | ;;
89 | esac
90 |
91 | if [ -z "$JAVA_HOME" ] ; then
92 | if [ -r /etc/gentoo-release ] ; then
93 | JAVA_HOME=`java-config --jre-home`
94 | fi
95 | fi
96 |
97 | if [ -z "$M2_HOME" ] ; then
98 | ## resolve links - $0 may be a link to maven's home
99 | PRG="$0"
100 |
101 | # need this for relative symlinks
102 | while [ -h "$PRG" ] ; do
103 | ls=`ls -ld "$PRG"`
104 | link=`expr "$ls" : '.*-> \(.*\)$'`
105 | if expr "$link" : '/.*' > /dev/null; then
106 | PRG="$link"
107 | else
108 | PRG="`dirname "$PRG"`/$link"
109 | fi
110 | done
111 |
112 | saveddir=`pwd`
113 |
114 | M2_HOME=`dirname "$PRG"`/..
115 |
116 | # make it fully qualified
117 | M2_HOME=`cd "$M2_HOME" && pwd`
118 |
119 | cd "$saveddir"
120 | # echo Using m2 at $M2_HOME
121 | fi
122 |
123 | # For Cygwin, ensure paths are in UNIX format before anything is touched
124 | if $cygwin ; then
125 | [ -n "$M2_HOME" ] &&
126 | M2_HOME=`cygpath --unix "$M2_HOME"`
127 | [ -n "$JAVA_HOME" ] &&
128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
129 | [ -n "$CLASSPATH" ] &&
130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
131 | fi
132 |
133 | # For Migwn, ensure paths are in UNIX format before anything is touched
134 | if $mingw ; then
135 | [ -n "$M2_HOME" ] &&
136 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
137 | [ -n "$JAVA_HOME" ] &&
138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
139 | # TODO classpath?
140 | fi
141 |
142 | if [ -z "$JAVA_HOME" ]; then
143 | javaExecutable="`which javac`"
144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
145 | # readlink(1) is not available as standard on Solaris 10.
146 | readLink=`which readlink`
147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
148 | if $darwin ; then
149 | javaHome="`dirname \"$javaExecutable\"`"
150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
151 | else
152 | javaExecutable="`readlink -f \"$javaExecutable\"`"
153 | fi
154 | javaHome="`dirname \"$javaExecutable\"`"
155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
156 | JAVA_HOME="$javaHome"
157 | export JAVA_HOME
158 | fi
159 | fi
160 | fi
161 |
162 | if [ -z "$JAVACMD" ] ; then
163 | if [ -n "$JAVA_HOME" ] ; then
164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
165 | # IBM's JDK on AIX uses strange locations for the executables
166 | JAVACMD="$JAVA_HOME/jre/sh/java"
167 | else
168 | JAVACMD="$JAVA_HOME/bin/java"
169 | fi
170 | else
171 | JAVACMD="`which java`"
172 | fi
173 | fi
174 |
175 | if [ ! -x "$JAVACMD" ] ; then
176 | echo "Error: JAVA_HOME is not defined correctly." >&2
177 | echo " We cannot execute $JAVACMD" >&2
178 | exit 1
179 | fi
180 |
181 | if [ -z "$JAVA_HOME" ] ; then
182 | echo "Warning: JAVA_HOME environment variable is not set."
183 | fi
184 |
185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
186 |
187 | # For Cygwin, switch paths to Windows format before running java
188 | if $cygwin; then
189 | [ -n "$M2_HOME" ] &&
190 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
191 | [ -n "$JAVA_HOME" ] &&
192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
193 | [ -n "$CLASSPATH" ] &&
194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
195 | fi
196 |
197 | # traverses directory structure from process work directory to filesystem root
198 | # first directory with .mvn subdirectory is considered project base directory
199 | find_maven_basedir() {
200 | local basedir=$(pwd)
201 | local wdir=$(pwd)
202 | while [ "$wdir" != '/' ] ; do
203 | if [ -d "$wdir"/.mvn ] ; then
204 | basedir=$wdir
205 | break
206 | fi
207 | wdir=$(cd "$wdir/.."; pwd)
208 | done
209 | echo "${basedir}"
210 | }
211 |
212 | # concatenates all lines of a file
213 | concat_lines() {
214 | if [ -f "$1" ]; then
215 | echo "$(tr -s '\n' ' ' < "$1")"
216 | fi
217 | }
218 |
219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
221 |
222 | # Provide a "standardized" way to retrieve the CLI args that will
223 | # work with both Windows and non-Windows executions.
224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
225 | export MAVEN_CMD_LINE_ARGS
226 |
227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
228 |
229 | exec "$JAVACMD" \
230 | $MAVEN_OPTS \
231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
233 | ${WRAPPER_LAUNCHER} "$@"
234 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | set MAVEN_CMD_LINE_ARGS=%*
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 |
121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
123 |
124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
125 | if ERRORLEVEL 1 goto error
126 | goto end
127 |
128 | :error
129 | set ERROR_CODE=1
130 |
131 | :end
132 | @endlocal & set ERROR_CODE=%ERROR_CODE%
133 |
134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
138 | :skipRcPost
139 |
140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
142 |
143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
144 |
145 | exit /B %ERROR_CODE%
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.example
7 | spring-rabbit-global-errorhandler
8 | 3.2.0
9 | jar
10 |
11 | spring-rabbit-global-errorhandler
12 | Shows how to configure a custom error handler applied to listener beans
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 3.4.0
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 17
25 | ${project.version}
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-amqp
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-logging
36 |
37 |
38 |
39 |
40 |
41 | com.fasterxml.jackson.core
42 | jackson-databind
43 |
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-test
48 | test
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-maven-plugin
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/src/main/java/org/springframework/amqp/samples/errorhandler/Application.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.errorhandler;
2 |
3 | import org.slf4j.Logger;
4 |
5 | import org.springframework.amqp.core.Message;
6 | import org.springframework.amqp.core.Queue;
7 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
8 | import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
9 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
10 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
11 | import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler;
12 | import org.springframework.amqp.rabbit.support.ListenerExecutionFailedException;
13 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
14 | import org.springframework.amqp.support.converter.MessageConverter;
15 | import org.springframework.boot.SpringApplication;
16 | import org.springframework.boot.autoconfigure.SpringBootApplication;
17 | import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
18 | import org.springframework.context.ConfigurableApplicationContext;
19 | import org.springframework.context.annotation.Bean;
20 | import org.springframework.util.ErrorHandler;
21 |
22 | @SpringBootApplication
23 | public class Application {
24 |
25 | private static final String TEST_QUEUE = "spring.amqp.global.error.handler.demo";
26 |
27 | private final Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
28 |
29 | public static void main(String[] args) throws Exception {
30 | ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
31 | context.getBean(Application.class).runDemo(context.getBean(RabbitTemplate.class));
32 | context.close();
33 | }
34 |
35 | private void runDemo(RabbitTemplate template) throws Exception {
36 | template.convertAndSend(TEST_QUEUE, new Foo("bar"));
37 | template.convertAndSend(TEST_QUEUE, new Foo("bar"), m -> {
38 | return new Message("some bad json".getBytes(), m.getMessageProperties());
39 | });
40 | Thread.sleep(5000);
41 | }
42 |
43 | @RabbitListener(queues = TEST_QUEUE)
44 | public void handle(Foo in) {
45 | logger.info("Received: " + in);
46 | }
47 |
48 | @Bean
49 | public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,
50 | SimpleRabbitListenerContainerFactoryConfigurer configurer) {
51 | SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
52 | configurer.configure(factory, connectionFactory);
53 | factory.setErrorHandler(errorHandler());
54 | return factory;
55 | }
56 |
57 | @Bean
58 | public ErrorHandler errorHandler() {
59 | return new ConditionalRejectingErrorHandler(new MyFatalExceptionStrategy());
60 | }
61 |
62 | @Bean
63 | public Queue queue() {
64 | return new Queue(TEST_QUEUE, false, false, true);
65 | }
66 |
67 | @Bean
68 | public MessageConverter jsonConverter() {
69 | return new Jackson2JsonMessageConverter();
70 | }
71 |
72 | public static class MyFatalExceptionStrategy extends ConditionalRejectingErrorHandler.DefaultExceptionStrategy {
73 |
74 | private final Logger logger = org.slf4j.LoggerFactory.getLogger(getClass());
75 |
76 | @Override
77 | public boolean isFatal(Throwable t) {
78 | if (t instanceof ListenerExecutionFailedException) {
79 | ListenerExecutionFailedException lefe = (ListenerExecutionFailedException) t;
80 | logger.error("Failed to process inbound message from queue "
81 | + lefe.getFailedMessage().getMessageProperties().getConsumerQueue()
82 | + "; failed message: " + lefe.getFailedMessage(), t);
83 | }
84 | return super.isFatal(t);
85 | }
86 |
87 | }
88 |
89 | public static class Foo {
90 |
91 | private String foo;
92 |
93 | public Foo() {
94 | super();
95 | }
96 |
97 | public Foo(String foo) {
98 | this.foo = foo;
99 | }
100 |
101 | public String getFoo() {
102 | return this.foo;
103 | }
104 |
105 | public void setFoo(String foo) {
106 | this.foo = foo;
107 | }
108 |
109 | @Override
110 | public String toString() {
111 | return "Foo [foo=" + this.foo + "]";
112 | }
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | rabbitmq:
3 | listener:
4 | simple:
5 | retry:
6 | enabled: false
7 | initial-interval: 2000
8 | multiplier: 1.5
9 | max-interval: 10000
10 | max-attempts: 3
11 |
--------------------------------------------------------------------------------
/spring-rabbit-global-errorhandler/src/test/java/org/springframework/amqp/samples/errorhandler/ApplicationTests.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.errorhandler;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import org.springframework.boot.test.context.SpringBootTest;
6 |
7 | @SpringBootTest
8 | public class ApplicationTests {
9 |
10 | @Test
11 | public void contextLoads() {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/spring-rabbit-json/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 |
12 | ### IntelliJ IDEA ###
13 | .idea
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### NetBeans ###
19 | nbproject/private/
20 | build/
21 | nbbuild/
22 | dist/
23 | nbdist/
24 | .nb-gradle/
--------------------------------------------------------------------------------
/spring-rabbit-json/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/spring-rabbit-json/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/spring-rabbit-json/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
2 |
--------------------------------------------------------------------------------
/spring-rabbit-json/README.adoc:
--------------------------------------------------------------------------------
1 | # Receiving JSON From a Non-Spring Application
2 |
3 | Spring AMQP applications communicating over AMQP using JSON add type information to message headers to enable the receiving application to convert the JSON to a class instance.
4 |
5 | This sample demonstrates techniques to use for such conversion when the sending application is not a Spring app or if you wish to convert to a different type when receiving messages.
6 |
7 | - Inferred type from `@RabbitListener` methods
8 | - Parameterized types in template `receiveAndConvert()` methods
9 | - `ClassMapper` id mapping configuration with a legacy POJO listener.
10 |
11 | It is a Spring Boot application and can be run with normal boot run methods, e.g.: `./mvnw spring-boot:run`
12 |
--------------------------------------------------------------------------------
/spring-rabbit-json/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | #
58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look
59 | # for the new JDKs provided by Oracle.
60 | #
61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
62 | #
63 | # Apple JDKs
64 | #
65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
66 | fi
67 |
68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
69 | #
70 | # Apple JDKs
71 | #
72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
73 | fi
74 |
75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
76 | #
77 | # Oracle JDKs
78 | #
79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
80 | fi
81 |
82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
83 | #
84 | # Apple JDKs
85 | #
86 | export JAVA_HOME=`/usr/libexec/java_home`
87 | fi
88 | ;;
89 | esac
90 |
91 | if [ -z "$JAVA_HOME" ] ; then
92 | if [ -r /etc/gentoo-release ] ; then
93 | JAVA_HOME=`java-config --jre-home`
94 | fi
95 | fi
96 |
97 | if [ -z "$M2_HOME" ] ; then
98 | ## resolve links - $0 may be a link to maven's home
99 | PRG="$0"
100 |
101 | # need this for relative symlinks
102 | while [ -h "$PRG" ] ; do
103 | ls=`ls -ld "$PRG"`
104 | link=`expr "$ls" : '.*-> \(.*\)$'`
105 | if expr "$link" : '/.*' > /dev/null; then
106 | PRG="$link"
107 | else
108 | PRG="`dirname "$PRG"`/$link"
109 | fi
110 | done
111 |
112 | saveddir=`pwd`
113 |
114 | M2_HOME=`dirname "$PRG"`/..
115 |
116 | # make it fully qualified
117 | M2_HOME=`cd "$M2_HOME" && pwd`
118 |
119 | cd "$saveddir"
120 | # echo Using m2 at $M2_HOME
121 | fi
122 |
123 | # For Cygwin, ensure paths are in UNIX format before anything is touched
124 | if $cygwin ; then
125 | [ -n "$M2_HOME" ] &&
126 | M2_HOME=`cygpath --unix "$M2_HOME"`
127 | [ -n "$JAVA_HOME" ] &&
128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
129 | [ -n "$CLASSPATH" ] &&
130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
131 | fi
132 |
133 | # For Migwn, ensure paths are in UNIX format before anything is touched
134 | if $mingw ; then
135 | [ -n "$M2_HOME" ] &&
136 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
137 | [ -n "$JAVA_HOME" ] &&
138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
139 | # TODO classpath?
140 | fi
141 |
142 | if [ -z "$JAVA_HOME" ]; then
143 | javaExecutable="`which javac`"
144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
145 | # readlink(1) is not available as standard on Solaris 10.
146 | readLink=`which readlink`
147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
148 | if $darwin ; then
149 | javaHome="`dirname \"$javaExecutable\"`"
150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
151 | else
152 | javaExecutable="`readlink -f \"$javaExecutable\"`"
153 | fi
154 | javaHome="`dirname \"$javaExecutable\"`"
155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
156 | JAVA_HOME="$javaHome"
157 | export JAVA_HOME
158 | fi
159 | fi
160 | fi
161 |
162 | if [ -z "$JAVACMD" ] ; then
163 | if [ -n "$JAVA_HOME" ] ; then
164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
165 | # IBM's JDK on AIX uses strange locations for the executables
166 | JAVACMD="$JAVA_HOME/jre/sh/java"
167 | else
168 | JAVACMD="$JAVA_HOME/bin/java"
169 | fi
170 | else
171 | JAVACMD="`which java`"
172 | fi
173 | fi
174 |
175 | if [ ! -x "$JAVACMD" ] ; then
176 | echo "Error: JAVA_HOME is not defined correctly." >&2
177 | echo " We cannot execute $JAVACMD" >&2
178 | exit 1
179 | fi
180 |
181 | if [ -z "$JAVA_HOME" ] ; then
182 | echo "Warning: JAVA_HOME environment variable is not set."
183 | fi
184 |
185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
186 |
187 | # For Cygwin, switch paths to Windows format before running java
188 | if $cygwin; then
189 | [ -n "$M2_HOME" ] &&
190 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
191 | [ -n "$JAVA_HOME" ] &&
192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
193 | [ -n "$CLASSPATH" ] &&
194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
195 | fi
196 |
197 | # traverses directory structure from process work directory to filesystem root
198 | # first directory with .mvn subdirectory is considered project base directory
199 | find_maven_basedir() {
200 | local basedir=$(pwd)
201 | local wdir=$(pwd)
202 | while [ "$wdir" != '/' ] ; do
203 | if [ -d "$wdir"/.mvn ] ; then
204 | basedir=$wdir
205 | break
206 | fi
207 | wdir=$(cd "$wdir/.."; pwd)
208 | done
209 | echo "${basedir}"
210 | }
211 |
212 | # concatenates all lines of a file
213 | concat_lines() {
214 | if [ -f "$1" ]; then
215 | echo "$(tr -s '\n' ' ' < "$1")"
216 | fi
217 | }
218 |
219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
221 |
222 | # Provide a "standardized" way to retrieve the CLI args that will
223 | # work with both Windows and non-Windows executions.
224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
225 | export MAVEN_CMD_LINE_ARGS
226 |
227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
228 |
229 | exec "$JAVACMD" \
230 | $MAVEN_OPTS \
231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
233 | ${WRAPPER_LAUNCHER} "$@"
234 |
--------------------------------------------------------------------------------
/spring-rabbit-json/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | set MAVEN_CMD_LINE_ARGS=%*
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 |
121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
123 |
124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
125 | if ERRORLEVEL 1 goto error
126 | goto end
127 |
128 | :error
129 | set ERROR_CODE=1
130 |
131 | :end
132 | @endlocal & set ERROR_CODE=%ERROR_CODE%
133 |
134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
138 | :skipRcPost
139 |
140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
142 |
143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
144 |
145 | exit /B %ERROR_CODE%
--------------------------------------------------------------------------------
/spring-rabbit-json/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.example
7 | spring-rabbit-json
8 | 3.2.0
9 | jar
10 |
11 | spring-rabbit-json
12 | Receiving JSON from non-Spring Applications
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 3.4.0
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 17
25 | ${project.version}
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-amqp
32 |
33 |
34 |
35 | com.fasterxml.jackson.core
36 | jackson-databind
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-test
42 | test
43 |
44 |
45 |
46 |
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-maven-plugin
51 |
52 |
53 |
54 |
55 |
56 | repository.springframework.maven.snapshots
57 | Spring Framework Repository Including Snapshots
58 | https://repo.spring.io/snapshot
59 |
60 | true
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/spring-rabbit-json/src/main/java/org/springframework/amqp/samples/json/Application.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.json;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.concurrent.CountDownLatch;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | import org.springframework.amqp.core.AmqpAdmin;
9 | import org.springframework.amqp.core.AnonymousQueue;
10 | import org.springframework.amqp.core.Message;
11 | import org.springframework.amqp.core.MessageBuilder;
12 | import org.springframework.amqp.core.MessagePropertiesBuilder;
13 | import org.springframework.amqp.core.Queue;
14 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
15 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
16 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
17 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
18 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
19 | import org.springframework.amqp.support.converter.DefaultClassMapper;
20 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
21 | import org.springframework.amqp.support.converter.MessageConverter;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.boot.SpringApplication;
24 | import org.springframework.boot.autoconfigure.SpringBootApplication;
25 | import org.springframework.context.ConfigurableApplicationContext;
26 | import org.springframework.context.annotation.Bean;
27 | import org.springframework.core.ParameterizedTypeReference;
28 |
29 | @SpringBootApplication
30 | public class Application {
31 |
32 | private static final String INFERRED_FOO_QUEUE = "sample.inferred.foo";
33 |
34 | private static final String INFERRED_BAR_QUEUE = "sample.inferred.bar";
35 |
36 | private static final String RECEIVE_AND_CONVERT_QUEUE = "sample.receive.and.convert";
37 |
38 | private static final String MAPPED_QUEUE = "sample.mapped";
39 |
40 | public static void main(String[] args) throws Exception {
41 | ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
42 | ctx.getBean(Application.class).runDemo(ctx.getBean("rabbitTemplate", RabbitTemplate.class),
43 | ctx.getBean("jsonRabbitTemplate", RabbitTemplate.class));
44 | ctx.close();
45 | }
46 |
47 | @Autowired
48 | private AmqpAdmin rabbitAdmin;
49 |
50 | private volatile CountDownLatch latch = new CountDownLatch(2);
51 |
52 | public void runDemo(RabbitTemplate rabbitTemplate, RabbitTemplate jsonRabbitTemplate) throws Exception {
53 | String json = "{\"foo\" : \"value\" }";
54 | Message jsonMessage = MessageBuilder.withBody(json.getBytes())
55 | .andProperties(MessagePropertiesBuilder.newInstance().setContentType("application/json")
56 | .build()).build();
57 |
58 | // inferred type
59 |
60 | rabbitTemplate.send(INFERRED_FOO_QUEUE, jsonMessage);
61 | rabbitTemplate.send(INFERRED_BAR_QUEUE, jsonMessage);
62 | this.latch.await(10, TimeUnit.SECONDS);
63 |
64 | // convertAndReceive with type
65 |
66 | rabbitTemplate.send(RECEIVE_AND_CONVERT_QUEUE, jsonMessage);
67 | rabbitTemplate.send(RECEIVE_AND_CONVERT_QUEUE, jsonMessage);
68 |
69 | Foo foo = jsonRabbitTemplate.receiveAndConvert(RECEIVE_AND_CONVERT_QUEUE, 10_000,
70 | new ParameterizedTypeReference() { });
71 | System.out.println("Expected a Foo, got a " + foo);
72 | Bar bar = jsonRabbitTemplate.receiveAndConvert(RECEIVE_AND_CONVERT_QUEUE, 10_000,
73 | new ParameterizedTypeReference() { });
74 | System.out.println("Expected a Bar, got a " + bar);
75 |
76 | // Mapped type information with legacy POJO listener
77 |
78 | this.latch = new CountDownLatch(2);
79 | jsonMessage.getMessageProperties().setHeader("__TypeId__", "foo");
80 | rabbitTemplate.send(MAPPED_QUEUE, jsonMessage);
81 | jsonMessage.getMessageProperties().setHeader("__TypeId__", "bar");
82 | rabbitTemplate.send(MAPPED_QUEUE, jsonMessage);
83 | this.latch.await(10, TimeUnit.SECONDS);
84 |
85 | this.rabbitAdmin.deleteQueue(RECEIVE_AND_CONVERT_QUEUE);
86 | }
87 |
88 | @RabbitListener(queues = INFERRED_FOO_QUEUE)
89 | public void listenForAFoo(Foo foo) {
90 | System.out.println("Expected a Foo, got a " + foo);
91 | this.latch.countDown();
92 | }
93 |
94 | @RabbitListener(queues = INFERRED_BAR_QUEUE)
95 | public void listenForAFoo(Bar bar) {
96 | System.out.println("Expected a Bar, got a " + bar);
97 | this.latch.countDown();
98 | }
99 |
100 | @Bean
101 | public SimpleMessageListenerContainer legacyPojoListener(ConnectionFactory connectionFactory) {
102 | SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
103 | container.setQueueNames(MAPPED_QUEUE);
104 | MessageListenerAdapter messageListener = new MessageListenerAdapter(new Object() {
105 |
106 | @SuppressWarnings("unused")
107 | public void handleMessage(Object object) {
108 | System.out.println("Got a " + object);
109 | Application.this.latch.countDown();
110 | }
111 |
112 | });
113 | Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
114 | jsonConverter.setClassMapper(classMapper());
115 | messageListener.setMessageConverter(jsonConverter);
116 | container.setMessageListener(messageListener);
117 | return container;
118 | }
119 |
120 | @Bean
121 | public DefaultClassMapper classMapper() {
122 | DefaultClassMapper classMapper = new DefaultClassMapper();
123 | Map> idClassMapping = new HashMap<>();
124 | idClassMapping.put("foo", Foo.class);
125 | idClassMapping.put("bar", Bar.class);
126 | classMapper.setIdClassMapping(idClassMapping);
127 | return classMapper;
128 | }
129 |
130 | @Bean
131 | public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
132 | return new RabbitTemplate(connectionFactory);
133 | }
134 |
135 | @Bean
136 | public RabbitTemplate jsonRabbitTemplate(ConnectionFactory connectionFactory) {
137 | RabbitTemplate template = new RabbitTemplate(connectionFactory);
138 | template.setMessageConverter(jsonConverter());
139 | return template;
140 | }
141 |
142 | @Bean
143 | public MessageConverter jsonConverter() {
144 | return new Jackson2JsonMessageConverter();
145 | }
146 |
147 | @Bean
148 | public Queue inferredFoo() {
149 | return new AnonymousQueue(() -> INFERRED_FOO_QUEUE);
150 | }
151 |
152 | @Bean
153 | public Queue inferredBar() {
154 | return new AnonymousQueue(() -> INFERRED_BAR_QUEUE);
155 | }
156 |
157 | @Bean
158 | public Queue convertAndReceive() {
159 | return new Queue(RECEIVE_AND_CONVERT_QUEUE);
160 | }
161 |
162 | @Bean
163 | public Queue mapped() {
164 | return new AnonymousQueue(() -> MAPPED_QUEUE);
165 | }
166 |
167 | public static class Foo {
168 |
169 | private String foo;
170 |
171 | public Foo() {
172 | super();
173 | }
174 |
175 | public Foo(String foo) {
176 | this.foo = foo;
177 | }
178 |
179 | public String getFoo() {
180 | return this.foo;
181 | }
182 |
183 | public void setFoo(String foo) {
184 | this.foo = foo;
185 | }
186 |
187 | @Override
188 | public String toString() {
189 | return getClass().getSimpleName() + " [foo=" + this.foo + "]";
190 | }
191 |
192 | }
193 |
194 | public static class Bar extends Foo {
195 |
196 | public Bar() {
197 | super();
198 | }
199 |
200 | public Bar(String foo) {
201 | super(foo);
202 | }
203 |
204 | }
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/spring-rabbit-json/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/spring-rabbit-json/src/main/resources/application.properties
--------------------------------------------------------------------------------
/spring-rabbit-json/src/test/java/org/springframework/amqp/samples/json/ApplicationTests.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.json;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import org.springframework.boot.test.context.SpringBootTest;
6 |
7 | @SpringBootTest
8 | public class ApplicationTests {
9 |
10 | @Test
11 | public void contextLoads() {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/spring-rabbit-streams/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/spring-rabbit-streams/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
3 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/README.adoc:
--------------------------------------------------------------------------------
1 | = Interaction with RabbitMQ Streams
2 |
3 | The `spring-rabbit-stream` provides Spring-friendly API over https://www.rabbitmq.com/docs/streams[RabbitMQ Streams] Java client.
4 |
5 | The https://www.rabbitmq.com/docs/stream[`rabbitmq_stream` plugin] must be enabled on RabbitMQ broker.
6 |
7 | Together with Spring Boot auto-configuration for https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#messaging.amqp[Spring AMQP], this sample demonstrates a simple production of 100 messages to `sample-spring-amqp-stream` RabbitMQ queue of type `stream`.
8 | This queue is created automatically by the application using `StreamAdmin` API.
9 | Then this sample registers 10 `@RabbitListener` instances dynamically (which are `spring.rabbitmq.listener.type=stream`) to demonstrate fan-out capability of RabbitMQ Streams.
10 |
11 | The `SpringRabbitStreamsApplicationTests` ensures that all the listeners in the application report their consumption from the `spring-rabbit-stream` into logs for the last `Value #99` data.
12 |
13 | See more information in the https://docs.spring.io/spring-amqp/reference/stream.html[Reference Manual].
14 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.4.0
9 |
10 |
11 | org.springframework.amqp.samples
12 | spring-rabbit-streams
13 | 3.2.0
14 | spring-rabbit-streams
15 | spring-rabbit-streams
16 |
17 | 17
18 | ${project.version}
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-amqp
24 |
25 |
26 | org.springframework.amqp
27 | spring-rabbit-stream
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-test
32 | test
33 |
34 |
35 | org.springframework.amqp
36 | spring-rabbit-test
37 | test
38 |
39 |
40 |
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-maven-plugin
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/src/main/java/org/springframework/amqp/samples/streams/SpringRabbitStreamsApplication.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.streams;
2 |
3 | import java.time.Duration;
4 | import java.util.concurrent.CompletableFuture;
5 | import java.util.stream.IntStream;
6 |
7 | import com.rabbitmq.stream.Environment;
8 | import com.rabbitmq.stream.OffsetSpecification;
9 | import jakarta.annotation.PostConstruct;
10 | import org.apache.commons.logging.Log;
11 | import org.apache.commons.logging.LogFactory;
12 |
13 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
14 | import org.springframework.amqp.rabbit.config.ContainerCustomizer;
15 | import org.springframework.beans.BeansException;
16 | import org.springframework.beans.factory.BeanFactory;
17 | import org.springframework.beans.factory.BeanFactoryAware;
18 | import org.springframework.beans.factory.BeanNameAware;
19 | import org.springframework.beans.factory.annotation.Value;
20 | import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
21 | import org.springframework.boot.ApplicationRunner;
22 | import org.springframework.boot.SpringApplication;
23 | import org.springframework.boot.autoconfigure.SpringBootApplication;
24 | import org.springframework.context.annotation.Bean;
25 | import org.springframework.rabbit.stream.listener.StreamListenerContainer;
26 | import org.springframework.rabbit.stream.producer.RabbitStreamOperations;
27 | import org.springframework.rabbit.stream.support.StreamAdmin;
28 |
29 | @SpringBootApplication
30 | public class SpringRabbitStreamsApplication implements BeanFactoryAware {
31 |
32 | private AutowireCapableBeanFactory beanFactory;
33 |
34 | public static void main(String[] args) {
35 | SpringApplication.run(SpringRabbitStreamsApplication.class, args);
36 | }
37 |
38 | @Override
39 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
40 | this.beanFactory = (AutowireCapableBeanFactory) beanFactory;
41 | }
42 |
43 | @PostConstruct
44 | public void addStreamConsumers() {
45 | for (int i = 0; i < 10; i++) {
46 | this.beanFactory.initializeBean(new SampleRabbitStreamListener(),
47 | SampleRabbitStreamListener.class.getSimpleName() + "#" + i);
48 | }
49 | }
50 |
51 | @Bean
52 | ApplicationRunner streamProducer(RabbitStreamOperations rabbitStreamOperations) {
53 | return args -> {
54 | CompletableFuture>[] sendResults =
55 | IntStream.range(0, 100)
56 | .boxed()
57 | .map((value) -> "Value #" + value)
58 | .map(rabbitStreamOperations::convertAndSend)
59 | .toArray(CompletableFuture>[]::new);
60 |
61 | CompletableFuture.allOf(sendResults).join();
62 | };
63 |
64 | }
65 |
66 | @Bean
67 | StreamAdmin streamAdmin(Environment streamEnvironment, @Value("${spring.rabbitmq.stream.name}") String streamName) {
68 | return new StreamAdmin(streamEnvironment, sc -> sc.stream(streamName).maxAge(Duration.ofMinutes(1)).create());
69 | }
70 |
71 | @Bean
72 | ContainerCustomizer streamListenerContainerContainerCustomizer() {
73 | return (container) ->
74 | container.setConsumerCustomizer((listenerId, consumerBuilder) ->
75 | consumerBuilder.offset(OffsetSpecification.last()));
76 | }
77 |
78 | private static class SampleRabbitStreamListener implements BeanNameAware {
79 |
80 | private static final Log LOG = LogFactory.getLog(SampleRabbitStreamListener.class);
81 |
82 | private String beanName;
83 |
84 | @Override
85 | public void setBeanName(String name) {
86 | this.beanName = name;
87 | }
88 |
89 | @RabbitListener(queues = "${spring.rabbitmq.stream.name}")
90 | void listen(String data) {
91 | LOG.info(this.beanName + " received: " + data);
92 | }
93 |
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.rabbitmq.listener.type=stream
2 | spring.rabbitmq.stream.name=sample-spring-amqp-stream
3 |
--------------------------------------------------------------------------------
/spring-rabbit-streams/src/test/java/org/springframework/amqp/samples/streams/SpringRabbitStreamsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package org.springframework.amqp.samples.streams;
2 |
3 | import java.util.stream.IntStream;
4 |
5 | import org.junit.jupiter.api.Test;
6 | import org.junit.jupiter.api.extension.ExtendWith;
7 |
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.boot.test.system.CapturedOutput;
10 | import org.springframework.boot.test.system.OutputCaptureExtension;
11 | import org.springframework.test.annotation.DirtiesContext;
12 |
13 | import static org.assertj.core.api.Assertions.assertThat;
14 | import static org.awaitility.Awaitility.await;
15 |
16 | @SpringBootTest
17 | @ExtendWith(OutputCaptureExtension.class)
18 | @DirtiesContext
19 | class SpringRabbitStreamsApplicationTests {
20 |
21 | @Test
22 | void verifyAllStreamListenerReceivesAllData(CapturedOutput output) {
23 | IntStream.range(0, 10)
24 | .forEach((index) ->
25 | await().untilAsserted(() ->
26 | assertThat(output.getOut())
27 | .contains("SampleRabbitStreamListener#" + index + " received: Value #99")));
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/stocks/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-projects/spring-amqp-samples/7fd03cc7253667b41643f5f4370e35c1170e9705/stocks/.DS_Store
--------------------------------------------------------------------------------
/stocks/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | org.springframework.samples.spring
6 | spring-rabbit-stocks
7 | 3.2.0
8 | war
9 | Spring Rabbit Stocks
10 | https://www.spring.io
11 |
12 |
15 |
16 |
17 | true
18 | 6.2.1
19 | 3.2.1
20 | UTF-8
21 | 17
22 |
23 |
24 |
25 |
26 |
27 | com.fasterxml.jackson
28 | jackson-bom
29 | 2.18.2
30 | import
31 | pom
32 |
33 |
34 |
35 |
36 |
37 |
38 | org.springframework.amqp
39 | spring-rabbit
40 | ${spring.amqp.version}
41 |
42 |
43 |
44 | org.springframework
45 | spring-context-support
46 | ${spring.framework.version}
47 | runtime
48 |
49 |
50 | org.springframework
51 | spring-oxm
52 | ${spring.framework.version}
53 |
54 |
55 | org.springframework
56 | spring-tx
57 | ${spring.framework.version}
58 |
59 |
60 | org.springframework
61 | spring-webmvc
62 | ${spring.framework.version}
63 |
64 |
65 | jakarta.servlet
66 | jakarta.servlet-api
67 | 6.0.0
68 | provided
69 |
70 |
71 | org.apache.taglibs
72 | taglibs-standard-spec
73 | 1.2.5
74 | runtime
75 |
76 |
77 | org.apache.taglibs
78 | taglibs-standard-impl
79 | 1.2.5
80 | runtime
81 |
82 |
83 | org.aspectj
84 | aspectjrt
85 | 1.9.22.1
86 |
87 |
88 | org.aspectj
89 | aspectjweaver
90 | 1.9.22.1
91 |
92 |
93 |
94 | com.fasterxml.jackson.core
95 | jackson-databind
96 | runtime
97 |
98 |
99 |
100 | org.springframework.amqp
101 | spring-rabbit-test
102 | ${spring.amqp.version}
103 | test
104 |
105 |
106 |
107 | junit
108 | junit
109 | 4.13.2
110 | test
111 |
112 |
113 |
114 | org.apache.logging.log4j
115 | log4j-core
116 | 2.24.3
117 |
118 |
119 |
120 | org.apache.logging.log4j
121 | log4j-jcl
122 | 2.24.3
123 | runtime
124 |
125 |
126 | org.apache.logging.log4j
127 | log4j-slf4j-impl
128 | 2.24.3
129 |
130 |
131 | com.jgoodies
132 | forms
133 | 1.2.1
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | org.eclipse.jetty
142 | jetty-maven-plugin
143 | 11.0.24
144 |
145 |
146 | org.apache.maven.plugins
147 | maven-compiler-plugin
148 | 3.13.0
149 |
150 | 17
151 | 17
152 |
153 |
154 |
155 | org.apache.maven.plugins
156 | maven-surefire-plugin
157 | 3.5.2
158 |
159 |
160 |
161 | **/*Tests.java
162 |
163 |
164 | **/Abstract*.java
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/config/AbstractStockAppRabbitConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.config;
18 |
19 | import org.springframework.amqp.core.AmqpAdmin;
20 | import org.springframework.amqp.core.TopicExchange;
21 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
22 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
23 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
24 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
25 | import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
26 | import org.springframework.amqp.support.converter.MessageConverter;
27 | import org.springframework.beans.factory.annotation.Value;
28 | import org.springframework.context.annotation.Bean;
29 | import org.springframework.context.annotation.Configuration;
30 |
31 | /**
32 | * Provides shared configuration between Client and Server.
33 | *
The abstract method configureRabbitTemplate lets the Client and Server further customize
34 | * the rabbit template to their specific needs.
35 | *
36 | * @author Mark Pollack
37 | * @author Mark Fisher
38 | * @author Gary Russell
39 | */
40 | @Configuration
41 | public abstract class AbstractStockAppRabbitConfiguration {
42 |
43 | /**
44 | * Shared topic exchange used for publishing any market data (e.g. stock quotes)
45 | */
46 | protected static String MARKET_DATA_EXCHANGE_NAME = "app.stock.marketdata";
47 |
48 | /**
49 | * The server-side consumer's queue that provides point-to-point semantics for stock requests.
50 | */
51 | protected static String STOCK_REQUEST_QUEUE_NAME = "app.stock.request";
52 |
53 | /**
54 | * Key that clients will use to send to the stock request queue via the default direct exchange.
55 | */
56 | protected static String STOCK_REQUEST_ROUTING_KEY = STOCK_REQUEST_QUEUE_NAME;
57 |
58 | @Value("${amqp.port:5672}")
59 | private final int port = 5672;
60 |
61 |
62 | protected abstract void configureRabbitTemplate(RabbitTemplate template);
63 |
64 | @Bean
65 | public ConnectionFactory connectionFactory() {
66 | //TODO make it possible to customize in subclasses.
67 | CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
68 | connectionFactory.setUsername("guest");
69 | connectionFactory.setPassword("guest");
70 | connectionFactory.setPort(port);
71 | return connectionFactory;
72 | }
73 |
74 | @Bean
75 | public RabbitTemplate rabbitTemplate() {
76 | RabbitTemplate template = new RabbitTemplate(connectionFactory());
77 | template.setMessageConverter(jsonMessageConverter());
78 | configureRabbitTemplate(template);
79 | return template;
80 | }
81 |
82 | @Bean
83 | public MessageConverter jsonMessageConverter() {
84 | return new Jackson2JsonMessageConverter();
85 | }
86 |
87 | @Bean
88 | public TopicExchange marketDataExchange() {
89 | return new TopicExchange(MARKET_DATA_EXCHANGE_NAME);
90 | }
91 |
92 | /**
93 | * @return the admin bean that can declare queues etc.
94 | */
95 | @Bean
96 | public AmqpAdmin amqpAdmin() {
97 | RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
98 | return rabbitAdmin ;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/config/RoutingKey.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.config;
18 |
19 | /**
20 | * Enumerations for the RoutingKeys used in the application to allow for a more fluent API
21 | * style when configuring the broker in code.
22 | *
23 | * @author Mark Pollack
24 | */
25 | public enum RoutingKey {
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/config/client/RabbitClientConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.config.client;
18 |
19 |
20 | import org.springframework.amqp.core.AcknowledgeMode;
21 | import org.springframework.amqp.core.AmqpAdmin;
22 | import org.springframework.amqp.core.AnonymousQueue;
23 | import org.springframework.amqp.core.Binding;
24 | import org.springframework.amqp.core.BindingBuilder;
25 | import org.springframework.amqp.core.Queue;
26 | import org.springframework.amqp.rabbit.core.RabbitAdmin;
27 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
28 | import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
29 | import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
30 | import org.springframework.amqp.rabbit.stocks.config.AbstractStockAppRabbitConfiguration;
31 | import org.springframework.amqp.rabbit.stocks.gateway.RabbitStockServiceGateway;
32 | import org.springframework.amqp.rabbit.stocks.gateway.StockServiceGateway;
33 | import org.springframework.amqp.rabbit.stocks.handler.ClientHandler;
34 | import org.springframework.beans.factory.annotation.Autowired;
35 | import org.springframework.beans.factory.annotation.Value;
36 | import org.springframework.context.annotation.Bean;
37 | import org.springframework.context.annotation.Configuration;
38 |
39 | /**
40 | * Configures RabbitTemplate and creates the Trader queue and binding for the client.
41 | *
42 | * @author Mark Pollack
43 | * @author Mark Fisher
44 | * @author Gary Russell
45 | */
46 | @Configuration
47 | public class RabbitClientConfiguration extends AbstractStockAppRabbitConfiguration {
48 |
49 | @Value("${stocks.quote.pattern}")
50 | private String marketDataRoutingKey;
51 |
52 | @Autowired
53 | private ClientHandler clientHandler;
54 |
55 | /**
56 | * The client's template will by default send to the exchange defined
57 | * in {@link org.springframework.amqp.rabbit.config.AbstractRabbitConfiguration#rabbitTemplate()}
58 | * with the routing key {@link AbstractStockAppRabbitConfiguration#STOCK_REQUEST_QUEUE_NAME}
59 | *
60 | * The default exchange will delivery to a queue whose name matches the routing key value.
61 | */
62 | @Override
63 | public void configureRabbitTemplate(RabbitTemplate rabbitTemplate) {
64 | rabbitTemplate.setRoutingKey(STOCK_REQUEST_QUEUE_NAME);
65 | }
66 |
67 | @Bean
68 | public StockServiceGateway stockServiceGateway() {
69 | RabbitStockServiceGateway gateway = new RabbitStockServiceGateway();
70 | gateway.setRabbitOperations(rabbitTemplate());
71 | gateway.setDefaultReplyTo(traderJoeQueue().getName());
72 | return gateway;
73 | }
74 |
75 | @Bean
76 | public SimpleMessageListenerContainer messageListenerContainer() {
77 | SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
78 | container.setQueues(marketDataQueue(), traderJoeQueue());
79 | container.setMessageListener(messageListenerAdapter());
80 | container.setAcknowledgeMode(AcknowledgeMode.AUTO);
81 | return container;
82 |
83 | //container(using(connectionFactory()).listenToQueues(marketDataQueue(), traderJoeQueue()).withListener(messageListenerAdapter()).
84 | }
85 |
86 | @Bean
87 | public MessageListenerAdapter messageListenerAdapter() {
88 | return new MessageListenerAdapter(clientHandler, jsonMessageConverter());
89 | }
90 |
91 |
92 | // Broker Configuration
93 |
94 | // @PostContruct
95 | // public void declareClientBrokerConfiguration() {
96 | // declare(marketDataQueue);
97 | // declare(new Binding(marketDataQueue, MARKET_DATA_EXCHANGE, marketDataRoutingKey));
98 | // declare(traderJoeQueue);
99 | // // no need to bind traderJoeQueue as it is automatically bound to the default direct exchanage, which is what we will use
100 | //
101 | // //add as many declare statements as needed like a script.
102 | // }
103 |
104 | @Bean
105 | public Queue marketDataQueue() {
106 | return new AnonymousQueue();
107 | }
108 |
109 | /**
110 | * Binds to the market data exchange. Interested in any stock quotes.
111 | */
112 | @Bean
113 | public Binding marketDataBinding() {
114 | return BindingBuilder.bind(marketDataQueue()).to(marketDataExchange()).with(marketDataRoutingKey);
115 | }
116 |
117 | /**
118 | * This queue does not need a binding, since it relies on the default exchange.
119 | */
120 | @Bean
121 | public Queue traderJoeQueue() {
122 | return new AnonymousQueue();
123 | }
124 |
125 | @Bean
126 | public AmqpAdmin rabbitAdmin() {
127 | return new RabbitAdmin(connectionFactory());
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/config/server/RabbitServerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.config.server;
18 |
19 | import org.springframework.amqp.core.Queue;
20 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
21 | import org.springframework.amqp.rabbit.stocks.config.AbstractStockAppRabbitConfiguration;
22 | import org.springframework.context.annotation.Bean;
23 | import org.springframework.context.annotation.Configuration;
24 |
25 | /**
26 | * Configures RabbitTemplate for the server.
27 | *
28 | * @author Mark Pollack
29 | * @author Mark Fisher
30 | */
31 | @Configuration
32 | public class RabbitServerConfiguration extends AbstractStockAppRabbitConfiguration {
33 |
34 | /**
35 | * The server's template will by default send to the topic exchange named
36 | * {@link AbstractStockAppRabbitConfiguration#MARKET_DATA_EXCHANGE_NAME}.
37 | */
38 | public void configureRabbitTemplate(RabbitTemplate rabbitTemplate) {
39 | rabbitTemplate.setExchange(MARKET_DATA_EXCHANGE_NAME);
40 | }
41 |
42 | /**
43 | * We don't need to define any binding for the stock request queue, since it's relying
44 | * on the default (no-name) direct exchange to which every queue is implicitly bound.
45 | */
46 | @Bean
47 | public Queue stockRequestQueue() {
48 | return new Queue(STOCK_REQUEST_QUEUE_NAME);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/domain/Quote.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * https://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 |
14 | package org.springframework.amqp.rabbit.stocks.domain;
15 |
16 | import java.text.DateFormat;
17 | import java.util.Date;
18 |
19 | /**
20 | * Domain object representing a stock quote.
21 | *
22 | * @author Mark Fisher
23 | */
24 | public class Quote {
25 |
26 | private Stock stock;
27 | private String price;
28 | private long timestamp;
29 |
30 | private DateFormat format = DateFormat.getTimeInstance();
31 |
32 | public Quote() {
33 | this(null, null);
34 | }
35 |
36 | public Quote(Stock stock, String price) {
37 | this(stock, price, new Date().getTime());
38 | }
39 |
40 | public Quote(Stock stock, String price, long timestamp) {
41 | this.stock = stock;
42 | this.price = price;
43 | this.timestamp = timestamp;
44 | }
45 |
46 | public Stock getStock() {
47 | return this.stock;
48 | }
49 |
50 | public void setStock(Stock stock) {
51 | this.stock = stock;
52 | }
53 |
54 | public String getPrice() {
55 | return price;
56 | }
57 |
58 | public long getTimestamp() {
59 | return timestamp;
60 | }
61 |
62 | public void setTimestamp(long timestamp) {
63 | this.timestamp = timestamp;
64 | }
65 |
66 | public String getTimeString() {
67 | return format.format(new Date(timestamp));
68 | }
69 |
70 | public void setPrice(String price) {
71 | this.price = price;
72 | }
73 |
74 | @Override
75 | public String toString() {
76 | return "Quote [time=" + getTimeString() + ", stock=" + stock + ", price=" + price + "]";
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/domain/Stock.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.domain;
18 |
19 | /**
20 | * @author Mark Fisher
21 | * @author Dave Syer
22 | */
23 | public class Stock {
24 |
25 | private String ticker;
26 |
27 | private StockExchange stockExchange;
28 |
29 | // For de-seialization:
30 | public Stock() {
31 | }
32 |
33 | public Stock(StockExchange stockExchange, String ticker) {
34 | this.stockExchange = stockExchange;
35 | this.ticker = ticker;
36 | }
37 |
38 | public String getTicker() {
39 | return ticker;
40 | }
41 |
42 | public StockExchange getStockExchange() {
43 | return stockExchange;
44 | }
45 |
46 | public void setTicker(String ticker) {
47 | this.ticker = ticker;
48 | }
49 |
50 | public void setStockExchange(StockExchange stockExchange) {
51 | this.stockExchange = stockExchange;
52 | }
53 |
54 | @Override
55 | public String toString() {
56 | return "Stock [ticker=" + ticker + ", stockExchange=" + stockExchange + "]";
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/domain/StockExchange.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.domain;
18 |
19 | /**
20 | * Enumeration for Stock Exchanges.
21 | *
22 | * @author Mark Fisher
23 | */
24 | public enum StockExchange {
25 |
26 | nyse, nasdaq;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/domain/TradeRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.amqp.rabbit.stocks.domain;
17 |
18 | import java.math.BigDecimal;
19 | import java.util.UUID;
20 |
21 | /**
22 | * Simple trade request 'data' object. No functionality in this 'domain' class.
23 | * @author Mark Pollack
24 | *
25 | */
26 | public class TradeRequest {
27 |
28 | private String ticker;
29 |
30 | private long quantity;
31 |
32 | private BigDecimal price;
33 |
34 | private String orderType;
35 |
36 | private String accountName;
37 |
38 | private boolean buyRequest;
39 |
40 | private String userName;
41 |
42 | private String requestId;
43 |
44 | private String id = UUID.randomUUID().toString();
45 |
46 | public String getTicker() {
47 | return ticker;
48 | }
49 |
50 | public void setTicker(String ticker) {
51 | this.ticker = ticker;
52 | }
53 |
54 | public long getQuantity() {
55 | return quantity;
56 | }
57 |
58 | public void setQuantity(long quantity) {
59 | this.quantity = quantity;
60 | }
61 |
62 | public BigDecimal getPrice() {
63 | return price;
64 | }
65 |
66 | public void setPrice(BigDecimal price) {
67 | this.price = price;
68 | }
69 |
70 | public String getOrderType() {
71 | return orderType;
72 | }
73 |
74 | public void setOrderType(String orderType) {
75 | this.orderType = orderType;
76 | }
77 |
78 | public String getAccountName() {
79 | return accountName;
80 | }
81 |
82 | public void setAccountName(String accountName) {
83 | this.accountName = accountName;
84 | }
85 |
86 | public boolean isBuyRequest() {
87 | return buyRequest;
88 | }
89 |
90 | public void setBuyRequest(boolean buyRequest) {
91 | this.buyRequest = buyRequest;
92 | }
93 |
94 | public String getUserName() {
95 | return userName;
96 | }
97 |
98 | public void setUserName(String userName) {
99 | this.userName = userName;
100 | }
101 |
102 | public String getRequestId() {
103 | return requestId;
104 | }
105 |
106 | public void setRequestId(String requestId) {
107 | this.requestId = requestId;
108 | }
109 |
110 | public String getId() {
111 | return id;
112 | }
113 |
114 | public void setId(String id) {
115 | this.id = id;
116 | }
117 |
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/domain/TradeResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * https://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | */
13 | package org.springframework.amqp.rabbit.stocks.domain;
14 |
15 | import java.math.BigDecimal;
16 | import java.util.Date;
17 |
18 | /**
19 | * Simple trade request 'data' object. No functionality in this 'domain' class.
20 | * @author Mark Pollack
21 | *
22 | */
23 | public class TradeResponse {
24 |
25 | private String ticker;
26 |
27 | private long quantity;
28 |
29 | private BigDecimal price;
30 |
31 | private String orderType;
32 |
33 | private String confirmationNumber;
34 |
35 | private boolean error;
36 |
37 | private String errorMessage;
38 |
39 | private String accountName;
40 |
41 | private long timestamp = new Date().getTime();
42 |
43 | private String requestId;
44 |
45 | public String getRequestId() {
46 | return requestId;
47 | }
48 |
49 | public void setRequestId(String requestId) {
50 | this.requestId = requestId;
51 | }
52 |
53 | public String getTicker() {
54 | return ticker;
55 | }
56 |
57 | public void setTicker(String ticker) {
58 | this.ticker = ticker;
59 | }
60 |
61 | public long getQuantity() {
62 | return quantity;
63 | }
64 |
65 | public void setQuantity(long quantity) {
66 | this.quantity = quantity;
67 | }
68 |
69 | public BigDecimal getPrice() {
70 | return price;
71 | }
72 |
73 | public void setPrice(BigDecimal price) {
74 | this.price = price;
75 | }
76 |
77 | public String getOrderType() {
78 | return orderType;
79 | }
80 |
81 | public void setOrderType(String orderType) {
82 | this.orderType = orderType;
83 | }
84 |
85 | public String getConfirmationNumber() {
86 | return confirmationNumber;
87 | }
88 |
89 | public void setConfirmationNumber(String confirmationNumber) {
90 | this.confirmationNumber = confirmationNumber;
91 | }
92 |
93 | public String getAccountName() {
94 | return accountName;
95 | }
96 |
97 | public void setAccountName(String accountName) {
98 | this.accountName = accountName;
99 | }
100 |
101 | public boolean isError() {
102 | return error;
103 | }
104 |
105 | public void setError(boolean error) {
106 | this.error = error;
107 | }
108 |
109 | public String getErrorMessage() {
110 | return errorMessage;
111 | }
112 |
113 | public void setErrorMessage(String errorMessage) {
114 | this.errorMessage = errorMessage;
115 | }
116 |
117 | public long getTimestamp() {
118 | return timestamp;
119 | }
120 |
121 | public void setTimestamp(long timestamp) {
122 | this.timestamp = timestamp;
123 | }
124 |
125 | @Override
126 | public String toString() {
127 | return "TradeResponse [accountName=" + accountName + ", requestId="
128 | + requestId + ", confirmationNumber=" + confirmationNumber
129 | + ", error=" + error + ", errorMessage=" + errorMessage
130 | + ", orderType=" + orderType + ", price=" + price
131 | + ", quantity=" + quantity + ", ticker=" + ticker + "]";
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/gateway/MarketDataGateway.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.amqp.rabbit.stocks.gateway;
17 |
18 | /**
19 | * Gateway interface for sending market data to clients
20 | * @author Mark Pollack
21 | *
22 | */
23 | public interface MarketDataGateway {
24 |
25 | void sendMarketData();
26 | }
27 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/gateway/RabbitMarketDataGateway.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.gateway;
18 |
19 | import java.text.DecimalFormat;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.Random;
23 |
24 | import org.apache.commons.logging.Log;
25 | import org.apache.commons.logging.LogFactory;
26 |
27 | import org.springframework.amqp.rabbit.core.RabbitGatewaySupport;
28 | import org.springframework.amqp.rabbit.stocks.domain.Quote;
29 | import org.springframework.amqp.rabbit.stocks.domain.Stock;
30 | import org.springframework.amqp.rabbit.stocks.domain.StockExchange;
31 |
32 | /**
33 | * Rabbit implementation of the {@link MarketDataGateway} for sending Market data.
34 | *
35 | * @author Mark Pollack
36 | * @author Mark Fisher
37 | * @author Gary Russell
38 | */
39 | public class RabbitMarketDataGateway extends RabbitGatewaySupport implements MarketDataGateway {
40 |
41 | private static Log logger = LogFactory.getLog(RabbitMarketDataGateway.class);
42 |
43 | private static final Random random = new Random();
44 |
45 | private final List stocks = new ArrayList();
46 |
47 |
48 | public RabbitMarketDataGateway() {
49 | this.stocks.add(new MockStock("AAPL", StockExchange.nasdaq, 255));
50 | this.stocks.add(new MockStock("CSCO", StockExchange.nasdaq, 22));
51 | this.stocks.add(new MockStock("DELL", StockExchange.nasdaq, 15));
52 | this.stocks.add(new MockStock("GOOG", StockExchange.nasdaq, 500));
53 | this.stocks.add(new MockStock("INTC", StockExchange.nasdaq, 22));
54 | this.stocks.add(new MockStock("MSFT", StockExchange.nasdaq, 29));
55 | this.stocks.add(new MockStock("ORCL", StockExchange.nasdaq, 24));
56 | this.stocks.add(new MockStock("CAJ", StockExchange.nyse, 43));
57 | this.stocks.add(new MockStock("F", StockExchange.nyse, 12));
58 | this.stocks.add(new MockStock("GE", StockExchange.nyse, 18));
59 | this.stocks.add(new MockStock("HMC", StockExchange.nyse, 32));
60 | this.stocks.add(new MockStock("HPQ", StockExchange.nyse, 48));
61 | this.stocks.add(new MockStock("IBM", StockExchange.nyse, 130));
62 | this.stocks.add(new MockStock("TM", StockExchange.nyse, 76));
63 | }
64 |
65 |
66 | public void sendMarketData() {
67 | Quote quote = generateFakeQuote();
68 | Stock stock = quote.getStock();
69 | logger.info("Sending Market Data for " + stock.getTicker());
70 | String routingKey = "app.stock.quotes."+ stock.getStockExchange() + "." + stock.getTicker();
71 | getRabbitOperations().convertAndSend(routingKey, quote);
72 | }
73 |
74 | private Quote generateFakeQuote() {
75 | MockStock stock = this.stocks.get(random.nextInt(this.stocks.size()));
76 | String price = stock.randomPrice();
77 | return new Quote(stock, price);
78 | }
79 |
80 |
81 | private static class MockStock extends Stock {
82 |
83 | private final int basePrice;
84 | private final DecimalFormat twoPlacesFormat = new DecimalFormat("0.00");
85 |
86 | private MockStock(String ticker, StockExchange stockExchange, int basePrice) {
87 | super(stockExchange, ticker);
88 | this.basePrice = basePrice;
89 | }
90 |
91 | private String randomPrice() {
92 | return this.twoPlacesFormat.format(this.basePrice + Math.abs(random.nextGaussian()));
93 | }
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/gateway/RabbitStockServiceGateway.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.gateway;
18 |
19 | import java.util.UUID;
20 |
21 | import org.springframework.amqp.AmqpException;
22 | import org.springframework.amqp.core.Message;
23 | import org.springframework.amqp.core.MessagePostProcessor;
24 | import org.springframework.amqp.rabbit.core.RabbitGatewaySupport;
25 | import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
26 |
27 | /**
28 | * Rabbit implementation of {@link StockServiceGateway} to send trade requests to an external process.
29 | *
30 | * @author Mark Pollack
31 | * @author Gary Russell
32 | */
33 | public class RabbitStockServiceGateway extends RabbitGatewaySupport implements StockServiceGateway {
34 |
35 | private String defaultReplyTo;
36 |
37 | public void setDefaultReplyTo(String defaultReplyTo) {
38 | this.defaultReplyTo = defaultReplyTo;
39 | }
40 |
41 | public void send(TradeRequest tradeRequest) {
42 | getRabbitOperations().convertAndSend(tradeRequest, new MessagePostProcessor() {
43 | public Message postProcessMessage(Message message) throws AmqpException {
44 | message.getMessageProperties().setReplyTo(defaultReplyTo);
45 | message.getMessageProperties().setCorrelationId(UUID.randomUUID().toString());
46 | return message;
47 | }
48 | });
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/gateway/StockServiceGateway.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.gateway;
18 |
19 | import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
20 |
21 | /**
22 | * Gateway interface that sends trades to an external process.
23 | *
24 | * @author Mark Pollack
25 | */
26 | public interface StockServiceGateway {
27 |
28 | void send(TradeRequest tradeRequest);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/handler/ClientHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.amqp.rabbit.stocks.handler;
18 |
19 | import org.apache.commons.logging.Log;
20 | import org.apache.commons.logging.LogFactory;
21 |
22 | import org.springframework.amqp.rabbit.stocks.domain.Quote;
23 | import org.springframework.amqp.rabbit.stocks.domain.Stock;
24 | import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
25 | import org.springframework.amqp.rabbit.stocks.ui.StockController;
26 |
27 | /**
28 | * POJO handler that receives market data and trade responses. Calls are delegated to the UI controller.
29 | *
30 | * @author Mark Pollack
31 | * @author Mark Fisher
32 | */
33 | public class ClientHandler {
34 |
35 | private static Log log = LogFactory.getLog(ClientHandler.class);
36 |
37 | private StockController stockController;
38 |
39 | public StockController getStockController() {
40 | return stockController;
41 | }
42 |
43 | public void setStockController(StockController stockController) {
44 | this.stockController = stockController;
45 | }
46 |
47 | public void handleMessage(Quote quote) {
48 | Stock stock = quote.getStock();
49 | log.info("Received market data. Ticker = " + stock.getTicker() + ", Price = " + quote.getPrice());
50 | stockController.displayQuote(quote);
51 | }
52 |
53 | public void handleMessage(TradeResponse tradeResponse) {
54 | log.info("Received trade repsonse. [" + tradeResponse + "]");
55 | stockController.updateTrade(tradeResponse);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/stocks/src/main/java/org/springframework/amqp/rabbit/stocks/handler/ServerHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2002-2010 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.amqp.rabbit.stocks.handler;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import org.springframework.amqp.rabbit.stocks.domain.TradeRequest;
22 | import org.springframework.amqp.rabbit.stocks.domain.TradeResponse;
23 | import org.springframework.amqp.rabbit.stocks.service.CreditCheckService;
24 | import org.springframework.amqp.rabbit.stocks.service.ExecutionVenueService;
25 | import org.springframework.amqp.rabbit.stocks.service.TradingService;
26 | import org.springframework.util.StringUtils;
27 |
28 |
29 | /**
30 | * POJO handler that receives trade requests and sends back a trade response. Main application
31 | * logic sits here which coordinates between {@link ExecutionVenueService}, {@link CreditCheckService},
32 | * and {@link TradingService}.
33 | *
34 | * @author Mark Pollack
35 | *
36 | */
37 | public class ServerHandler {
38 |
39 | private ExecutionVenueService executionVenueService;
40 |
41 | private CreditCheckService creditCheckService;
42 |
43 | private TradingService tradingService;
44 |
45 |
46 |
47 | public ServerHandler(ExecutionVenueService executionVenueService,
48 | CreditCheckService creditCheckService,
49 | TradingService tradingService) {
50 | this.executionVenueService = executionVenueService;
51 | this.creditCheckService = creditCheckService;
52 | this.tradingService = tradingService;
53 | }
54 |
55 | public TradeResponse handleMessage(TradeRequest tradeRequest)
56 | {
57 | TradeResponse tradeResponse;
58 | List> errors = new ArrayList