Advanced Messaging

This section covers various advanced topics in JMS. Compared to the other parts of the concepts guide, the topics in this section are separate and can be read in any order. The topics covered here are typically only used by advanced users in special situations, so if you were not previously familiar with JMS, you may want to skip this section now and come back later if you need to use these concepts.

Temporary Destinations

JMS supports a features called temporary destinations, which can be used to create temporary queues and topics dynamically. Such destinations are not created by an administrator and they are typically short-lived with the intent of exchanging non-persistent messages. Each temporary destination has a unique, system-generated name and can only be used within the scope of the connection in which they were created.

JMS uses temporary destination to implement an RPC-like mechanism on top of a Pub/Sub or P2P messaging model. This artifact is called a requestor and it support a method called request which take a message as a parameter and returns an reply message. There is both a QueueRequestor and a TopicRequestor. Under the covers, the request method performs the following steps:

  1. It creates a temporary destination and sets the ReplyTo field in the message header of the supplied message to this destination.

  2. Then the message supplied to the method is sent to the destination of the message.

  3. Finally, the requestor waits for a response to the temporary destination. This reply is returned to the caller.

The graph below illustrates how requestors work:

The experience for users of the requestor is that of invoking a remote service RPC-style. If a consumer receives the message from the destination it will process it and reply back to the temporary destination. The requestors provided with JMS are fairly simple and application developers may want to implement more sophisticated ones that support timeout, etc.

Pausing Message Delivery

JMS has advanced facilities for starting and stopping the delivery of messages to consumers within a connection. The Connection interface supports the following two methods:

The suspend and resume capabilities of a connection provides very convenient functionality for a broad category of applications. As an example, this can be used by interactive applications (e.g. GUI applications) to allow users to start and stop the flow of messages using built-in JMS functionality.

Connection Consumer

As described previously, a session provides a single-threaded context for sending and receiving messages. This means that all calls to receive, receiveNoWait and onMessage are serialized for all consumers within a particular session. This is typically very convenient for applications developers as they do not need to worry about writing thread-safe consumers.

However, it also means that unless a consumer applications creates multiple connections to a JMS provider, it may not exploit the concurrency capabilites of the underlying JVM and hardware to maximize the number of messages a client application can process. Creating many connections is typically not advisable since a connection is often a fairly resource-intense object.

To address this need for advanced concurrency in consumer applications, the JMS specification defined an optional JMS feature called the connection consumer. A connection consumer "operates" at the connection level rather than the session level and is therefore not subject to the concurrency restrictions of a session.

A ConnectionConsumer is an object, which can process messages concurrently. Connection consumers are created using the createConnectionConsumer or createDurableConnectionConsumer method on the TopicConnection or QueueConnection. Under the covers, the connection consumer relies on a ServerSessionPool to dispatch messages to an asynchronous consumer set with the setMessageListener method on a session object created by the pool.

The graph below illustrates the relationship between a connection consumer, the server session pool and a session. Since a server session pool can create multiple sessions, which are run in different threads, this architecture allows messages to be dispatched concurrently using a single connection. If the session supports distributed transactions (XASession), the session's message listener can optionally involve an XAResource to transactionally dispatch messages.

The JMS provider executes the following steps to drive dispatch of messages using the connection consumer:

  1. A connection consumer initially connects to some destination, which sends messages to it.

  2. When it has received a certain number of messages from the destination, it fetches a server session from a server session pool. A server session is conceptually a thread and the server session pool is conceptually a thread pool.

  3. The connection consumer gets a session from the server session.

  4. Using the JMS provider's private APIs the connection consumer can assign its messages to the session. This step is automatically performed by the JMS provider.

  5. The connection consumer calls the start method on the server session.

  6. The server session is then required to call the run method on the session. Since the Session implements the Runnable interface, it can be run by any thread.

  7. The session's run method dispatches its messages to a session message listener. As mentioned above, the listener can optionally interact with the session's XAResource to control transactional dispatch of messages.

In summary, the connection consumer architecture allows users to not only dispatch messages concurrently, but also control the thread that actually performs the work. Although this architecture is primarily intended for application servers implementing message driven beans, it can also be used by sophisticated application developers.

Distributed Transactions

A distributed transaction goes beyond a transacted session by allowing the task of sending or acknowledging messages to be coordinated with other tasks executing in a distributed system. As an example, acknowledging a message can be performed in the same unit of work as storing the message into a database.

A distributed transaction supports the ACID properties:

The ACID properties are enforced by driving a distributed transaction using the two-phase commit protocol (2PC). The 2PC protocol is driven by a piece of middleware called a resource coordinator (or transaction manager). The resource coordinator drives the two phases by executing the following actions:

  1. First, all resources enlisted in the transaction are asked to prepare. If a resource is prepared it means that it is ready to go ahead and complete the transaction. If any resource can not prepare, the transaction aborts (rollback).

  2. If the first phase succeeds and all resources are prepared, the second phase starts. In this phase all resources are asked to commit. The resource coordinator is responsible for calling commit on all resources until they succeed.

It is important to realize that sending a message and receiving the same message in one distributed transaction is not possible, since it would violate the ACID properties described above (isolation). Entering a message into a destination and removing a message from a destination are two distinct operations, which must be executed in two different transactions.

As mentioned above, global transactions require the presense of a coordinator, which keeps track of resources participating in the transaction. The coordinator remembers the state of resources in case of crashes and ensures that the two phase commit protocol is driven to completion (commit or rollback). The coordinator is provided by the Novell exteNd Messaging Platform's JTS component.

When JMS is used in an application server context, which supports a coordinator (JTS/JTA), the proper handling of XAResource objects is done automatically by the container. Most application programmers will prefer to use distributed transactions in such a controlled environment, where the work or enlisting, delisting and driving JMS resources is taken care of.



Copyright © 2003, 2004 Novell, Inc. All rights reserved. Copyright © 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.