Point-to-Point Messaging Example

You are now in a position to start coding. For all the following code examples, you will need to import the javax.jms package. This contains all the classes for creating connections, sessions, and destinations.

Connecting to a Queue

To send a JMS message, a number of steps must first be performed. You must

1.
Obtain a ConnectionFactory

2.
Establish a Session

3.
Create a MessageProducer object

Although this example is in the point-to-point message domain, the same steps are required for publish/subscribe topics.

The following steps show how to create a queue used later to send a simple text message.

1.
Obtain the JNDI initial context.

Context context = new InitialContext();

2.
Contact the JMS provider, obtain a JMS connection from the appropriate ConnectionFactory, and create a connection for a queue. The following code uses a connection factory registered against the JNDI name jms/QueueConnectionFactory.

ConnectionFactory connectionFactory = (ConnectionFactory)context.lookup("jms
/QueueConnectionFactory");
Connection connection = connectionFactory.createConnection();

The createConnection() method throws a JMSException if the JMS provider fails to create the queue connection and lookup() can throw a NamingException if the name is not found.

3.
Establish a Session for this connection. In this case, the Session has transactions set to false (transactions are covered later) and AUTO ACKNOWLEDGE of receipt of messages. This will throw a JMSException if the Connection object fails to create a session.

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

NOTE

Although sent messages are not acknowledged, a session can be used to receive messages created by its own connection. This is why an Acknowledge mode must be specified on a session, even if the queue is only used to send messages.

4.
Obtain the queue destination using its JNDI name. The lookup() method can throw a NamingException if the name is not found.

Destination destination = (Queue)context.lookup("jms/firstQueue");

5.
Finally, create a message producer that will be used to send messages. This will throw a JMSException if the Session fails to create a producer, and an InvalidDestinationException if an invalid destination is specified.

MessageProducer producer = session.createProducer(destination);

Note how the connection factory hides all the implementation details of the connection from the client. It does the hard work of creating resources, handling authentication, and supporting concurrent use.

Now you have a queue that is ready to send messages. But before that, you need to know a little more about JMS messages.

JMS Messages

JMS messages consist of three parts:

  • A header— Used to identify messages, set priority and expiration, and so on and to route messages.

  • Properties— Used to add information in addition to the message header.

  • Message body— There are five message body forms defined in JMS—BytesMessage, MapMessage, ObjectMessage, StreamMessage, and TextMessage.

Note that only the header is a required component of a message; the other two parts, including the body, are optional.

Message Header Fields

The JMS message header contains a number of fields that are generated by the JMS provider when the message is sent. These include the following:

  • JMSMessageID A unique identifier

  • JMSDestination Represents the queue or topic to which the message is sent

  • JMSRedelivered Set when the message has been resent for some reason

The following three header fields are available for the client to set:

  • JMSType A string that can be used to identify the contents of a message

  • JMSCorrelationID Used to link one message with another, typically used to link responses to requests

  • JMSReplyTo Used to define where responses should be sent

Other header fields may be set by the client but can be overridden by the JMS provider with figures set by an administrator:

  • JMSDeliveryMode This can be either PERSISTENT or NON_PERSISTENT (the default is PERSISTENT).

  • JMSPriority Providers recognize priorities between 0 and 9, with 9 being the highest (default is 4). Note that there is no guarantee that higher priority messages will be delivered before lower priority ones.

  • JMSTimestamp This contains the time the message was sent to the JMS provider by the application. Note that this is not the time the message is actually transmitted by the JMS provider to the receivers.

  • JMSExpiration An expiration time, after which the message will be deleted

Each header field has associated setter and getter methods that are fully described on the JMS API documentation.

Message Properties

Most header fields are written by the JMS provider, so there is not a great deal of scope for clients to add information to JMS header fields. However, JMS messages can incorporate properties which are name/value pairs defined by the client.

Property values can be boolean, byte, short, int, long, float, double, or String and are defined using the appropriate Message.setProperty method. For example:

message.setStringProperty ("Type", "Java");

This example sets the message object's property called "Type" to the string "Java". A corresponding getProperty method is used to retrieve a message's property by name. The getPropertyNames() can be used if the names are not known. You can use these properties to distinguish message queues or send extra information.

JMS Body Types

JMS supports five types of message body, each defined by its own message interface. Each message type is briefly described in Table 9.3. Refer to the JMS API for more information on the message body types.

Table 9.3. JMS Message Body Types
Message Body TypeMessage Contents
BytesMessageUninterpreted byte stream
MapMessageName/value pairs
ObjectMessageSerializable Java object
StreamMessageStream of Java primitives
TextMessageJava String

Creating a Message

For the example given here, the default header properties will be used. Also, to keep this example straightforward, a TextMessage body will be used. A TextMessage object extends the Message interface and is used to send a message containing a String object.

A text message body is created using the createTextMessage() method in the Session object.

TextMessage message = session.createTextMessage();

The content of the text message is defined with message.setText():

message.setText("some text");

Having created a message, you are ready to send it.

Sending a Message

A message must be sent using the MessageProducer for your destination. For example

producer.send(message);

It's as simple as that.

Closing the Connection

Connections are relatively heavyweight objects, and you should always release the resources explicitly rather than depending on the garbage collector. Closing the connection is required to close any associated objects such as the session and message producer.

connection.close();

Send JMS Text Message Example

The code for the entire point-to-point sender example is shown in Listing 9.1. You will find this code in PTPSender.java file in the examples directory for Day 9 on the Web site.

Listing 9.1. Complete Listing for PTPSender.java
import javax.naming.*;
import javax.jms.*;

public class PTPSender {
    private Connection connection;
    private Session session;
    private MessageProducer producer;
    public static void main(String[] args) {
        PTPSender sender = null;
        try {
            sender = new PTPSender();
            System.out.println ("Sending message Hello World");
            sender.sendMessage("Hello World");
        }
        catch(Exception ex) {
            System.err.println("Exception in PTPSender: " + ex);
        }
        finally {
            try {sender.close();} catch(Exception ex){}
        }
    }

    public PTPSender() throws JMSException, NamingException {
        Context context = new InitialContext();
        ConnectionFactory connectionFactory =
            (ConnectionFactory)context.lookup("jms/QueueConnectionFactory");
        connection = connectionFactory.createConnection();
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = (Destination)context.lookup("jms/firstQueue");
        producer = session.createProducer(destination);
    }

    public void sendMessage(String msg) throws JMSException {
        TextMessage message = session.createTextMessage();
        message.setText(msg);
        producer.send(message);
    }

    public void close() throws JMSException {
        producer.close();
        session.close();
        connection.close();
    }
}

To send messages to the J2EE RI message queue you defined at the start of this exercise use the command

asant PTPSender

The next example program will retrieve a single message from the same example queue and display it on the screen.

Consuming Messages

There are two ways of consuming queued messages with JMS.

  • Synchronously— An explicit call to the receive() method.

  • Asynchronously— By registering an object that implements the MessageListener interface. The JMS provider invokes the onMessage() method in this object each time there is a message queued at the destination.

Figure 9.5 is a UML sequence diagram showing the difference between synchronous and asynchronous message consumption.

Figure 9.5. Synchronous and asynchronous message consumption.


The following example will demonstrate how to receive a message from a queue using a synchronous call.

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

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