In this section, first, we will go through the basics of Java Messaging Service and will see the differences between JMS and e-mail. Then, we will look into the JMS application and its different components that create the complete JMS application. We will also look through other things such as the JMS provider and the messaging model. We will dig into the API programming model. Then, we will see the messaging consumption types. Then, we will jump into the Spring JMS integration and we will see some code samples. And then, we will look into the details of the code content.
Let's now discuss the message and messaging.
A message is nothing but just bytes of data or information exchanged between two parties. By taking different specifications, a message can be described in various ways. However, it is nothing but an entity of communication. A message can be used to transfer a piece of information from one application to another application, which may or may not run in the same platform.
Messaging is the communication between different applications (in a distributed environment) or system components, which are loosely coupled unlike its peers such as TCP sockets, Remote Method Invocation (RMI), or CORBA, which is tightly coupled. The advantage of Java messaging includes the ability to integrate different platforms, increase the scalability and reliability of message delivery, and reduce the system bottlenecks. Using messaging, we can increase the systems and clients who are consuming and producing the message as much as we want.
We have quite a lot of ways in which we communicate right from the instance messenger, to the stock taker, to the mobile-based messaging, to the age-old messaging system; they are all part of messaging. We understand that a message is a piece of data transferred from one system to another and it can be between humans as well, but it is mainly between systems rather than human beings when we talk about the messaging using JMS.
The Java Message Service (JMS) is a Java Message Oriented Middleware (MOM) API for sending messages between two or more clients. JMS is a part of the Java Enterprise edition. JMS is a broker like a postman who acts like a mediator between the message sender and receiver.
JMS is a specification that describes a common way for Java programs to create, send, and read distributed enterprise messages. It advocates the loosely coupled communication without caring about the sender and the receiver. It provides asynchronous messaging, which means that it doesn't matter whether the sender and the receiver are present at the same time or not. The two systems that are sending or receiving messages need not be up at the same time.
Let's look into the sample JMS application pictorial as shown in the following figure:
We have a Sender and a Receiver. The Sender sends a message while the Receiver receives one. We need a broker that is MOM between the Sender and the Receiver who takes the sender's message and passes it to the network to the receiver. MOM is basically an MQ application such as ActiveMQ or IBM-MQ, which are two different message providers. The Sender promises the loose coupling and it can be a .NET or mainframe-based application. The Receiver can be a Java or Spring-based application, and it sends back the message to the Sender as well. This is a two-way communication that is loosely coupled.
Let's move on the JMS components listed in the following table:
Here is the pictorial representation:
There are three JMS clients in the preceding figure. The Producer can be assumed as it's you who is going to send a message to your friend. The Consumer can be assumed to be your friend who will receive a message. The Producer/Consumer could be someone else who will receive as well as send a message. The JMS Provider can be assumed as the post office or postman via which the whole delivery things happen and which guarantee that the sure delivery happens only once.
There are various MOM Service Provider products; some of them are listed in the following table:
Product |
Company |
---|---|
WebLogic |
Oracle |
MQ Series |
IBM |
JBOSSMQ |
JBOSS |
SoniqMQ |
Progress |
ActiveMQ |
Apache |
We will mainly look into the ActiveMQ message queue. The Active MQ is from Apache, and it's free.
We need to follow the given steps to configure ActiveMQ to our system:
activemq-5.10.0in
folder, inside which you will find the following folders:activemq-5.10.0in for 64 bit
activemq-5.10.0in for 32 bit
These folders can be seen in the following screenshot:
win32
or win64
folder based on your machine, and open Command Prompt at this location and then run activemq
, as shown here:
We can see in the preceding screenshot, that activemq
is run and has provided some information on the console. This MQ can be listed at tcp://localhost:61616 URL
. The admin page URL http://localhost:8161/admin
provides access to the admin page (username: admin
, password: admin
):
Create the configuration file Spring.xml
and define the respective bean definitions such as ActiveMQ ConnectionFactory, ActiveMQ queue destination, and JMS template as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jms="http://www.springframework.org/schema/jms" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"> <context:component-scan base-package="org.packt.Spring.chapter10.JMS" /> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="defaultDestination" ref="destination" /> </bean> <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL"> <value>tcp://localhost:61616</value> </property> </bean> <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg value="myMessageQueue" /> </bean> </beans>
The Spring Framework supports JMS with the help of the following classes:
ActiveMQConnectionFactory
: This will create a JMS ConnectionFactory for ActiveMQ that connects to a remote broker on a specific host name and portActiveMQQueue
: This will configure the ActiveMQ queue name as in our case myMessageQueue
JmsTemplate
: This is a handy abstraction supported by Spring, and it allows us to hide some of the lower-level JMS details while sending a messageThe MessageSender
class is responsible for sending a message to the JMS queue:
package org.packt.Spring.chapter10.JMS.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Component; @Component public class MessageSender { @Autowired private JmsTemplate jmsTemplate; public void send(final Object Object) { jmsTemplate.convertAndSend(Object); } }
The App
class contains the main method, which calls the send()
method to send a message, as shown in the following code snippet:
package org.packt.Spring.chapter10.JMS.Main; import java.util.HashMap; import java.util.Map; import org.packt.Spring.chapter10.JMS.Message.MessageSender; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "Spring.xml"); MessageSender messageSender = (MessageSender) context .getBean("messageSender"); Map<String, String> message = new HashMap<String, String>(); message.put("Hello", "World"); message.put("city", "Sasaram"); message.put("state", "Bihar"); message.put("country", "India"); messageSender.send(message); System.out.println("Message Sent to JMS Queue: " + message); } }
Before you run
App.java
, you need to start ActiveMQ, which allows us to run a broker; it will run ActiveMQ Broker using the out-of-the-box configuration.
Run App.java
and get the output on the console as follows:
Message Sent to JMS Queue: {state=Bihar, Hello=World, country=India, city=Sasaram}
We can monitor ActiveMQ Broker using the web console by pointing the browser to http://localhost:8161/admin
. Once app.java
gets executed, a message will be sent to the JMS queue, as shown in the following screenshot:
There are chances of getting the error Could not connect to broker URL exception: tcp://localhost:61616. Reason: Java.net.ConnectException: Connection refused: connect
. This exception will come if the message broker service is not up, so make sure that ActiveMQ is running, as shown here:
Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused: connect at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316)