Wednesday, September 21, 2011

JMS : Java Message Service


Introduction

Enterprise messaging systems

Enterprise messaging systems, often known as message oriented middleware (MOM), provide a mechanism for integrating applications in a loosely coupled, flexible manner. They provide asynchronous delivery of data between applications on a store and forward basis; that is; the applications do not communicate directly with each other, but instead communicate with the MOM, which acts as an intermediary.
The MOM provides assured delivery of messages (or at least makes its best effort) and relieves application programmers from knowing the details of remote procedure calls (RPC) and networking/communications protocols.

What is JMS?


JMS is a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging product.
The key to JMS portability is the fact that the JMS API is provided by Sun as a set of interfaces. Products that provide JMS functionality do so by supplying a provider that implements these interfaces.
As a developer, you build a JMS application by defining a set of messages and a set of client applications that exchange those messages.
  
JMS overview and architecture

Application


A JMS application comprises the following elements:

  • JMS clients. Java programs that send and receive messages using the JMS API.
  • Non-JMS clients. It is important to realize that legacy programs will often be part of an overall JMS application, and their inclusion must be anticipated in planning.
  • Messages. The format and content of messages to be exchanged by JMS and non-JMS clients is integral to the design of a JMS application.
  • JMS provider. As was stated previously, JMS defines a set of interfaces for which a provider must supply concrete implementations specific to its MOM product.
  • Administered objects. An administrator of a messaging-system provider creates objects that are isolated from the proprietary technologies of the provider. 
Administered objects

 To keep JMS clients portable, objects that implement the JMS interfaces must be isolated from a provider's proprietary technologies.
The mechanism for doing this is administered objects. These objects, which implement JMS interfaces, are created by an administrator of the provider's messaging system and are placed in the JNDI namespace.
The objects are then retrieved by JMS programs and accessed through the JMS interfaces that they implement. The JMS provider must supply a tool that allows creation of administered objects and their placement in the JNDI namespace.

There are two types of administered objects:

  • ConnectionFactory: Used to create a connection to the provider's underlying messaging system.
  • Destination: Used by the JMS client to specify the destination of messages being sent or the source of messages being received.
Although the administered objects themselves are instances of classes specific to a provider's implementation, they are retrieved using a portable mechanism (JNDI) and accessed through portable interfaces (JMS). The JMS program needs to know only the JNDI name and the JMS interface type of the administered object; no provider-specific knowledge is required

Interfaces

The high-level interfaces are:

  • ConnectionFactory: An administered object that creates a Connection. 
  • Connection: An active connection to a provider.
  • Destination: An administered object that encapsulates the identity of a message destination, such as where messages are sent to or received from.
  • Session: A single-threaded context for sending and receiving messages. For reasons of simplicity and because Sessions control transactions, concurrent access by multiple threads is restricted. Multiple Session s can be used for multithreaded applications.
  • MessageProducer: Used for sending messages.
  • MessageConsumer: Used for receiving messages.
  
Developing a JMS program

A typical JMS program goes through the following steps to begin producing and consuming messages:
  1. Look up a ConnectionFactory through JNDI.
  2. Look up one or more Destination s through JNDI.
  3. Use the ConnectionFactory to create a Connection. 
  4. Use the Connection to create one or more Session s.
  5. Use a Session and a Destination to create the required Message Producers and Message Consumers.
  6. Start the Connection
At this point, messages can begin to flow, and the application can receive, process, and send messages, as required.


Header







The following list gives the name of each header field of Message,its corresponding Java type, and a description of the field:




JMS permits an administrator to configure JMS to override the client-specified values for MSDeliveryMode, JMSExpiration and JMSPriority. If this is done, the header field value must reflect the administratively specified value.





Properties

The following list gives the name of each standard property of Message.JMS reserves the "JMSX" property name for these and future JMS-defined properties.



Using Properties

Property values are set prior to sending a message. When a client receives a message, its properties are in read-only mode. If a client attempts to set properties at this point, a  MessageNotWriteableException is thrown.

Message Body

There are five forms of message body, and each form is defined by an interface that extends Message. These interfaces are:
  • StreamMessage: Contains a stream of Java primitive values that are filled and read sequentially using standard stream operations.
  • MapMessage: Contains a set of name-value pairs; the names are of type string and the values are Java primitives.
  • TextMessage: Contains a String. 
  • ObjectMessage: Contains a Serializable Java object; JDK 1.2 collection classes can be used.
  • BytesMessage: Contains a stream of uninterpreted bytes; allows encoding a body to match an existing message format.
Each provider supplies classes specific to its product that implement these interfaces. It is important to note that the JMS specification mandates that providers must be prepared to accept and handle a Message object that is not an instance of one of its own Message classes.

Transaction

A JMS transaction groups a set of produced messages and a set of consumed messages into an atomic unit of work. If an error occurs during a transaction, the production and consumption of messages that occurred before the error can be "undone."
Session objects control transactions, and a Session can be denoted as transacted when it is created. A transacted Sessionalways has a current transaction, that is, there is no begin(); commit() and rollback() end one transaction and automatically begin another.
Distributed transactions can be supported by the Java Transaction API (JTA) XAResource API, though this is optional for providers.

Message Selection

JMS provides a mechanism, called a message selector, for a JMS program to filter and categorize the messages it receives.
The message selector is a String that contains an expression whose syntax is based on a subset of SQL92. The message selector is evaluated when an attempt is made to receive a message, and only messages that match the selection criteria of the selector are made available to the program.
Selection is based on matches to header fields and properties; body values cannot be used for selection. 


Acknowledgment

