Understanding JMS Interfaces and Classes

The main concepts of the JMS API (interfaces and classes) are included in the javax.jms package. JMS interfaces are based on a set of common messaging concepts. Both the PTP and the Pub/Sub JMS messaging models define a customized set of interfaces for these common (patent) concepts. Table 13.1 summarizes the JMS common interfaces for both the PTP model and Pub/Sub model interfaces.

Table 13.1. Summary of PTP and Pub/Sub Interfaces
JMS Parent InterfacePTP SpecificPub/Sub Specific
ConnectionFactoryQueueConnectionFactoryTopicConnectionFactory
ConnectionQueueConnectionTopicConnection
DestinationQueueTopic
SessionQueueSessionTopicSession
MessageProducerQueueSenderTopicPublisher
MessageConsumerQueueReceiver, QueueBrowserTopicSubscriber

Table 13.2 provides a brief definition of these JMS interfaces, and whether they support concurrent use.

Table 13.2. Summary of Common Interfaces
InterfaceDescriptionConcurrent Use?
ConnectionFactoryAn administered object used by a client to create a ConnectionYes
ConnectionAn active connection to a JMS providerYes
DestinationAn administered object that encapsulates the identity of a message destinationYes
SessionA single-threaded context for sending and receiving messagesNo
MessageProducerAn object created by a Session that is used for sending messages to a destinationNo
MessageConsumerAn object created by a Session that is used for receiving messages sent to a destinationNo

To write a JMS client, you must first import the javax.jms package and then, depending on the JMS model you are using, work through the following outline of the basic steps involved in developing a JMS client. The following steps replace the JMS parent interface with the appropriate interface of the messaging model you chose from those listed in Table 13.1:

1.
Import the javax.jms package

2.
Look up the ConnectionFactory using the JNDI Context

3.
Create a Connection from the ConnectionFactory

4.
Create a Session from the Connection object

5.
Look up the Destination using the same JNDI Context

6.
Create a MessageProducer or a MessageConsumer using the Session object

7.
Create a Message by choosing an appropriate JMS message type

8.
Send/receive the Message after starting the Connection

Note

Remember that the administered objects ConnectionFactory and Destination are already created and registered into a JNDI namespace, as discussed earlier in the “Administered Objects” section.


The preceding steps are a generalized layout of the client code developed for any of the JMS models. We stated the parent object, rather than the specific interface or class used by a particular model. In the next section, you'll learn how to apply these steps for both the PTP and Pub/Sub models.

Caution

Not all JMS objects are multi-threaded. JMS imposes restrictions on the Session object to be single-threaded. This means that a JMS provider must serialize messages delivered to all consumers created from the Session object. A Connection object can be shared by many Sessions because it's multi-threaded.


Figure 13.4 summarizes the main interfaces of the JMS API. Developing a JMS client depends on which JMS model you are using (either PTP or Pub/Sub), and on the client type (either producer or consumer).

Figure 13.4. JMS main interfaces.


Point-to-Point Concepts

Point-to-point concepts are about working with queues of messages. The main objects of the PTP API are the administered objects: the QueueConnectionFactory and Queue interfaces, which act as factories for creating other objects. The JMS PTP model defines how a client works with queues: how it finds them, how it sends messages to them, and how it receives messages from them. The following are the main steps in developing JMS PTP messaging clients:

1.
Look up a QueueConnectionFactory in the JNDI namespace.

2.
Create a QueueConnection.

3.
Look up a message queue.

4.
Create a QueueSession.

5.
Create a QueueSender, QueueReceiver, or QueueBrowser.

6.
Start sending, receiving, or browsing messages.

7.
Close the connection.

We discuss these steps in more detail in the following sections.

Step 1: Look Up a QueueConnectionFactory in the JNDI Namespace

A connection factory contains information about the JMS provider, the host, and the port that the server is listening to. It is created and configured by an administrator, and the client looks it up in the JNDI namespace. We assume that a QueueConnectionFactory named qcFactory has been created for our use.

Note

You will learn how to configure these JMS administered objects on Day 14, “Developing Message-Driven Beans,” for both WebLogic and JBoss, when you study message-driven beans.


import javax.naming.*;
import javax.jms.*;
// Establish a JNDI context
Context ctx = new InitialContext();
// Lookup the administered object qcFactory in the JNDI service
QueueConnectionFactory qcf = (QueueConnectionFactory)
        ctx.lookup("java:comp/env/jms/qcFactory");

Step 2: Create a QueueConnection

After obtaining a QueueConnectionFactory, use it to create a QueueConnection. This creates an active connection to the JMS provider with the default security credentials for the JMS client.

QueueConnection qConn = qcf.createQueueConnection();

Alternatively, you can also create a connection using a user with a password:

