Spring Boot Jms ActiveMQ Example

Spring Boot Jms ActiveMQ Example thumbnail
227K
By Dhiraj 12 December, 2017

This article is about spring boot and JMS integration. Here we will be using spring boot features to implement asynchronous messaging service. We wil be using activemq as a message broker and look into different support provided by spring boot while integrating JMS with activemq. The application that we will be creating here will be a simple spring jms activemq example with a sample JMS producer and consumer.

If you are looking for spring 4 and JMS integration with activemq then follow - Spring JMS ActiveMq Exmple

Spring Boot ActiveMQ Support

Spring boot automatically configures connectionfactory if it detects ActiveMQ on the classpath. In this case, it also makes use of embedded broker if does not find any ActiveMQ custom configurations in application.properties. Here in this example we will have activemq configurations outside the application but we will also look into ways to integrate embedded activemq with spring boot by defining our JMS configurations in application.properties. So let us get started with defining the project structure first.

Project Structure

spring-boot-jms-activemq

Maven Dependencies

spring-boot-starter-activemq : It provides all the required dependencies to integrate JMS and activemq with spring boot.

activemq-broker : This provides embedded activemq in spring boot application. But since, we will be configuring our activemq outside the application we have commented it for time being.

spring-boot-maven-plugin : It will collect all the jar files present in the classpath and create a single executable jar.

pom.xml
	<groupId>com.devglan</groupId>
    <artifactId>spring-boot-jms</artifactId>
    <version>0.1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>
	
    <dependencies>
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
		
<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-broker</artifactId> </dependency>
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Other Interesting Posts
Spring JMS ActiveMQ Example
Spring Boot Actuator Complete Guide
Spring Boot Security Hibernate Example
Spring Mvc Anglar Js Example
Working with Spring Boot Jdbc Template
Spring Boot Security Password Encoding using Bcrypt Encoder
Websocket spring Boot Integration Without STOMP

Configuring ActiveMQ in Spring Boot

Following is the application.properties which has configurations for activemq. Here we are configuring the tcp broker url along with the username and password required to make activemq connection

application.properties
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

Configuring Spring Beans for JMS(Not Required)

While integrating JMS and ActiveMQ with spring boot, no extra configuratins specific to JmsTemplate or containerFactory is required. The following configurations will be implicitly provided by spring boot for us. Hence, the following class is not available in the source. I am including these configurations just to show you guys how Spring Boot helps to get rid of boiler plate codes and configurations.

@Configuration
public class JmsConfig {

	String BROKER_URL = "tcp://localhost:61616"; 
	String BROKER_USERNAME = "admin"; 
	String BROKER_PASSWORD = "admin";
	
	@Bean
	public ActiveMQConnectionFactory connectionFactory(){
	    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
	    connectionFactory.setBrokerURL(BROKER_URL);
	    connectionFactory.setPassword(BROKER_USERNAME);
	    connectionFactory.setUserName(BROKER_PASSWORD);
	    return connectionFactory;
	}

	@Bean
	public JmsTemplate jmsTemplate(){
	    JmsTemplate template = new JmsTemplate();
	    template.setConnectionFactory(connectionFactory());
	    return template;
	}

	@Bean
	public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
	    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
	    factory.setConnectionFactory(connectionFactory());
	    factory.setConcurrency("1-1");
	    return factory;
	}

}

JMS Listener

@JmsListener:It marks a method to be the target of a JMS messagelistener on the specified destination. In our case the destination is inbound.queue.This class is responsible to listen messsage from the inbound queue and process the same.

@SendTo annotation will take care of sending the return value of receiveMessage() to the destination defined in @SendTo.

Listener.java
@Component
public class Listener {

	@JmsListener(destination = "inbound.queue")
	@SendTo("outbound.queue")
	public String receiveMessage(final Message jsonMessage) throws JMSException {
		String messageData = null;
		System.out.println("Received message " + jsonMessage);
		String response = null;
		if(jsonMessage instanceof TextMessage) {
			TextMessage textMessage = (TextMessage)jsonMessage;
			messageData = textMessage.getText();
			Map map = new Gson().fromJson(message, Map.class);
			response  = "Hello " + map.get("name");
		}
		return response;
	}

}

JMS Producer

Spring boot provides a very convenient way to send message to a destined queue.Since the introduction of @SendTo annotation, it only requires the queue name in the parameter to send messages.Annotating any method with @SendTo annotation ensures the returning object of the method will be pushed to the queue.

