JMS: An infrastructure for XML-based business-to-business communication

Learn how the Java Messaging Service can provide a flexible, reliable, and secure means of exchanging XML-based transactions

1 2 3 Page 2
Page 2 of 3

Within the context of a connection, the client application establishes one or more sessions, each with its own transactional characteristics and acknowledgement modes. All actual messaging activity is performed via the session object. It is considerably more efficient to employ multiple sessions per connection than multiple connections to the same broker. Connections require more resources to establish and maintain than sessions, and can easily be reused for communication through different topics or queues, as well as for different transactional or acknowledgement behavior.

The JMS syntax for creating a session on an established connection is:

   public javax.jms.[Topic|Queue]Session create[Topic|Queue]Session
   (boolean transacted, int acknowledgeMode)

Where:

  • transacted is a boolean value; if it is true, the session will be transacted
  • acknowledgeMode indicates whether the consumer or the client will acknowledge any messages they receive

Transactional behavior

Transactional behavior is controlled at the session level. When a session is transacted, the message broker stages the message traffic until the client application either commits or rolls back the transaction. The completion of a session's current transaction automatically begins a new transaction.

The use of transactions affects producers and consumers of messages in the following manner:

  • Producers:

    • Commit: The broker sends the set of messages that have been staged
    • Rollback: The broker disposes of the set of messages that have been staged
  • Consumers:
    • Commit: The broker disposes of the set of messages that have been staged
    • Rollback: The broker resends the set of messages that have been staged

When a rollback is performed in a session that is both a producer and a consumer, its produced messages are destroyed, and its consumed messages are resent.

Acknowledgement modes

Acknowledgment modes are also controlled at the session level. Acknowledgment is distinct from replies in the request-reply model; they instead inform the message broker that a given client has successfully received a message. Replies, on the other hand, are additional messages sent by a receiver in response to an incoming message. Acknowledgement can be thought of as analogous to handshaking in hardware communication. JMS supports the following acknowledgement modes for receiving messages:

  • AUTO_ACKNOWLEDGE: The session automatically acknowledges receipt of each message. In synchronous mode, this indicates a successful return from a call to receive. In asynchronous mode, it indicates that the asynchronous message handler indicated a successful return.

  • CLIENT_ACKNOWLEDGE: Allows the client application to indicate that it received the message successfully, possibly delaying the acknowledgement. The application must invoke the acknowledge() method on each message successfully received.

  • DUPS_OK_ACKNOWLEDGE: A variation on AUTO_ACKNOWLEDGE that provides a lazy mechanism that can result in duplicate message deliveries in failure situations. While this mode is only appropriate for insensitive data, it can provide increased efficiency in a messaging system.

Pub/sub programming

In the pub/sub paradigm, each session object publishes and/or subscribes to one or more topics. An authorized publisher produces messages through a specified topic, and authorized subscribers receive messages by subscribing to that topic. This model promotes the independence of producers and consumers from one another, and allows for both one-to-many and many-to-many configurations. Topics may be static objects under administrative control, dynamic objects created as needed, or temporary objects created for more transitory or anonymous uses.

In order to publish messages, a session must create a publisher object for the selected topic. Likewise, to consume messages published to a topic, a session must create subscriber objects that subscribe to the desired topic. In Figure 2 below, the pub/sub session contains publisher objects producing messages to topics maintained by the message broker and subscribers consuming messages from topics to which the session is subscribed.

Figure 2. Pub/sub model

Publishing a message