String user = "john";
String password = "1234";
QueueConnection qConn = qcf.createQueueConnection(user, password);

Step 3: Look Up a Message Queue

An administrator has created, configured, and registered a queue named myQueue in the JNDI for your use. Again, use JNDI to look it up:

Queue q = (Queue) ctx.lookup("java:comp/env/jms/myQueue");

Step 4: Create a QueueSession

Use the QueueConnection to create one or more QueueSession objects, which will be used to create a QueueSender (if you want to send() messages) or a QueueReceiver (if you want to receive() messages):

QueueSession qSession = qConn.createQueueSession(false,
              Session.AUTO_ACKNOWLEDGE);

The first parameter of the createQueueSession() method is a Boolean that indicates whether this session will begin a local transaction (called a transacted session). In this example, no transaction started. The second parameter indicates the mode of acknowledging message receipt. Message acknowledgement is discussed later today.

Note

A QueueConnection can be used to create more than one QueueSession. Each of these sessions is used in producing or consuming messages, and it can be transacted or not.


Step 5: Create a QueueSender, QueueReceiver, or QueueBrowser

Three options are available to a JMS client: to become a sender, a receiver, or a browser for a queue.

Step 5.1: Create a QueueSender

If you will be sending messages to the Queue, use the QueueSession to create a QueueSender:

QueueSender sender = qSession.createSender(q);

Step 5.2: Create a QueueReceiver

Similarly, if you will be receiving messages from the queue, use the QueueSession to create a QueueReceiver. After a message is received and acknowledged, it will be removed automatically from the queue.

QueueReceiver receiver = qSession.createReceiver(q);

Note

If messages have been received but not acknowledged when a QueueSession terminates, they are retained and redelivered by the JMS provider when a consumer next accesses the queue.


Step 5.3: Create a QueueBrowser

If you need to look at pending messages in the queue without consuming them, use the QueueSession to create a QueueBrowser. Queue browsing is useful for looking into queue messages from monitoring tools.

QueueBrowser qBrowser = qSession.createBrowser(q);

Note

The QueueBrowser feature is unique to the PTP model.


Step 6: Start Delivering Messages

All previous steps are just to set up the connection to the appropriate queues.

Step 6.1: Sending Messages

Before sending a message, a Message object must be created and populated with its content:

TextMessage msg = qSession.createTextMessage();
msg.setText("Hello World");
sender.send(msg);

Step 6.2: Receiving Messages

You must start the connection before receiving messages. It is implicitly started for either sending or browsing a queue.

qConn.start()

Receiving messages can be synchronous or asynchronous. In receiving synchronous messages, a JMS consumer uses the receive() method, which will be blocked indefinitely until a message arrives on the destination. On the other hand, asynchronous messages are received by using the onMessage() method of the MessageListener, where messages are pushed by the container and processed by the consumer.

The receive() method is used in synchronous receivers. JMS offers two more variants: receiveNoWait(), which is used for polling messages, and receive(long timeout), which will wait for the timeout period before returning.

TextMessage msg = (TextMessage)receiver.receive();
System.out.println(msg.getText());

To receive messages asynchronously, you can use either message-driven beans or MessageListener. First, you need to register your message listener with the receiver by using the setMessageListener() method:

receiver.setMessageListener(this);

We assume that our current JMS receiver implements the MessageListener interface. Now, implement the onMessage() method to listen to the incoming messages:

public void onMessage(Message message) {
 // unpack and process the messages received
}

Note

Some clients are designed with a message-based application triggering mechanism. The trigger is typically a threshold of waiting messages. JMS does not provide a mechanism for triggering the execution of a client. Some providers might support such a triggering mechanism via their administrative facilities.


A Connection also can be stopped using the stop() method and closed using the close() method.

Step 6.3: Browsing Messages

Browsing messages returns a java.util.Enumeration that is used to scan the queue's messages. It may be an enumeration of the entire content of a queue, or it may contain only the messages matching a message selector.

for (Enumeration msgList = qBrowser.getEnumeration();
          msgList.hasMoreElements(); ) {
          System.out.println(mmsList.nextElement());
}

Step 7: Close the Connection

After all sending or receiving activities are finished, remember to close the Connection object before ending the client:

QConn.close();

Publish-and-Subscribe Concepts

Publish-and-subscribe systems are about working with topics of messages. The main object of the Pub/Sub API is the Topic interface. It is common for a client to have all its messages broadcast to a single topic. Topics are created administratively and are treated as named objects by their clients. The JMS Pub/Sub model defines how a client works with topics: how it finds them, how it publishes messages to them, and how it subscribes to them to extract their messages. JMS also supports durable subscribers that remember the existence of topics while they are inactive.

The steps in developing a JMS Pub/Sub messaging client are similar to those in developing a JMS PTP client.

