|
|

[an error occurred while processing this directive]
|
 |
 |
 |
introduction |
 |
 |
 |
|
Java Messaging Service (JMS), Sun's Java interface for access to Message Oriented Middleware (MOM) services, is an increasingly important standard in the world of J2EE computing. Yet because of its newness, JMS is still not terribly well understood by application developers. In this article, we'll try to demystify JMS while providing a crash course in message-oriented middleware (MOM) concepts. Along the way, we'll have occasion to mention SilverStream Software's xCommerce JMS Enterprise Enabler and talk briefly about how it allows the designer of XML integration applications to leverage the power of messaging. By the end of the article, you'll have a solid grasp of MOM fundamentals and how JMS fits into the J2EE puzzle.
|
 |
 |
what is JMS, really? |
 |
 |
 |
|
In order for distributed applications running on Java application servers to make full use of messaging systems (such as IBM's MQSeries or Progress Software's SonicMQ), Java-language clients and Java middle-tier services must have a common way to "talk to" enterprise messaging products. JMS provides that capability. In essence, JMS is an abstraction layer that lets the Java programmer create MOM-facing elements without having to know the low-level particulars of any vendor's solution.
The JMS standard was built with several goals in mind:
- Provide an Application Programming Interface suitable for creating and manipulating messages in formats compatible with existing MOM products.
- Support many different message-content types, including messages containing Java objects.
- Facilitate the development of heterogeneous applications that span operating systems, machine architectures, transport mechanisms, and computer languages.
JMS is a broadly applicable Java API that is intended to be layered over a wide range of existing and future Message Oriented Middleware systems, much the same way that JNDI (the Java Name and Directory Interface) is layered over existing name and directory services.
The complete JMS specification is available at http://java.sun.com/products/jms/.
|
 |
 |
what is Enterprise messaging? |
 |
 |
 |
|
An enterprise messaging system provides for the transport and storage of messages. Messages, in this context, are packets of information that are produced and/or consumed primarily by enterprise applications (rather than humans). They may contain key-value pairs, XML documents, serialized Java objects, or arbitrary byte streams.
One of the main attractions of Message Oriented Middleware is its ability to hide the details of message transport and delivery from diverse clients that may need to communicate across networks that use different communication protocols. By acting as a communications gateway, MOM shields clients from connectivity issues that would otherwise impede development of distributed applications.
The other aspect of enterprise messaging that makes products like MQSeries and SonicMQ so powerful is their ability to link processes in asynchronous fashion. Asynchronous processing means that the exchange of data between parties does not depend on either party being in direct, realtime contact with the other. The alternative to asynchronous processing is synchronous processing, wherein a host and a client (or a peer and a peer) must be in continuous conversation with each other for the entire duration of a session, without interruption. (An example of a synchronous interchange would be the use of a Remote Procedure Call in a CICS environment.)
While synchronous sessions are essential for some types of business logic, there are also many kinds of business processes that do not require synchronous communication between participants. For those processes, asynchronous interaction generally makes the most efficient use of resources and can dramatically improve system productivity.
A synchronous process is analogous to a restaurant in which every customer orders his meal directly through a conversation with the chef and the kitchen takes no other orders while the current customer's meal is being cooked. Customers line up and must wait, one by one, for every meal to be invidiually prepared. Asynchronous processing would be analogous to the more familiar scenario of waiters and waitresses conveying orders between customer and, kitchen concurrently. In the latter case, the waiters serve as a messaging channel to the kitchen, where orders are "queued up" and finished meals are dispersed on an as-available basis. In this example (as in many business processes), much better efficiencies are possible with asynchronous order processing than with synchronous order processing.
The time-domain decoupling afforded by messaging systems helps make robust, fail-safe operation possible. One party can be busy, or even offline, when the other party sends (or receives) its message. A network or server can go down, yet not affect the transmission or receipt of a message.
|
 |
 |
what Are message queues? |
 |
 |
 |
