JMS is a Java Enterprise technology that has been implemented to decouple the logic from event producer from event consumers by means of messages. In this tutorial we will learn how we can use Spring Boot to create and consume JMS messages using Artemis MQ broker.

In this example we will start an embedded Artemis MQ server as part of our application and start sending and consuming messages. Apache Artemis MQ is an open source message broker written in Java together with a full Java Message Service (JMS) client.

Creating the project

In order to start, we will need a project which uses artemis dependencies, therefore from the CLI we will execute:

$ spring init -d=artemis artemis -x

Additionally, as we will start ArtemisMQ in embedded mode, we will also need to add as extra dependency "artemis-jms-server":

<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>artemis-jms-server</artifactId>
</dependency>

Here is the final pom.xml file:

<?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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>artemis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

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

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-artemis</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>artemis-jms-server</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

The configuration of the server will be contained in the file application.properties:

spring.artemis.mode=embedded
spring.artemis.embedded.enabled=true
spring.artemis.embedded.queues=springbootQueue
myqueue=springbootQueue

As you can see, we have declared the server mode, that is embedded and we have declared the Queue name that will be used in the project. Now let’s look at the producer that will our main Application class:

package com.example.artemis;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.core.JmsTemplate;

@SpringBootApplication
public class DemoApplication {
	private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

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

	@Value("${myqueue}")
	String queue;

	@Bean
	CommandLineRunner start(JmsTemplate template) {
		return args -> {
			log.info("Sending> ...");

			template.convertAndSend(queue, "Hello World from Spring Boot!");
		};
	}
}

As you can see, it’s declaring a @Bean CommandLineRunner method. This means that it will be executed after the Spring Boot finishes its pre-configuration. Also, this method has the JmsTemplate instance, which will be autowired automatically. The JmsTemplate is will use the convertAndSend method to send an Hello World message.

In order to consume messages, we will be adding a Message Consumer:

package com.example.artemis;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Consumer implements MessageListener{
	private Logger log = LoggerFactory.getLogger(Consumer.class);
	@Override
	public void onMessage(Message message) {
		try {
			log.info("Received message: " + message.getBody(Object.class));
		}catch (JMSException ex) {
			ex.printStackTrace();
		}
	}
}

Within this class, we need:

• implement MessageListener

• Code the method onMessage to receive messages asynchronously.

Finally, you need to do some extra configuration involving how to connect to the ArtemisMQ server:

package com.example.artemis;

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.jms.listener.DefaultMessageListenerContainer;

import javax.jms.ConnectionFactory;

@Configuration
public class MessagingConfig {
	@Autowired
	private ConnectionFactory connectionFactory;
	@Value("${myqueue}")
	private String queue;

	@Bean
	public DefaultMessageListenerContainer messageListener() {
		DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
		container.setConnectionFactory(this.connectionFactory);
		container.setDestinationName(queue);
		container.setMessageListener(new Consumer());
		return container;
	}
}

The @Configuration annotation tells Spring to configure any declared methods annotated with the @Bean annotations.

We have @Autowired a ConnectionFactory for creating a connection with the default user identity to the broker. In this case it will create the connection to the ArtemisMQ server with the default credentials.

Finally, the @Bean messageListener defines a bean that will return a DefaultMessageListenerContainer instance. The DefaultMessageListenerContainer will be responsible for connecting to the queue and listening through the consumer’s MessageListener interface implementation.

That's all. You can run the application with:

$ ./mvnw spring-boot:run

After running the program you should have the logs from the consumer and producer, something similar to this:

INFO 27897 --- [           main] com.example.artemis.DemoApplication      : Started DemoApplication in 2.624 seconds (JVM running for 3.183)
INFO 27897 --- [           main] com.example.artemis.DemoApplication      : Sending> ...
INFO 27897 --- [ssageListener-1] com.example.artemis.Consumer             : Received message: Hello World from Spring Boot!

Congratulations! You have successfully connected an embedded ArtemisMQ server with a Spring Boot consumer/producer!

Continue reading here if you want to learn how to connect to a remote ArtemisMQ server: JMS Messaging with Spring Boot and Remote Artemis MQ