As we are using the annotation @SendTo, we don't require any specific Producer class in this scenario. But below is a snippet of Producer class from the previous article in case you have a use case to define a custom Producer class.

@Component
public class Producer {

	@Autowired
	JmsTemplate jmsTemplate;

	public void sendMessage(final String queueName, final String message) {
		Map map = new Gson().fromJson(message, Map.class);
		final String textMessage = "Hello" + map.get("name");
		System.out.println("Sending message " + textMessage + "to queue - " + queueName);
		jmsTemplate.send(queueName, new MessageCreator() {

			public Message createMessage(Session session) throws JMSException {
				TextMessage message = session.createTextMessage();
				return message;
			}
		});
	}

}

Working with JMS Topic

Spring boot provides above discussed default behaviours to work with messaging queue.But to deal with topic in Spring JMS, we require to manually tell spring to enable it. For this, we either require to set the boolean flag i.e. pubSubDomain to true in JMSConfig.java or add below key value pair in application.properties. Set pubSubDomain to true for the bean definition of JmsTemplate and DefaultJmsListenerContainerFactory. Following are the changes we require to do.

JMSConfig.java
template.setPubSubDomain(true);
factory.setPubSubDomain(true);
application.properties
spring.jms.pub-sub-domain=true

Once this is done, rest of the configuration remain same and in place of listening from a queue our aplication can start listening from the topic and publish message to a topic.Following are the lines I have added to consume message from a topic in Listener.java.

@JmsListener(destination = "inbound.topic")
	@SendTo("outbound.topic")
	public String receiveMessageFromTopic(final Message jsonMessage) throws JMSException {
		String messageData = null;
		System.out.println("Received message " + jsonMessage);
		String response = null;
		if(jsonMessage instanceof TextMessage) {
			TextMessage textMessage = (TextMessage)jsonMessage;
			messageData = textMessage.getText();
			Map map = new Gson().fromJson(message, Map.class);
			response  = "Hello " + map.get("name");
		}
		return response;
	}

Once this configuration is done and appliation is deployed you can see the following topics under topics menu.

jms-activemq-topic

Spring Bean Configuration

@SpringBootApplication Equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes:

Application.java
package com.devglan.tiles;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;

@SpringBootApplication
@EnableJms
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Installing Apache ActiveMq

ActiveMq by default exposes a broker url tcp://localhost:61616 and an admin console on tcp://localhost:61616 with userId and password as admin and admin. Following are the steps to download and install activemq. 1. Download apache activemq from here as per your operating system. 2. Extract under some folder. In my case it's under java\apache-activemq-5.11.1-bin. 3. Now traverse to java\apache-activemq-5.11.1-bin\bin\win64 and execute the acivemq.bat file. 4. Open the browser and hit - http://localhost:8161/admin/ 4. Enter userId/password as admin/admin. Then following screen will appear:

activemq-connect

5. Now click on the queues option present in menu bar and you can notice there are no queues available as below image.

activemq-queues

Run Application

1. Run Application.java as a java applicaton and you can see one queue automatically created with name inbound.queue which we had configured in our Listener.class. Refresh the page after application restart.

activemq-queue-creation

2. Our application is now listening to this queue and whenever we push messsage to this queue our Listener should automatically pick this message. Now click on the send To option. Enter a JSON string as {"name":"John"} and click on send.

activemq-send-message

3. After the messsage is sent, the message is received by Listener.java and the same message will be processed and send back to outbound.queue by Producer.java. Now you can see one more queue created once you click on the queues option from the menu as shown below:

activemq-message

Also, you can check logs in the console.

Conclusion

This demonstrates a simple JMS integration. It is very useful in a mechanism to allow asynchronous request processing. You may wish to implement JMS because the request take a long time to complete or because several parties may be interested in the actual request. Another reason for using it is to allow multiple clients (potentially written in different languages) to access information via JMS.

I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Share

If You Appreciate This, You Can Consider:

We are thankful for your never ending support.

About The Author

author-image
A technology savvy professional with an exceptional capacity to analyze, solve problems and multi-task. Technical expertise in highly scalable distributed systems, self-healing systems, and service-oriented architecture. Technical Skills: Java/J2EE, Spring, Hibernate, Reactive Programming, Microservices, Hystrix, Rest APIs, Java 8, Kafka, Kibana, Elasticsearch, etc.

Further Reading on Spring Boot