When publishing a message, the publishing application specifies the quality of service to be used (factors involved here include the message's delivery mode, time-to-live, and priority) as well as whether the subscriber requests a reply:

publish(Message message, int deliveryMode, int priority, long timeToLive)

Where:

  • message is a javax.jms message
  • deliveryMode is either NON_PERSISTENT or PERSISTENT
  • priority is between 0 and 9, with 0 being lowest and 9 highest
  • timeToLive is between 0 and n, with 0 being forever and any other positive value of n being n milliseconds

Delivery modes

The delivery mode is one of several aspects that determine quality of service for message delivery and receipt:

  • NON_PERSISTENT: This is the most efficient delivery mode, because it does not require that the message be logged to stable storage. The JMS specification indicates that a JMS provider must deliver a NON_PERSISTENT message with an at-most-once guarantee, meaning that the broker may lose the message (due to a power outage, for example), but it must not deliver it twice.

  • PERSISTENT: This mode instructs the broker to place the message in a data store as an extension of the send operation. This ensures that the message will survive power outages and other system failures. The JMS specification indicates that a JMS provider must deliver a PERSISTENT message with a once-and-only-once guarantee. It must not lose the message and it must not deliver it twice.

Priority

When several messages await consumption by a subscriber, higher priority messages are presented to the client prior to those of lower priority, resulting in non-FIFO (first in, first out) behavior.

Time-to-live

The time-to-live parameter specifies how long the message broker should retain the message in order to ensure that all subscribers receive it. If, after initial delivery, any durable subscribers did not acknowledge delivery, the message is retained for the time-to-live duration in anticipation of those durable subscribers reconnecting to the message broker and accepting delivery. If the time-to-live is specified as zero, the message is said to live forever; it will not expire.

When a message's time-to-live is reached, the broker will typically discard it. The JMS specification does not define any form of notification of message expiration. Clients should not receive messages that have expired; however, the JMS specification does not guarantee that message brokers will not allow this to happen. Typically, a message set to live forever will be discarded as soon as delivery to all current subscribers and all durable subscribers is complete.

Nondurable subscriptions

To create a nondurable subscription to a topic, the client application invokes the following method provided by the session object:

TopicSubscriber createSubscriber(Topic topic, String messageSelector, boolean noLocal)

Where:

  • topic is a string that specifies the name of a topic
  • messageSelector is a string that defines selection criteria
  • noLocal is a boolean; a value of true indicates that the client application will not receive messages from subscribed topics that were published locally

Message selection

Subscribers can filter the messages they receive by qualifying their subscriptions with so-called message selectors. Message selectors cause the JMS provider to evaluate message headers and properties prior to sending messages to the client application. Message selectors employ a syntax based on a subset of SQL-92 conditional expressions. Because the JMS provider handles the filtering, the application and its communication links are more efficient and consume less bandwidth.

The following message selector might filter a subscription on a topic to retrieve only high-priority quotes that are requesting a reply:

"Property_Priority > 7 AND Property_Type='Quote' AND
   Property_Reply is NOT NULL"

Durable subscriptions

To create a durable subscription to a topic, the client application invokes the following method provided by the session object:

TopicSubscriber createDurableSubscriber (Topic topic,
   String name, String messageSelector, boolean noLocal)

Where:

  • topic is a string that specifies the name of a topic
  • name is an arbitrary string (not necessarily the username, although that is not uncommon) that indicates the name under which to maintain the durable subscription to the specified topic

  • messageSelector is a string that defines selection criteria

  • noLocal is a boolean; a value of true indicates that the client application will not receive messages from subscribed topics that were published locally

A durable subscription indicates that the client wants to receive all the messages published to a topic even if the client connection is not active. The broker ensures that all messages published to the topic are retained until the durable subscriber acknowledges them or the messages have expired.

Pub/sub code sample

Let's take a look at this in action. The following code sample illustrates the basic steps required to create a publisher and a subscriber for a sample topic, and publish a message:

String APP_TOPIC = "sample_topic";
//The session method is used to create the topic.
javax.jms.Topic topic = session.createTopic (APP_TOPIC);
//The subscriber uses the session method to create a subscriber to it.
javax.jms.TopicSubscriber subscriber =
   session.createDurableSubscriber(topic, user);
//The subscriber sets a listener for the topic.
subscriber.setMessageListener(myListener);
//The publisher uses the session method to create a publisher.
publisher = session.createPublisher(topic);
// Publish a message to the topic.
private void jmsPublish (String aMessage)
{
   try
   {
      javax.jms.TextMessage msg = session.createTextMessage();
         msg.setText( user + ": " + aMessage );
      publisher.publish( msg );
   }
   catch ( javax.jms.JMSException jmse )
   {
      jmse.printStackTrace();
   }
}

(Note: This article can only provide the briefest of introductions to JMS programming in the context of enabling B2B communication with XML. The JMS API is quite useful for the development of a wide variety of synchronous and asynchronous transaction models. I encourage you to check the Resources listed at the end of this article for more information.)

Point-to-point programming

In the point-to-point (PTP) paradigm, each session object sends and/or receives through one or more queues. Prospective consumers of messages sent to a queue can either receive the message that is first in line (thereby removing it from the queue) or browse through all the messages in the queue, causing no changes.

Figure 3. Point-to-point model

In Figure 3 above, the PTP session employs sender objects that send messages to queues maintained by the message broker, and receivers that receive messages addressed to specific queues.

In the PTP paradigm, the first message received by the broker is the first message delivered to a consumer. This FIFO technique requires that the broker retain the second message and any subsequent messages until the first message is consumed. Even when there are no clients associated with a queue, messages are retained. Hence, unlike the pub/sub semantics, durability and persistence are implicit queue concepts. There is only one message consumer for a given message. In some JMS implementations, multiple prospective receivers can attach to a queue, but only one takes delivery of each message. When each message is acknowledged as delivered, the broker disposes of it. No other client sees it and no other client can receive it.

JMS specifies a queue browser mechanism. A queue browser allows authorized clients to examine queues (counting messages, for example) without destroying the examined messages.

In Figure 4 below, three message queues are shown within a message broker. The queues are shown to have different depths, indicating the stack of messages that are retained until receivers consume them. The receiver could be one of many standing by to receive the first message in the queue. On the red queue, multiple receivers are attached, but only one will receive the next message: a message queued through PTP is delivered only once.

Figure 4. Point-to-point messaging in action

The JMS programming model for PTP is virtually identical to that for pub/sub, except for the inherent semantic differences between the two models. As such, we will not go into the details of PTP programming here.

JMS messages

Now let's take a look at the messages themselves. All JMS messages are composed of the following three sections:

  • Header fields: All messages support the same set of header fields. Header fields contain values used by both client applications and JMS providers to identify and route messages.
  • Properties: These contain JMS-specified and user-defined name-value pairs that can be used for message filtering/routing and application requirements. These named properties are used by the message selection mechanism described earlier. The JMS specification does not require the use of any message properties, even those defined by the specification. Property names must obey the rules for a message-selector identifier. Property values, which are set prior to sending a message, can be booleans, bytes, shorts, ints, longs, floats, doubles, and Strings.
  • Body: The body section contains the application-specific portion of the message. JMS defines several types of message bodies that correspond with the JMS-supported message types:

    • BytesMessage: A stream of uninterpreted bytes.
    • MapMessage: A set of name-value pairs, in which the names are strings and the values are Java primitive types. The entries can be accessed sequentially or randomly by name.
    • TextMessage: A message containing a java.util.StringBuffer.
    • StreamMessage: A stream of Java primitive types, filled and read sequentially.
    • ObjectMessage: A message that contains a serializable Java object.

    These five types cover the majority of messaging styles currently in use.

Related:
1 2 3 Page 2
Page 2 of 3