|
Asynchronous messaging depends on the fact that messages are sent not to clients, per se, but to queues, which exist independently of the client processes that use them.
A queue is a holding area or repository in which data elements (messages, in this case) are stored for eventual retrieval. In a MOM environment, client applications needn't know how message queues are structured, maintained, or stored; the details of queue management are handled by the MOM vendor (or "JMS provider"). Like server nodes, queues are often clustered for purposes of reliability, scalability, and load balancing.
While FIFO (first-in/first-out) and LIFO (last-in/first-out) queues are familiar constructs in computing, no order of retrieval is presumed in a message queue. Rather, the retrieval order is open. This means custom prioritization schemes can be applied to messages so that retrieval order (i.e., consumption order) is dependent on a client's needs. Properly exploited, this feature can lead to more efficient overall system operation. Processing of low-priority messages can be deferred to a time when system resources are available; low-priority items needn't interfere with the processing of high-priority ones.
You should note that the length of time messages are held in a queue, the maximum number of messages a queue can handle, and the manner in which resource overruns are handled are not defined by the JMS standard. The MOM vendor's documentation is the place to learn more about these issues.
|
 |
 |
are message-based applications slow? |
 |
 |
 |
|
While some latency occurs in all messaging systems, this does not mean that applications that use messaging are, of necessity, slow. Depending on the installation, throughputs of many hundreds of messages per second are possible. The important thing to keep in mind is that the asynchronous processing made possible by messaging affords the possibility of multitasking for applications that otherwise might not have that capability. This can boost throughput significantly (as in the restaurant example mentioned earlier). While a customer adds items to his shopping cart, the shopping-cart app can trigger an inventory-checking component, while another component can calculate shipping charges, while another component pulls customer information out of a database, etc., all operations taking place concurrently.
|
 |
 |
can messages be part of transactions? |
 |
 |
 |
|
One of the things that makes JMS messaging attractive is that message sessions can optionally incorporate transaction control. A transacted session groups an arbitrary set of produced and/or consumed messages into a single logical unit of work. When a transaction commits, all of its inputs (in terms of messages) are acknowledged and all outputs are sent. When a transacted message session rolls back, any produced messages are destroyed and any messages consumed during the session are recovered.
An an example, suppose an application builds a group of five messages. A requirement of the application is that the entire group of five messages must be sent as a batch; or else none of the five must be sent. Using an xCommerce JMS Component, the application could be structured such that messages are built and sent individually, but if a connection closes prematurely (or any other error condition happens, involving any of the five messages), the entire group is rolled back. NOTE
JMS does not require that MOM products support distributed transactions. But if such support exists, JMS does require that such support be implemented via the JTA (Java Transactions API) XAResource interface. Consult the JMS provider's documentation to see what kind of distributed transaction support, if any, is available in a particular MOM environment.
Since distributed transactions are controlled via JTA/XAResource, the use of JMS commit or rollback commands in a JTA context will cause a JMS TransactionInProgressException to be thrown.
|
 |
 |
point-to-point messaging |
 |
 |
 |
|
Two main messaging paradigms are implemented by MOM vendors:
Point-to-Point (PTP) messaging, and Publish/Subscribe
(which is discussed further below). Some vendors implement one or the other; some implement both.
Note that Point-to-point does not imply a synchronous connection in the context of messaging (as it does in some other contexts, such as discussions of RPC).
In the PTP model, any JMS client can, in theory, send messages to any other JMS client, subject only to administrative constraints. PTP is an asynchronous, queue-based, peer-to-peer model in which queues are created administratively and have indefinite lifespans. A queue is always available to receive and hold messages sent to it whether the client or clients using that queue are online or not. This is what makes messaging asynchronous.
With PTP, a queue functions much like a mailbox. One application might send messages to a queue; another application might retrieve messages from the same queue. A common case is that a client will have all its messages delivered to a single queue.
Publish/Subscribe Messaging
The Publish/Subscribe (or pub/sub) messaging model, implemented by some (but not all) MOM vendors, differs from Point-to-Point in the following ways:
- Queues are typically shared by multiple clients.
- Queues are organized hierarchically into nodes called topics. (This is a typical implementation scheme, although in fact JMS places no restrictions on what a topic can represent.)
- Each topic acts as a kind of mini-message-broker that accumulates and distributes messages addressed to it.
Clients in this kind of system use message producer/consumer objects called TopicPublishers and
TopicSubscribers. A client may subscribe to more than one topic; and a client may be both a subscriber and a publisher.
TopicSubscribers can be durable or non-durable. If a client needs to have access to all messages on a given topic (including ones that may be published when the subscriber is offline), a durable TopicSubscriber must be used. Otherwise, the client will have access only to messages that are queued during the lifetime of a given message-retrieval session.
Messages are served to subscribers in serial fashion. Because topics are shared resources (and because only one subscriber can be serviced at a time), the potential for latency is somewhat greater in pub/sub messaging than in PTP.
|
 |
 |
