JMS 2.0 Simple Example

In this post, I will explain how to use JMS api with simple example.

Note: I will be using JMS 2.0 api for this and future examples.

Below is the complete main code

Main Class


1  package package1;
2  
3  import java.util.Properties;
4  
5  import javax.jms.ConnectionFactory;
6  import javax.jms.Destination;
7  import javax.jms.JMSException;
8  import javax.naming.Context;
9  import javax.naming.InitialContext;
10 import javax.naming.NamingException;
11 
12 public class Example1 {
13  public static void main(String[] args) throws NamingException, JMSException {
14      Properties env = new Properties();
15      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
16      env.put(Context.PROVIDER_URL, "file:///C:/openmq5_1_1/temp");
17      InitialContext initialContext = new InitialContext(env);
18      ConnectionFactory connectionFactory = (ConnectionFactory)initialContext.lookup("MyConnectionFactory");
19      Destination destination = (Destination)initialContext.lookup("MyQueue");
20      
21      Producer producer = new Producer(destination, connectionFactory);
22      Consumer consumer = new Consumer(destination, connectionFactory);
23      
24      Thread producerThread = new Thread(producer);
25      Thread consumerThread = new Thread(consumer);
26      
27      producerThread.start();
28      consumerThread.start();
29      
30      initialContext.close();
31  }
32 }

At line 14 I have created Properties object to populate it with INITIAL_CONTEXT_FACTORY and PROVIDER_URL.

The value of these keys vary based on the JMS provider. So please consult your specific JMS provider for more details on this.

For the example I am using OpenMessageQueue 5.1 JMS provider.

At line 17 I create an InitialContext and at line 18 I create a ConnectionFactory instance.

At line 19 using the initialContext instance, I lookup for “Destination” instance with name “MyQueue”.

Destination class is a super class of “Queue” and “Topic” classes. Queue class represents the physical queue for point to point messaging, whereas Topic class represents the physical topic for publish-subscribe messaging.

My example follows point to point messaging.

At line 21 I created a “Producer” instance and at line 22 “Consumer” instance. Both the classes implements the Runnable interface. Producer will create and publish a message which will be consumed by Consumer.

To both instance I will pass the destination and connectionFactory instance.

The Destination class and ConnectionFactory are thread safe in other words they can be accessed by multiple threads.

At line 24 I associate “producer” instance with “producerThread” instance and at line 25 I associate “consumer” instance with “consumerThread”.

At line 27 and 28 I start the producerThread and consumerThread.

Now we will look into the Producer class. Below is the complete code of Producer class

Producer


1  package package1;
2  
3  import javax.jms.ConnectionFactory;
4  import javax.jms.Destination;
5  import javax.jms.JMSContext;
6  import javax.jms.JMSProducer;
7  
8  public class Producer implements Runnable {
9   private Destination destination;
10  private ConnectionFactory connectionFactory;
11  
12  public Producer(Destination destination, ConnectionFactory connectionFactory) {
13      this.destination = destination;
14      this.connectionFactory = connectionFactory;
15  }
16  
17  @Override
18  public void run() {
19      JMSContext jmsContext =  null;
20      
21      try {
22          jmsContext = connectionFactory.createContext();
23          JMSProducer jmsProducer = jmsContext.createProducer();
24          jmsProducer.send(destination, "Hello World");
25      } catch(Exception excep) {
26          excep.printStackTrace();
27      } finally {
28          if(jmsContext != null) {
29              jmsContext.close();
30          }
31      }
32  }
33 }

At line 22 I create an instance of JMSContext. JMSContext is newly added interface and contains a reference to both Connection and Session object. In other words
a JMSContext represents an active connection to JMS provider and an active session.

Earlier we used to create Connection and Session objects separately but from JMS 2.0 onwards, we just have to create an instance of JMSContext. The JMSContext when getting created is populated with Connection and Session object.

Next we create an instance of JMSProducer. This interface is newly added and it replaces the old MessageProducer, QueueSender, and TopicPublisher.

Next we publish the message by calling “send” method on the jmsProducer. This send method takes two arguments which are

1) Destination object
2) The message in string format.

They are other overloaded versions of send method which you can refer in java doc.

Now we will look into the Consumer class. Below is the complete code of Consumer class

Consumer


1  package package1;
2  
3  import javax.jms.ConnectionFactory;
4  import javax.jms.Destination;
5  import javax.jms.JMSConsumer;
6  import javax.jms.JMSContext;
7  import javax.jms.Message;
8  import javax.jms.TextMessage;
9  
10 public class Consumer implements Runnable {
11  private Destination destination;
12  private ConnectionFactory connectionFactory;
13  
14  public Consumer(Destination destination, ConnectionFactory connectionFactory) {
15      this.destination = destination;
16      this.connectionFactory = connectionFactory;
17  }
18  
19  @Override
20  public void run() {
21      JMSContext jmsContext =  null;
22      
23      try {
24          jmsContext = connectionFactory.createContext();
25          JMSConsumer jmsConsumer = jmsContext.createConsumer(destination);
26          Message message = jmsConsumer.receive();
27          System.out.println(((TextMessage)message).getText());
28      } catch(Exception excep) {
29          excep.printStackTrace();
30      } finally {
31          if(jmsContext != null) {
32              jmsContext.close();
33          }
34      }       
35  }
36 }

At line 24 I create an instance of JMSContext.

Next we create an instance of JMSConsumer. This interface is newly added and it replaces the old MessageConsumer, QueueReceiver, and TopicSubscriber.

Next we receive the message by calling “receive” method on the jmsConsumer.

They are other overloaded versions of receive method which you can refer in java doc.

This version of receive is synchronous meaning it will block the current thread and wait till it receives the message.

In this way we can use the new JMS 2.0 api.

Leave a Reply