In the past posts, we had learned how to consume/produce ActiveMq JMS messages. Today, JavaSampleApproach will show you way to create a SpringBoot ActiveMQ Response Management application by @SendTo
annotation.
Related posts:
– Spring ActiveMQ JMS Consumer and JMS Producer
– Send Java object messages to ActiveMQ server (specially with Bi-Directional relationship Java objects)
– Spring JMS ActiveMq Topic (Publisher-Subcribers pattern)
I. Technologies
– Java 8
– Maven 3.6.1
– Spring Tool Suite: Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE
– Apache ActiveMQ 5.14.0
II. ActiveMQ Response Management
With the Spring JMS improvements (from 4.1), we can used @SendTo
annotation to define the default next destination with @JmsListener
:
@JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory")
@SendTo("${jsa.activemq.queue.sendto}")
public Product processOrder(Product product) {
// process a newProduct
return newProduct;
}
For additional headers, you could return a Message object instead:
@JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory")
@SendTo("${jsa.activemq.queue.sendto}")
public Message receive(Product product, @Header("company") String companyName){
...
Message mesage = MessageBuilder
.withPayload(product)
.setHeader("type", product.getType())
.build();
return mesage;
}
@JmsListener
methods, we can also place the @SendTo
annotation at the class level to share a default reply destination.
III. Practice
In the tutorial, we create 2 SpringBoot projects {SpringActiveMqProducerConsumer, SpringActiveMqSendTo}:
Step to do:
– Create SpringBoot projects
– Create model messages
– Configure ActiveMq ConnectionFactory
– Create Jms Producer/Listeners
– Run and check results
1. Create SpringBoot projects
Using SpringToolSuite, create 2 projects SpringBoot projects {SpringActiveMqProducerConsumer, SpringActiveMqSendTo}, then add dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2. Create model messages
Create 2 model classes {Company
, Product
}:
– Company:
package com.javasampleapproach.activemq.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="@id", scope = Company.class)
public class Company {
private String name;
private List products;
public Company(){
}
public Company(String name){
this.name = name;
}
public Company(String name, List products){
this.name = name;
this.products = products;
}
// name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// products
public void setProducts(List products){
this.products = products;
}
public List getProducts(){
return this.products;
}
}
– Product:
package com.javasampleapproach.activemq.model;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="@id", scope = Product.class)
public class Product {
private String name;
private String type;
private Company company;
public Product(){
}
public Product(String name, String type){
this.name = name;
this.type = type;
}
public Product(String name, Company company){
this.name = name;
this.company = company;
}
// name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType(){
return this.type;
}
public void setType(String type){
this.type = type;
}
// products
public void setCompany(Company company){
this.company = company;
}
public Company getCompany(){
return this.company;
}
@Override
public String toString() {
String info = String.format("[name = %s, type = %s]", this.name, this.type);
return info;
}
}
3. Configure ActiveMq ConnectionFactory
– Create ActiveMqConnectionFactoryConfig
file:
package com.javasampleapproach.activemq.config;
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
@Configuration
public class ActiveMqConnectionFactoryConfig {
@Value("${jsa.activemq.broker.url}")
String brokerUrl;
@Value("${jsa.activemq.borker.username}")
String userName;
@Value("${jsa.activemq.borker.password}")
String password;
/*
* Initial ConnectionFactory
*/
@Bean
public ConnectionFactory connectionFactory(){
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(brokerUrl);
connectionFactory.setUserName(userName);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean // Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
/*
* Used for Receiving Message
*/
@Bean
public JmsListenerContainerFactory> jsaFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setMessageConverter(jacksonJmsMessageConverter());
configurer.configure(factory, connectionFactory);
return factory;
}
/*
* Used for Sending Messages.
*/
@Bean
public JmsTemplate jmsTemplate(){
JmsTemplate template = new JmsTemplate();
template.setMessageConverter(jacksonJmsMessageConverter());
template.setConnectionFactory(connectionFactory());
return template;
}
}
4. Create Jms Producer/Listeners
4.1 For SpringActiveMqProducerConsumer project
– Create a Producer:
import javax.jms.JMSException;
import javax.jms.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessagePostProcessor;
import org.springframework.stereotype.Component;
import com.javasampleapproach.activemq.model.Product;
@Component
public class JmsProducer {
@Autowired
JmsTemplate jmsTemplate;
@Value("${jsa.activemq.queue.producer}")
String queue;
public void send(Product product, String companyName){
jmsTemplate.convertAndSend(queue, product, new MessagePostProcessor() {
public Message postProcessMessage(Message message) throws JMSException {
message.setStringProperty("company", companyName);
return message;
}
});
}
}
– Create a Consumer:
package com.javasampleapproach.activemq.jms.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import com.javasampleapproach.activemq.model.Product;
@Component
public class JmsConsumer {
@JmsListener(destination = "${jsa.activemq.queue.consumer}", containerFactory="jsaFactory")
public void appleReceive(Product product, @Header("type") String productType){
if("iphone".equals(productType)){
System.out.println("Recieved Iphone: " + product);
}else if("ipad".equals(productType)){
System.out.println("Recieved Ipad: " + product);
}
}
}
4.2 For SpringActiveMqSendTo project
– Create a JmsReplyConsumer:
package com.javasampleapproach.activemq.jms.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.Message;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import com.javasampleapproach.activemq.model.Company;
import com.javasampleapproach.activemq.model.Product;
@Component
public class JmsReplyConsumer {
@JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory")
@SendTo("${jsa.activemq.queue.sendto}")
public Message receive(Product product, @Header("company") String companyName){
// Console Log
System.out.println("Recieved Message: " + product);
// set company
Company apple = new Company("Apple");
product.setCompany(apple);
Message mesage = MessageBuilder
.withPayload(product)
.setHeader("type", product.getType())
.build();
return mesage;
}
}
5. Run and check results
– Start ActiveMQ server with commandline: C:\apache-activemq-5.14.5>.\bin\activemq start
.
– Build and Run the SpringBoot applications {SpringActiveMqSendTo, SpringActiveMqProducerConsumer} by commandlines: {mvn install -Dmaven.test.skip=true
, mvn spring-boot:run
}
-> Logs of JmsReplyConsumer
from SpringActiveMqSendTo:
Recieved Message: [name = Iphone 7, type = iphone]
Recieved Message: [name = IPadPro, type = ipad]
-> Logs of JmsConsumer
from SpringActiveMqProducerConsumer:
Recieved Iphone: [name = Iphone 7, type = iphone, company = Apple]
Recieved Ipad: [name = IPadPro, type = ipad, company = Apple]
-> With ActiveMQ server, go to http://localhost:8161/admin/queues.jsp
:
IV. Sourcecode
SpringActiveMqProducerConsumer
SpringActiveMqSendTo
Wonderful, what a blog it is! This web site gives helpful facts
to us, keep it up.
3997 486019I enjoy looking by way of and I conceive this site got some truly valuable stuff on it! . 517416
566358 707654A domain name is an identification label which defines a realm of administrative autonomy, authority, or control inside the Internet. Domain names are also critica for domain hostingwebsite hosting 620266
480152 110835Yay google is my king assisted me to uncover this outstanding site! . 574953
976336 666001I likewise conceive thus, perfectly written post! . 489061
This site is usually a walk-through you discover the details you wished with this and didn’t know who must. Glimpse here, and you’ll absolutely discover it.
Thank you for the good critique. Me & my friend were just preparing to do some research on this. We grabbed a book from our area library but I think I’ve learned better from this post. I am very glad to see such wonderful information being shared freely out there..
wonderful post. Ne’er knew this, thankyou for letting me know.
I would really love to guest post on your blog.:;”..
I am often to blogging and that i really appreciate your content regularly. The article has truly peaks my interest. I’m going to bookmark your website and maintain checking for brand spanking new data.
Congratulations on having One of the most sophisticated blogs Ive come throughout using some time! Its just incredible what you can remember from a little something as a result of how visually beautiful it’s. Youve put collectively a good blog space -great graphics, videos, layout. This really is undoubtedly a must-see weblog!
J’ai la possibilité de transférer les sites pour de nouvelles de miniatures sur cet idée. Contactez moi ici meme?
the table beds which we have a year ago had already broken down, it is mostly made up of plastic.,
112041 884819As I web-site possessor I believe the content matter here is rattling amazing , appreciate it for your efforts. You must keep it up forever! Best of luck. 482080
6687 488010But wanna remark that you have a very decent internet site , I adore the style it really stands out. 280925
670088 144459I adore your wp style, wherever did you download it through? 966144