DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Sending message asynchronously (JSM)
Abdelouahedd
Abdelouahedd

Posted on

Sending message asynchronously (JSM)

JMS is a Java standard that defines a common API for working with message brokers.

First introduced in 2001, JMS has been the go-to approach for asynchronous messaging
in Java for a very long time.

JSM components :

Jms provide multiple entities :

  • Jms provider : broker of messages
  • Jms client : component Jms that can produce or consume a message
  • Message : Data that can exchange between component Jms

JMS mode comunication :

JMS defines two modes for message delivery:

  • Point to point : in this mode a message is sent by a producer and is recieved by a single consumer. The support used for the implementation of this mode is the Queue.
  • Publish/subscribe : in this mode a message is sent by a producer and is reciebed by a single o multiple consumers. The support used for the implementation of this mode is the Topic.

Jms support multiple type of message (Text,Object,Stream octet,Map)

In the schema apove I explain how we can use Jms with activemq as broker

JMS communication schema

Setting up JMS:

  • First we have to run a broker in my case I use activeMq
    you can download the file zip and after extract the file you can acces to the bin foler and run

    $ ./activemq console
    

    activemq-run

    Now we can acces to the web page of activeMq on localhost,
    by default activemq use admin as username and password

    Iactivemq-web-page

  • After config the broker we can now create a spring boot application, and add some essiential dependencies to pom.xml for using jms and activemq

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
Enter fullscreen mode Exit fullscreen mode
Property Description
spring.activemq.broker-url The URL of the broker
spring.activemq.user The user for accessing the broker (optional)
spring.activemq.password The password for accessing the broker (optional)

in the application.yml of spring application we can implement does properties :

  spring:
    activemq:
    broker-url: tcp://127.0.0.1:8161
    user: admin
    password: admin
Enter fullscreen mode Exit fullscreen mode
  • After config the application we can now sending messages by using JmsTemplate that provide by spring.JmsTemplate eliminates a lot of boiler plate code that would otherwise be required to work with JMS.
    JmsTemplate has several methods that are useful for sending messages, including the following:

      // Send raw messages
      void send(MessageCreator messageCreator) throws JmsException;
      void send(Destination destination, MessageCreator messageCreator) throws JmsException;
      void send(String destinationName, MessageCreator messageCreator) throws JmsException;
      // Send messages converted from objects
      void convertAndSend(Object message) throws JmsException;
      void convertAndSend(Destination destination, Object message) throws JmsException;
      void convertAndSend(String destinationName, Object message) throws JmsException;
    

To use jmsTemplate we can just inject a bean of type JmsTemplate

    @Autowired
    private JmsTemplate jmsTemplate;
Enter fullscreen mode Exit fullscreen mode

and we can create a function to send message :

    public void sendMessage() throws Exception {
          jmsTemplate.convertAndSend("queue.test","Hello world !!");
    }
Enter fullscreen mode Exit fullscreen mode

as we can see in the code we use convertAndSend function to send a message to the queue (destination) queue.test
We can also create Destination by create function in a config class the return bean type Destination

    @Bean
    public Destination destination() {
      return new ActiveMQQueue("queue.test");
    }
Enter fullscreen mode Exit fullscreen mode

After create the bean we can use it in differante component

    @Autowired
    private Destination destination;
    @Autowired
    private JmsTemplate jmsTemplate;

    public void sendMessage() throws Exception {
            jmsTemplate.convertAndSend(destination,"Hello world !!");
    }
Enter fullscreen mode Exit fullscreen mode
  • Now it came the time to consume our message and we can do it by using jmsTemple with specifique functions that provide for us to recieve a message
    Message receive() throws JmsException;
    Message receive(Destination destination) throws JmsException;
    Message receive(String destinationName) throws JmsException;
    Object receiveAndConvert() throws JmsException;
    Object receiveAndConvert(Destination destination) throws JmsException;
    Object receiveAndConvert(String destinationName) throws JmsException;
Enter fullscreen mode Exit fullscreen mode

The receive() methods receive a raw Message, whereas the receiveAndConvert() methods use a configured message converter to convert messages into domain types.And for each of these, you can specify either a Destination or a String containing the destination name.

    @Autowired
    private Destination destination;
    @Autowired
    private JmsTemplate jmsTemplate;

    public void consumeMessage(Message message) throws Exception {
            Message message = jmsTemplate.receiveAndConvert(destination);
            //...
    }
Enter fullscreen mode Exit fullscreen mode

and we can also use a message listener by annotad a method in a component with @JmsListener.

    @Service
    public class Reciever{
      @JmsListener(destination = "queue.test")
      public void reciever(@Payload Message msg) throws JMSException {
          String message = ((TextMessage) msg).getText();
          System.out.println(message);
      }
    }
Enter fullscreen mode Exit fullscreen mode

The reciever() method is annotated with JmsListener to β€œlisten” for messages on the "queue.test" destination. It doesn’t deal with JmsTemplate, nor is it explicitly invoked by your application code. Instead, framework code within Spring waits for messages to arrive on the specified destination, and when they arrive, the reciever() method is invoked automatically with the message’s Message payload as a parameter.

Top comments (2)

Collapse
xrio profile image
Elattar Saad

Great article Abdo! Well written and explained!

Collapse
abdelouahedd profile image
Abdelouahedd Author

Thank you brother

🌚 Browsing with dark mode makes you a better developer by a factor of exactly 40.

It's a scientific fact.