This tutorial will show you how you can build Spring based application with Apache ActiveMQ for point-to-point messaging domain. In point to point messaging domain you have only one message producer and only one message consumer. For more information on point-to-point messaging system
please read tutorial https://roytuts.com/configure-jms-client-using-glassfish-3/
As the ActiveMQ will be started in embedded mode, so you won’t be able to see the message in the ActiveMQ admin console.
Now you will look into the following steps in order to implement point-to-point messaging system
using Spring and embedded ActiveMQ.
Prerequisites
Java at least 8, Spring Boot 2.4.3, Maven 3.6.3
Project Setup
You can create maven based project in your favorite IDE or tool. The name of the project is spring-jms-embedded-apache-activemq.
The pom.xml file with required dependency is given below:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>spring-jms-embedded-apache-activemq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Message Producer
In point to point messaging domain you need message produces that will produce message.
package com.roytuts.spring.jms.apache.activemq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class MessageProducer {
@Autowired
private JmsTemplate jmsTemplate;
public void sendMessageToDestination(final String message) {
jmsTemplate.convertAndSend(message);
}
}
Message Consumer
There is one message consumer that consumes messages produced by the message producer.
package com.roytuts.spring.jms.apache.activemq;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;
@Component
public class MessageConsumer implements MessageListener {
@Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String msg = ((TextMessage) message).getText();
System.out.println("Message has been consumed : " + msg);
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
} else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
App Configuration
Create a file application.properties under src/main/resources folder with the following key/value pairs. Here I have specified message broker URL and destination queue name. The queue is used in the point-to-point messaging domain whereas topic is used in the publish/subscribe domain.
jms.broker.url=tcp://localhost:61616
jms.queue.name=IN_QUEUE
You need to configure various Spring beans for connectionfactory, jms template, destination, etc. I am showing you embedded ActiveMQ, so I am creating the BrokerService bean for this.
package com.roytuts.spring.jms.apache.activemq;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.listener.DefaultMessageListenerContainer;
import org.springframework.jms.listener.MessageListenerContainer;
@Configuration
@PropertySource("classpath:application.properties")
public class JmsConfig {
@Value("${jms.broker.url}")
private String brokerUrl;
@Value("${jms.queue.name}")
private String queueName;
@Autowired
private MessageConsumer messageConsumer;
@Bean
public BrokerService broker() throws Exception {
BrokerService broker = new BrokerService();
broker.addConnector(brokerUrl);
broker.setPersistent(false);
return broker;
}
@Bean
public ConnectionFactory connectionFactory() {
return new CachingConnectionFactory(new ActiveMQConnectionFactory(brokerUrl));
}
@Bean
public Destination destination() {
return new ActiveMQQueue(queueName);
}
@Bean
public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory, Destination destination) {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setDefaultDestination(destination);
return jmsTemplate;
}
@Bean
public MessageListenerContainer defaultMessageListenerContainer(ConnectionFactory connectionFactory,
Destination destination) {
DefaultMessageListenerContainer defaultMessageListenerContainer = new DefaultMessageListenerContainer();
defaultMessageListenerContainer.setConnectionFactory(connectionFactory);
defaultMessageListenerContainer.setDestination(destination);
defaultMessageListenerContainer.setMessageListener(messageConsumer);
return defaultMessageListenerContainer;
}
}
Main Class
A class is having @SpringBootApplication
and main method enough to deploy the application using Spring Boot framework.
package com.roytuts.spring.jms.apache.activemq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringJmsApacheActiveMqApp implements CommandLineRunner {
@Autowired
private MessageProducer messageProducer;
public static void main(String[] args) {
SpringApplication.run(SpringJmsApacheActiveMqApp.class, args);
}
@Override
public void run(String... args) throws Exception {
messageProducer.sendMessageToDestination("Send this message to destination");
}
}
Testing the Application
Now you can start your Spring boot application by running the main class. You will see the following output on the console:
Message has been consumed : Send this message to destination
You won’t be able to check the ActiveMQ console as the Apache ActiveMQ is running in embedded mode. In the console you will see that the connector started Connector tcp://127.0.0.1:61616 started
.
That’s all about how to work with Spring and embedded Apache ActiveMQ for JMS.