JMS- Java Message Service is a standard that allows applications to send, receive, create and delete the messages.

Let us go through some basics of JMS before delving in to the code…

JMS was designed by Sun and several partner companies to standardize the messaging. It defines a common set of interfaces and associated semantics that allow programs written in the Java programming language to communicate with other messaging implementations.

Why JMS?
JMS makes life easy for a programmer while writing complex messaging components. Any JMS implementation promises maximum portability, asynchronous delivery of messages and reliable communication directly out of the box. JMS supports both point to point and publish/subscribe methods. Those who have written some basic socket programming to achieve the same would be able to appreciate JMS.

A few JMS elements we need to understand…

A JMS provider is the one who provides the implementation of the JMS interface.
A JMS client is an application that produces and/or receives messages
A JMs producer is an application that publishes the messages
A JMS consumer is an application that receives messages
A JMS message is a standard message which contains the data that needs to be transferred.
A JMS queue is where the messages are sent by the producer so that they get consumed by the consumer. Please note that this is a point to point solution. So there can be only one consumer for a queue.
A JMS Topic is a publish/subscribe solution which can have multiple consumers. A JMS client needs to subscribe to a topic to consume the messages
A Durable subscriber/consumer is a consumer when subscribes to a Topic/Queue, the Topic/Queue would save the message until it is consumed by the subscriber even if the subscriber is down.

Done!! Too much of theory… Time to get our hands dirty…

// Creating a JNDI API InitialContext object if none exists yet.
try {
jndiContext = new InitialContext();
} catch (NamingException e) {
System.out.println(“Could not create JNDI API context: ” +
e.toString());
System.exit(1);
}

/*
* Look up connection factory and destination. If either
* does not exist, exit. If you look up a
* TopicConnectionFactory or a QueueConnectionFactory,
* program behavior is the same.
*/
try {
connectionFactory = (ConnectionFactory) jndiContext.lookup(
“jms/TopicConnectionFactory”);
dest = (Destination) jndiContext.lookup(destName);
} catch (Exception e) {
System.out.println(“JNDI API lookup failed: ” + e.toString());
System.exit(1);
}

/*
* Create connection.
* Create session from connection; false means session is
* not transacted.
* Create consumer.
* Register message listener (TextListener).
* Receive text messages from destination.
* When all messages have been received, type Q to quit.
* Close connection.
*/
try {
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(dest);
listener = new TextListener();
consumer.setMessageListener(listener);
connection.start();
System.out.println(“To end program, type Q or q, ” +
“then “);
inputStreamReader = new InputStreamReader(System.in);

while (!((answer == ‘q’) || (answer == ‘Q’))) {
try {
answer = (char) inputStreamReader.read();
} catch (IOException e) {
System.out.println(“I/O exception: ” + e.toString());
}
}
} catch (JMSException e) {
System.out.println(“Exception occurred: ” + e.toString());
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
}
}

The above piece of code with the comments are self explanatory at a high level. The snippet is useul in writing an message consumer application. The piece of code that is highlighted requires a TextListener class that implements MessageListener. The onMessage method needs to be implemented in TextListener class which will be called when the message is sent to a Topic/Queue. The code look like below…

class TextListener implements MessageListener {
/*
* @param message the incoming message
*/
public void onMessage(Message message) {
TextMessage msg = null;

try {
if (message instanceof TextMessage) {
msg = (TextMessage) message;
System.out.println(“Reading message: ” + msg.getText());
} else {
System.out.println(“Message is not a TextMessage”);
}
} catch (JMSException e) {
System.out.println(“JMSException in onMessage(): ” + e.toString());
} catch (Throwable t) {
System.out.println(“Exception in onMessage():” + t.getMessage());
}
}
}

If you want to write a durable subscriber all we need to do is replace the session.createconsumer call with


private TopicSubscriber subscriber = null;
subscriber = session.createDurableSubscriber((Topic)destTopic, “Identifier”);

and after closing the connection unsubscribe the same.

session.unsubscribe(“Identifier”);

And finally to write a JMS producer application all we have to do is create a producer and send a message

producer = session.createProducer(dest);
producer.send(message);

Since JMS is based on J2EE, it requires application-client.xml file in META-INF directory. The application-client.xml file contains the JNDI information necessary for accessing the server application.

For a simple JMS client application, the content of the file would be something like this…

<application-client>

</application-client>

We also need the ejb.jar during the runtime to interpret these files.

With all the above instructions together you would be able to write a JMS client application that can send and receive messages. Sounds simple!! Yes!! It is…
For all those who believe in “Magic” can stop reading the post here and go ahead with writing your application. For those who don’t… wait for my next blog post to see how the Magic’s biggest secrets finally reveled 😛 …

Advertisements