Spring Jms ActiveMQ – How to create a SpringBoot ActiveMQ Response Management application by @SendTo annotation

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:

SpringBoot ActiveMQ Response Management application - sendto aannotation - architecture


@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;	
}
When having several @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}:

SpringBoot ActiveMQ Response Management application - sendto aannotation - project structure

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:

SpringBoot ActiveMQ Response Management application - sendto aannotation - activemq logs

IV. Sourcecode

SpringActiveMqProducerConsumer
SpringActiveMqSendTo

16 thoughts on “Spring Jms ActiveMQ – How to create a SpringBoot ActiveMQ Response Management application by @SendTo annotation”

  1. 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

  2. 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..

  3. 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.

  4. 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!

  5. 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

Leave a Reply

Your email address will not be published. Required fields are marked *