what about delivery guarantees? |
 |
 |
 |
|
JMS supports two modes of message delivery.
- The PERSISTENT mode instructs the message broker to write the message to a secure store to insure that the message is not lost in transit due to a system failure.
- The NON_PERSISTENT mode does not require the JMS provider to log the message to stable storage; thus, the message can, in theory, be lost. (The tradeoff here is one of performance. There is less overhead with a NON_PERSISTENT message.)
A JMS provider is required to deliver a NON_PERSISTENT message at-most-once. This means that while a message may sometimes be lost, it will never be delivered twice.
By contrast, the delivery guarantee for PERSISTENT messages is once-and-only-once. This means a provider failure must not cause a message to be lost in transit; and the message must not be delivered more than once.
NOTE Once-and-only-one delivery has the important limitation that it cannot and does not guarantee against message loss due to message expiration, resource overruns, or administrative destruction criteria. Configuring a message system for maximum reliability requires a thorough understanding of administrative issues surrounding the particular MOM solution in use.
|
 |
 |
how are messages structured? |
 |
 |
 |
|
Enterprise messaging products treat messages as persistible, lightweight entities that consist of a header, a body, and (in the case of JMS-aware products) a property list.The header contains fields used for message routing and identification. The body contains the application data being sent. Properties provide a mechanism for adding arbitrary descriptors (actually implemented as extra header fields) to messages so that clients, or their providers, can select or "filter" messages on the basis of application-specific criteria.
|
 |
 |
header information |
 |
 |
 |