Acknowledgment is the mechanism whereby a provider is informed that a message has been successfully received.
If the Session receiving the message is transacted, acknowledgment is handled automatically. If the Session is not transacted, then the type of acknowledgment is determined when the Session is created.

There are three types of acknowledgment:
  • Session.DUPS_OK_ACKNOWLEDGE: Lazy acknowledgment of message delivery; reduces overhead by minimizing work done to prevent duplicates; should be used only if duplicate messages are expected and can be handled.
  • Session.AUTO_ACKNOWLEDGE: Message delivery is automatically acknowledged upon completion of the method that receives the message.
  • Session.CLIENT_ACKNOWLEDGE: Message delivery is explicitly acknowledged by calling the acknowledge() method on the Message.

A session’s recover method is used to stop a session and restart it with its first unacknowledged message. In effect, the session’s series of delivered messages is reset to the point after its last acknowledged message. The messages it now delivers may be different from those that were originally delivered due to message expiration and the arrival of higher-priority messages.
A session must set the redelivered flag of messages it redelivers due to a
recovery.

It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages. A message that is redelivered due to session recovery is not considered a duplicate message.

Duplicate Delivery of Messages

A JMS provider must never deliver a second copy of an acknowledged message. When a client uses the AUTO_ACKNOWLEDGE mode, it is not in direct control of message acknowledgment. Since such clients cannot know for certain if a particular message has been acknowledged, they must be prepared for redelivery of the last consumed message. This can be caused by the client
completing its work just prior to a failure that prevents the message acknowledgment from occurring. Only a session’s last consumed message is subject to this ambiguity. The JMSRedelivered message header field will be set for a message redelivered under these circumstances.

Duplicate Production of Messages

JMS providers must never produce duplicate messages. This means that a client that produces a message can rely on its JMS provider to insure that consumers of the message will receive it only once. No client error can cause a provider to duplicate a message. If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return
from the sending method.

Synchronous Delivery

A client can request the next message from a MessageConsumer using one of its receive methods. There are several variations of receive that allow a client to poll or wait for the next message.

Asynchronous Delivery

A client can register an object that implements the JMS MessageListener interface with a MessageConsumer. As messages arrive for the consumer, the provider delivers them by calling the listener’s onMessage method. It is possible for a listener to throw a RuntimeException.

Message Delivery Mode

JMS supports two modes of message delivery.

The NON_PERSISTENT mode is the lowest-overhead delivery mode because it does not require that the message be logged to stable storage. A JMS provider failure can cause a NON_PERSISTENT message to be lost.

The PERSISTENT mode instructs the JMS provider to take extra care to insure the message is not lost in transit due to a JMS provider failure. A JMS provider must deliver a NON_PERSISTENT message at-most-once. This means that it may lose the message, but it must not deliver it twice.
A JMS provider must deliver a PERSISTENT message once-and-only-once. This means a JMS provider failure must not cause it to be lost, and it must not deliver it twice.

PERSISTENT (once-and-only-once) and NON_PERSISTENT (at-most-once) message delivery are a way for a JMS client to select between delivery techniques that may lose a messages if a JMS provider dies and those which take extra effort to insure that messages can survive such a failure. 




     There is typically a performance/reliability trade-off implied by this choice. When a 



client selects the NON_PERSISTENT delivery mode, it is indicating that it values performance over reliability; a selection of PERSISTENT reverses the requested trade-off. The use of PERSISTENT messages does not guarantee that all messages are always delivered to every eligible consumer. 

The below table shows the overview of Durable Non Durable subscriptions:


















JMS Point-to-Point Model


A point-to-point (PTP) product or application is built around the concept of message queues, senders, and receivers. Each message is addressed to a specific queue, and receiving clients extract messages from the queue(s) established to hold their messages. Queues retain all messages sent to them until the messages are consumed or until the messages expire. PTP messaging has the following characteristics and is illustrated in below figure
  Each message has only one consumer.
  • A sender and a receiver of a message have no timing dependencies. The receiver can fetch the message whether or not it was running when the client sent the message.
  • The receiver acknowledges the successful processing of a message.
Use PTP messaging when every message you send must be processed successfully by one consumer.

JMS Publish/Subscribe Model

In a publish/subscribe (pub/sub) product or application, clients address messages to a topic. Publishers and subscribers are generally anonymous and may dynamically publish or subscribe to the content hierarchy. The system takes care of distributing the messages arriving from a topic's multiple publishers to its multiple subscribers. Topics retain messages only as long as it takes to distribute them to current subscribers. Pub/sub messaging has the following characteristics.
  • Each message may have multiple consumers.
  • Publishers and subscribers have a timing dependency. A client that subscribes to a topic can consume only messages published after the client has created a subscription, and the subscriber must continue to be active in order for it to consume messages.
The JMS API relaxes this timing dependency to some extent by allowing clients to create durable subscriptions. Durable subscriptions can receive messages sent while the subscribers are not active. Durable subscriptions provide the flexibility and reliability of queues but still allow clients to send messages to many recipients Use pub/sub messaging when each message can be processed by zero, one, or many consumers. Below diagram illustrates pub/sub messaging.



The following states the table showing the common interfaces.

JMS common interface
PTP domain
Pub/sub domain
ConnectionFactory
QueueConnectionFactory
TopicConnectionFactory
Connection
QueueConnection
TopicConnection
Destination
Queue
Topic
Session
QueueSession
TopicSession
MessageProducer
QueueSender
TopicPublisher
MessageConsumer
QueueReceiver, QueueBrowser
TopicSubscriber


Unification of domains with the common interfaces results in some domain-specific classes inheriting methods that are not suited for that domain. The JMS provider is required to throw an IllegalStateException should this occur in client code.


JMS Exceptions


Following are the standard JMS Exceptions.







No comments:

Post a Comment