In this post under JMS I will explain how to send and receive Java Map data as JMS Message payload.
Note: I will be using JMS 2.0 api for this and future examples
Below is the complete main class code
Main Class
1 package package3;
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 Example3 {
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 created an InitialContext instance and at line 18 I created a ConnectionFactory instance.
At line 19 using the initialContext instance, I lookup for “Destination” instance with name “MyQueue”.
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.
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 Class
1 package package3;
2
3 import javax.jms.ConnectionFactory;
4 import javax.jms.Destination;
5 import javax.jms.JMSContext;
6 import javax.jms.JMSProducer;
7 import javax.jms.MapMessage;
8
9 public class Producer implements Runnable {
10 private Destination destination;
11 private ConnectionFactory connectionFactory;
12
13 public Producer(Destination destination, ConnectionFactory connectionFactory) {
14 this.destination = destination;
15 this.connectionFactory = connectionFactory;
16 }
17
18 @Override
19 public void run() {
20 JMSContext jmsContext = null;
21
22 try {
23 jmsContext = connectionFactory.createContext();
24 MapMessage message = jmsContext.createMapMessage();
25 message.setString("key1", "value1");
26 message.setString("key2", "value2");
27 message.setString("key3", "value3");
28 message.setString("key4", "value4");
29 JMSProducer jmsProducer = jmsContext.createProducer();
30 jmsProducer.send(destination, message);
31 } catch(Exception excep) {
32 excep.printStackTrace();
33 } finally {
34 if(jmsContext != null) {
35 jmsContext.close();
36 }
37 }
38 }
39 }
In the above code, at line 23 I create an instance of JMSContext named “jmsContext” using the connectionFactory.
With the help of jmsContext I create an instance of MapMessage class.
MapMessage is type of message which allows a map object to its payload.
Next from line 25 to 28, I set the key value pairs.
Next we create an instance of JMSProducer.
Next we publish the message by calling “send” method on the jmsProducer. This send method takes two arguments which are
1) Destination object
2) MapMessage instance
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 package3;
2
3 import java.util.Enumeration;
4
5 import javax.jms.ConnectionFactory;
6 import javax.jms.Destination;
7 import javax.jms.JMSConsumer;
8 import javax.jms.JMSContext;
9 import javax.jms.MapMessage;
10
11 public class Consumer implements Runnable {
12 private Destination destination;
13 private ConnectionFactory connectionFactory;
14
15 public Consumer(Destination destination, ConnectionFactory connectionFactory) {
16 this.destination = destination;
17 this.connectionFactory = connectionFactory;
18 }
19
20 @Override
21 public void run() {
22 JMSContext jmsContext = null;
23
24 try {
25 jmsContext = connectionFactory.createContext();
26 JMSConsumer jmsConsumer = jmsContext.createConsumer(destination);
27 MapMessage message = (MapMessage)jmsConsumer.receive();
28
29 Enumeration enumeration = message.getMapNames();
30 while(enumeration.hasMoreElements()) {
31 String key = (String)enumeration.nextElement();
32 System.out.println(key + ":" + message.getString(key));
33 }
34 jmsConsumer.close();
35 } catch(Exception excep) {
36 excep.printStackTrace();
37 } finally {
38 if(jmsContext != null) {
39 jmsContext.close();
40 }
41 }
42 }
43 }
In the above code, at line 25, I create an instance of JMSContext named “jmsContext” using the connectionFactory.
At line 26, we create an instance of JMSConsumer using jmsContext.
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.
Once we receive the message we cast it to an instance of MapMessage as shown at line 27.
From line 29 to 33 we loop through the map entries.
In this way we can send and receive Java Map data in JMS messages.