JMS API

We are using the following steps for developing a J2EE application to use the JMS API directly for asynchronous messaging. We will list all the common APIs that are predominately used in JMS.

1)       Import JMS packages: – A J2EE application that uses JMS starts with several import statement.

Eg: –

import javax.jms.*;       //JMS interfaces
import javax.naming.*;    //Used for JNDI lookup of administered objects.

2)      Get an initial context

Eg: –

try     {
ctx = new InitialContext(env);
}

3)      Retrieve administered objects: – Retrieve this object from the JNDI namespace. The InitialContext.lookup() method is helps to retrieve this object.

Eg: –

qcf = (QueueConnectionFactory)ctx.lookup( qcfName );
...
inQueue = (Queue)ctx.lookup(qnameIn );

Or we can use another method to extracting obtaining administratively-defined JMS destination objects by JNDI lookup is to use the Session.createQueue(String) method or Session.createTopic(String) method.

Eg: –

Queue q = mySession.createQueue("Q1");

Create a JMS Queue instance that can be used to reference the existing destination Q1.

4)      Create a connection to the messaging service provider:- The createQueueConnection() method on the factory object is helps to make the connection.

Eg: –

connection = qcf.createQueueConnection();

The JMS specification defines that connections should be created in the stopped state. Until the connection starts, MessageConsumers that are associated with the connection cannot receive any messages. To start the connection, we use the following command:

connection.start();

5)      Create a session for sending or receiving messages: – The createQueueSession method is used on the connection to obtain a session and this method takes two parameters.

  1. A boolean that determines whether or not the session is transacted.
  2. A parameter that determines the acknowledge mode.

Eg: –

boolean transacted = false;
session = connection.createQueueSession(transacted,
Session.AUTO_ACKNOWLEDGE);

In the above example the session is not transacted and it should automatically acknowledge received messages. For defining the EJB specification we use the following tags.

1)       The transacted flag passed on createQueueSession is ignored inside a global transaction and all work is performed as part of the transaction. Outside of a transaction the transacted flag is used and, if set to true, the application should use session.commit() and session.rollback() to control the completion of the work. In an EJB2.0 module, if the transacted flag is set to true and outside of an XA transaction, then the session is involved in the WebSphere local transaction and the unresolved action attribute of the method applies to the JMS work if it is not committed or rolled back by the application.

2)      Clients cannot use Message.acknowledge() to acknowledge messages. If a value of CLIENT_ACKNOWLEDGE is passed on the createxxxSession call, then messages are automatically acknowledged by the application server and Message.acknowledge() is not used.

6)      Send message.

1)      Create MessageProducers to create messages. In a point-to-point messaging the MessageProducer is a QueueSender and it is created by passing an output queue object into the createSender method on the session. Also the  QueueSender is n created for a specific queue

Eg:-

QueueSender queueSender = session.createSender(inQueue);

2)Use the session to create an empty message and add the data passed:-

Methods are provided on the Session object for message creation to avoid referencing the vendor-specific class names for the message types.

Eg: –

TextMessage outMessage = session.createTextMessage(outString);

3)Send the message: – To send the message, the message is passed to the send method on the QueueSender.

Eg: –

queueSender.send(outMessage);

Receive replies

Create a correlation ID to link the message sent with any replies.

Eg:- The client receives reply messages that are related to the message that it has sent, by using a provider-specific message ID in a JMSCorrelationID.

messageID = outMessage.getJMSMessageID();

The correlation ID is then used in a message selector, to select only messages that have that ID:

Eg:-

String selector = "JMSCorrelationID = '"+messageID+"'";

1)      Create a MessageReceiver to receive messages. In a point-to-point the MessageReceiver is a QueueReceiver that is created by passing an input queue object (retrieved earlier) and the message selector into the createReceiver method on the session.

Eg: –

QueueReceiver queueReceiver = session.createReceiver(outQueue, selector);

2)      Retrieve the reply message:- To retrieve a reply message, the receive method on the QueueReceiver is used:-

Eg: –

Message inMessage = queueReceiver.receive(2000);

The parameter in the receive call is a timeout in milliseconds and this parameter defines how long the method should wait if there is no message available immediately. We needn’t any delay, use the receiveNoWait() method.

3)      Act on the message received. When a message is received, you can act on it as needed by the business logic of the client. Some general JMS actions are to check that the message is of the correct type and extract the content of the message. To extract the content from the body of the message, it is necessary to cast from the generic Message class (which is the declared return type of the receive methods) to the more specific subclass, such as TextMessage. It is good practice always to test the message class before casting, so that unexpected errors can be handled gracefully the instanceof operator is used to check that the message received is of the TextMessage type. The message content is then extracted by casting to the TextMessage subclass.

Eg: –

if ( inMessage instanceof TextMessage )
String replyString = ((TextMessage) inMessage).getText();

If the application needs to create many short-lived JMS objects at the Session level or lower, it is important to close all the JMS resources used. For accomplishing this purpose we call the close() method on the various classes (QueueConnection,QueueSession, QueueSender, and QueueReceiver) when the resources are no longer required.

Eg: –

queueReceiver.close();
...
queueSender.close();
...
session.close();
session = null;
...
connection.close();
connection = null;

4) Publishing and subscribing to messages: – Use JMS Publish/Subscribe support instead of point-to-point messaging.

Eg: – To create a session and connection. The exceptions are that topic resources are used instead of queue resources (such as TopicPublisher instead of QueueSender), as used to publish a message

Eg: –

// Creating a TopicPublisher
TopicPublisher pub = session.createPublisher(topic);
...
pub.publish(outMessage);
...
// Closing TopicPublisher
pub.close();

Error handling mechanism

JMS runtime errors are reported by exceptions. The majority of methods in JMS throw JMSExceptions to indicate errors. It is good programming practice to catch these exceptions and display them on a suitable output.

Unlike normal Java exceptions, a JMSException can contain another exception embedded in it. The implementation of JMSException does not include the embedded exception in the output of its toString() method. So we need to check explicitly for an embedded exception and print it out.

Eg: –

catch (JMSException je)
{
System.out.println("JMS failed with "+je);
Exception le = je.getLinkedException();
if (le != null)
{
System.out.println("linked exception "+le);
}
}