|
Among the message characteristics defined in the header are an expiration time (which sets the message's useful life); message priority (based on a number ranking, from zero to nine); and delivery mode (PERSISTENT or NON_PERSISTENT).
The header fields defined by JMS are:
JMSCorrelationID
JMSDestination
JMSDeliveryMode
JMSExpiration
JMSPriority
JMSMessageID
JMSTimestamp
JMSRedelivered
JMSReplyTo
JMSType
The meanings of the fields are as follows.
JMSCorrelationID
A JMS client can use the JMSCorrelationID header to associated one message with another (for request/response situations). This field can hold an arbitrary string value, obtained by mapping a node value from an Input DOM, or perhaps created dynamically with the aid of ECMAScript, etc. Use of this field is not mandatory.
JMSDeliveryMode
This header field contains the delivery mode (PERSISTENT or NON_PERSISTENT) specified when the message was sent. At the start of a send session, this header field is ignored; after the send has been accomplished, it holds the delivery mode specified by the sending method.
JMSDestination
The JMSDestination header field is ignored at the time a message is sent; after the send, it contains the destination object specified by the sending message.
You do not need to enter anything manually in this field, since the necessary connection information (i.e., choice of destination queue) was automatically set when you first created the JMS Component.
JMSExpiration
This contains the Time-to-Live value for the message, specified in milliseconds. If it is zero, the message will have no expiration value (which means it will not expire).
Note: In most JMS-based MOMs, clients never receive expired messages.
JMSMessageID
The JMSMessageID value uniquely identifies a message in the MOM environment. It is set automatically by the JMS provider and is read-only (and only after a message has been sent).
JMSPriority
The JMSPriority field holds a string value containing one of ten values ('0' through '9') reflecting the message's priority. What prioritization actually means in a given MOM system is vendor dependent.
JMSRedelivered
If a client application receives a message that has the JMSRedelivered marker set, it is possible that the queue manager tried to deliver the message earlier, but the message was not acknowledged by the client (perhaps due to a system failure). This field is under the control of the queue manager or message broker. It is not under application control.
JMSReplyTo
The JMSReplyTo field is designed to contain a Destination supplied by a client when a message is sent. It represents the destination where a reply to the message (if any) should be sent.
JMSTimestamp
This field contains the time that a message was handed off to a provider to be sent. It may or may not be the actual transmission time, depending on whether (for instance) the message's "send" session is under transactional control.
JMSType
This user-settable field contains an arbitrary string supplied by a client when a message is created. The sender can assign any value to JMSType that a receiver might find useful. For example, application-defined JMSType values could facilitate message filtering by making it possible for various receivers to handle various specific message types.
NOTE Some JMS providers store message type definitions in a repository and may expect runtime values in JMSType that correspond to these type definitions. When this is the case, one should use symbolic values for JMSType that correspond to legal values defined in the applicable repository. (Consult the appropriate vendor's documentation for details.)
In addition to these predefined header fields (which every JMS message is required to have), there are JMS-defined property fields (many of which are optional), provider-specific properties, and user proprties.
|
 |
 |
body types |
 |
 |
 |
|
JMS defines five message body types:
- MapMessage-a message in which the body consists of a set of key-value pairs, wherein the keys are Java Strings and the values are Java primitive types. Entries may be accessed by sequential enumeration or randomly by name. (The ordering of key-value pairs is undefined.)
- TextMessage-a message in which the body is a java.lang.String.
- StreamMessage-a message whose body consists of a stream of Java primitive values (which are filled and read sequentially).
- ObjectMessage-a message containing a Serializable Java object. (For collections of objects, one of the collection classes defined in JDK 1.2 can be used.)
- BytesMessage-a message comprising any arbitrary stream of uninterrupted bytes. (This category is intended for literally encoding a body to match a vendor's native message format.)
NOTE Regardless of type, all JMS messages are read-only once posted to a queue.
SilverStream's JMS Enterprise Enabler for xCommerce allows you to define message payloads using any of the five canonical JMS body types. In addition, the JMS Enterprise Enabler offers two predefined message types (which are actually wrappers for two of the predefined JMS body types):
XML: Allows the xCommerce application to send or receive an XML document (based on any XML template of your choosing) as a message. The complete DOM representation of the XML document is available to you for mapping and/or manipulation via ECMAScript and XPath; and you can add new nodes to the template document. This message type wrappers the JMS- defined TextMessage type.
Copybook: Allows the xCommerce application to send or receive a COBOL copybook (as a BytesMessage).
|
 |
 |
how are messages retrieved? |
 |
 |
 |
|
JMS provides two mechanisms for client retrieval of messages:
Synchronous message retrieval, wherein a timeout value can be specified for terminating the session should no response occur.
Asynchronous retrieval via a MessageListener object whose onMessage() method contains application logic for processing incoming messages.
Here, the terms "synchronous" and "asynchronous" refer to the queue/client communication session rather than any relationship between sender and client. Senders can always post to queues, whether or not receiving clients are online; in that sense, all messages are asynchronously received.
In synchronous retrieval, a timeout value can be specified in milliseconds. If no expiration value is specified, the "receive" session will block indefinitely, until a message arrives. On the other hand, if a zero wait time is specified, queued messages that meet the applicable selection criteria (if any) will be retrieved-and the session terminated-immediately.
Asynchronous retrieval treats messages like events and allows clients to be notified immediately (and take action on) messages as they arrive. Application logic triggered by an onMessage() handler processes messages transparently, with a minimum of latency. A broadcaster/listener metaphor applies.
One way to think of it is that in a synchronous-retrieval scenario, the client is pulling data from the queue, whereas in the asynchronous case, the queue is pushing data at the client.
|
 |
|
 |
 |
 |