How to send JMS Messages with Spring Boot – Part 1

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 two parts tutorial, we will learn how to send and receive JMS Messages from a Spring Boot application using Apache Artemis MQ .

This tutorial is split in two parts:

  • Part 1: In the first part, we will show how to send JMS Messages using an embedded Artemis MQ Server
  • Part 2: In the next part, we will connect to a remote Artemis MQ Broker. The second part is available here: JMS Messaging with Spring Boot and Remote Artemis MQ

Creating the Project

Firstly, 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>

Next, 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.6.4</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>11</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 . Also, we have configured the list of destinations that we will use in our example. 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 to allow the execution after the Spring Boot finishes its pre-configuration. Also, this method has the JmsTemplate instance, which we use to convertAndSend an Hello World message.

Finally, 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.

Lastly, 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.

Running the Application

Finally, 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:

spring boot messaging

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

The source code for this tutorial (kindly provided by mastertheboss.com is available here)

Found the article helpful? if so please follow us on Socials
Twitter Icon       Facebook Icon       LinkedIn Icon       Mastodon Icon