Step 1: Look Up a TopicConnectionFactory in the JNDI Namespace

A TopicConnectionFactory named tcFactory has been registered in the JNDI namespace. Both publisher and subscriber programs must access a tcFactory in order to create a Connection.

import javax.naming.*;
import javax.jms.*;

// Establish a JNDI context
Context ctx = new InitialContext();
TopicConnectionFactory tcf = (TopicConnectionFactory)
        ctx.lookup("java:comp/env/jms/tcFactory");

Step 2: Create a TopicConnection from TopicConnectionFactory
TopicConnection tConn = tcf.createTopicConnection();

You also can create a connection using a user and password:

String user = "john";
String password = "1234";
TopicConnection tConn = tcf.createTopicConnection(user, password);

Step 3: Look Up a Message Topic

An administered object myTopic has been created, configured, and registered in the JNDI namespace:

Topic t = (Topic) ctx.lookup("java:comp/env/jms/myTopic");

Step 4: Create a TopicSession

Use the TopicConnection to create one or more TopicSession objects, which will be used to create a TopicPublisher (if you want to publish() messages) or a TopicSubscriber (if you want to subscribe() to messages):

TopicSession tSession = tConn.createTopicSession(false,
              Session.CLIENT_ACKNOWLEDGE);

Step 5: Create a TopicPublisher or TopicSubscriber

Three types of options are available to a JMS client: to become a TopicPublisher, a TopicSubscriber, or a durable subscriber.

Step 5.1: Create a TopicPublisher
TopicPublisher publisher = qSession.createPublisher (t);

Step 5.2: Create a TopicSubscriber
TopicSubscriber subscriber = tSession.createSubscriber(t);

Step 5.3: Create a Durable Subscriber

An ordinary subscriber is not durable, and its session lasts for its lifetime. A durable subscriber registers with a unique identity that is retained by the JMS provider. A subsequent subscriber with the same identity resumes the subscription in the state it was left before. If there is no active subscriber for a durable subscription, JMS retains the subscription's messages until they are received by the subscription or until they expire. Use the following to create a durable subscriber:

String durSubID = "Sub300";
TopicSubscriber dSubscriber =  tSession.createDurableSubscriber(t, durSubID);

The preceding statement is used as many times as the durable subscribers need to connect to the JMS system to get their messages.

Step 6: Start Delivering Messages

All previous steps are just to set up the connection to the appropriate topic.

Step 6.1: Publishing a Message

Before publishing a message, a Message object must be created and populated with its content:

TextMessage msg = tSession.createTextMessage();
msg.setText("Hello World");
publisher.publish(msg);

Step 6.2: Subscribing to a Message

You must start the TopicConnection before subscribing to messages. This is implicitly started when publishing to a topic. A durable subscriber becomes active when the connection is started.

tConn.start()

The receive() method is used in synchronous receivers:

TextMessage msg = (TextMessage)receiver.receive();
System.out.printline(msg.getText());

To receive messages asynchronously, use the following:

subscriber.setMessageListener(this);

  public void onMessage(Message message) {
   // unpack and process the messages received
  }

Note

A more convenient way of implementing a JMS consumer to handle asynchronous messages is to use a message-driven bean, which will be discussed later today, and is the subject of Day 14.


Step 6.3: Durable Subscription to a Message

Durable subscribers are treated the same way as non-durable subscribers. You might want to close the durable subscriber:

dSubscriber.close();

To delete a durable subscription, first you close the subscriber, and then use the unsubscribe() method with the subscription name as the argument:

dSubscriber.close();
tSession.unsubscribe(durSubID);

Step 7: Close the Connection

When all sending and receiving activities are complete, remember to close the connection before ending the client:

try {
  // do some stuff with JMS connection, and send/receive messages
     } catch (JMSException e) {
            System.out.println("Exception occurred: " +
                e.toString());
        } finally {
            if (tConn != null) {
                try {
                    tCon.close();
                } catch (JMSException e) {}
            }
        }

Exception Handling

JMS defines JMSException as the root class for exceptions thrown by JMS methods. JMSException must be handled in the catch clause of your JMS client. Information about errors can be obtained by the getErrorCode(), which returns a vendor-specific error. The method getMessage() returns a message that describes the error. The method setLinkedException() references another exception that is a result of a lower-level problem. If appropriate, this lower-level exception can be linked to the JMS exception.

Synchronous and Asynchronous Message Receivers

In both JMS models, as discussed in the previous sections, receiving messages can be synchronous or asynchronous. In receiving synchronous messages, a JMS consumer uses the receive() method, which will be blocked indefinitely until a message arrives at the destination. On the other hand, asynchronous messages are received by using the onMessage() method of the MessageListener, where messages are pushed by the container and processed by the consumer.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.212.102