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
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
Now we can acces to the web page of activeMq on localhost,
by default activemq use admin as username and password 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>
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
-
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;
and we can create a function to send message :
public void sendMessage() throws Exception {
jmsTemplate.convertAndSend("queue.test","Hello world !!");
}
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");
}
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 !!");
}
- 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;
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);
//...
}
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);
}
}
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)
Great article Abdo! Well written and explained!
Thank you brother