JMS Over HTTP Using OpenMQ (Sun Java System Message Queue and HTTP Tunneling)
Join the DZone community and get the full member experience.
Join For FreeYou may have already faced a situation where you need to have messaging capabilities in your application while your client application runs in an environment, which you have no control over its network configuration and restrictions. Such situation lead to the fact that you can not use JMS communication over designated ports like 7676 and so.
You may simply put JMS away and follow another protocol or even plain HTTP communication to address your architecture and design requirement, but we can not easily put pure JMS API capabilities away as we may need durable subscription over a proven and already well tested and established design and architecture. Different JMS implementation providers provide different type capabilities to address such a requirement. ActiveMQ provide HTTP and HTTPS transport for JMS API and described it here.
OpenMQ provide different transport protocol and access channels to access OpenMQ functionalities from different prgramming . One of the access channles which involve HTTP is named Universal Message Service (UMS) which provide a simple REST interaction template to place messages and comsume them from any programming language and device which can interact with a network server. UMS has some limitations which is simply understandable based on the RESTful nature of UMS. For current version of OpenMQ, it only supports Message Queues as destinations so there is no publish-subscribe functionality available.
Another capability which involve HTTP is JMS over HTTP or simply JMS HTTP tunneling. OpenMQ JMS implementation supports HTTP/s as transport protocol if we configure the message broker properly. Well I said the JMS implementation support HTTP/S as a transport protocol which means we as user of the JMS API see almost no difference in the way that we use the JMS API. We can use publish-subscribe, point to point, durable subscription, transaction and whatever provided in the JMS API.
First, lets overview the OpenMQ installation and configuration then we will take a look at an example to see what changes between using JMS API and JMS API over HTTP transport. Installation process is as follow:
- Download OpenMQ from https://mq.dev.java.net/ it should be a zip which is different for each platform.
- Install the MQ by unzipping the above file and running ./installer or installer.bat or so.
- After the installation completed, go to install_folder/var/mq/instances/imqbroker/props and open the config.properties in a text editor like notepad or emeditor or gedit.
- Add the following line to the end of the above file:
OpenMQ project provides a Java EE web application which interact with OpenMQ broker from one side and Sun JMS implementation on the other side. Interaction of this application with the client and MQ broker is highly customizable in different aspects like Broker port number, client poll inrval, Broker address and so on.
imq.service.activelist=jms,admin,httpjms
Now let's see how we can publish some messages, this sample code assume that we have configured the message broker and assumes that we have the following two JAR files in the classpath. These JAR files are available in install_folder/mq/lib/
- imq.jar
- jms.jar
Now the Publisher code:
public class Publisher {
public void publish(String messageContent) {
try {
String addressList = "http://127.0.0.1:8080/imqhttp/tunnel";
com.sun.messaging.TopicConnectionFactory topicConnectionFactory = new com.sun.messaging.TopicConnectionFactory();
topicConnectionFactory.setProperty(com.sun.messaging.ConnectionConfiguration.imqAddressList, addressList);
javax.jms.Topic top;
javax.jms.Connection con = topicConnectionFactory.createTopicConnection("admin", "admin");
javax.jms.Session session = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
top = session.createTopic("DIRECT_TOPIC");
MessageProducer prod = session.createProducer(top);
Message textMessage = session.createTextMessage(messageContent);
prod.send(textMessage);
prod.close();
session.close();
con.close();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
public static void main(String args[]) {
Publisher p = new Publisher();
for (int i = 1; i < 10; i++) {
p.publish("Sample Text Message Content: " + i);
}
}
}
As you can see the only difference is the connection URL which uses http instead of mq and point to a Servlet container address instead of pointing to the Broker listening address.
The subscriber sample code follow a similar pattern. Here I write a sample durable subscriber so you can see that we can use durable subscribtion over HTTP. But you should note that HTTP transport uses polling and continuesly open communication channel which can introduce some overload on the server.
class SimpleListener implements MessageListener {
public void onMessage(Message msg) {
System.out.println("On Message Called");
if (msg instanceof TextMessage) {
try {
System.out.print(((TextMessage) msg).getText());
} catch (JMSException ex) {
ex.printStackTrace();
}
}
}
}
public class Subscriber {
/**
* @param args the command line arguments
*/
public void subscribe(String clientID, String susbscritpionID) {
try {
// TODO code application logic here
String addressList = "http://127.0.0.1:8080/imqhttp/tunnel";
com.sun.messaging.TopicConnectionFactory topicConnectionFactory = new com.sun.messaging.TopicConnectionFactory();
topicConnectionFactory.setProperty(com.sun.messaging.ConnectionConfiguration.imqAddressList, addressList);
javax.jms.Topic top;
javax.jms.Connection con = topicConnectionFactory.createTopicConnection("admin", "admin");
con.setClientID(clientID);
javax.jms.Session session = con.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
top = session.createTopic("DIRECT_TOPIC");
TopicSubscriber topicSubscriber = session.createDurableSubscriber(top, susbscritpionID);
topicSubscriber.setMessageListener(new SimpleListener());
con.start();
} catch (JMSException ex) {
ex.printStackTrace();
}
}
public static void main(String args[]) {
Subscriber sub = new Subscriber();
sub.subscribe("C19", "C1_011");
}
}
Now how you can test the entire example and monitor the MQ? it is very simple by utilizing the provided tools.
Do the following steps to test the overall durable subscription system:
- Run a subscriber
- Run another subscriber with a different client ID
- Run a publisher once or twice
- Kill the second subscriber
- Run a publisher once
- Run the subscriber and you can see that the subscriber will fetch all messages which arrived after it shut down-ed.
Note that we can not have two separate client with same client ID running because the broker will not be able to distinguish which client it should send the messages.
The sample code for this entry can be found Here. The sample code is a NetBeans project with the publisher and the subscriber source code. A complete documentation of OpenMQ is available at its documentation centre. You can see how you can change different port numbers or configure different properties of the Broker and HTTP tunneling web application communication. |
Published at DZone with permission of Masoud Kalali. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments