Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Messaging Systems and the Java Message Service (JMS)

 
 

Articles Index

Message Service

Messaging systems are used to build highly reliable, scalable, and flexible distributed applications. This article discusses messaging systems in general, providing an overview of their features and types, and then describes how developers can write message-based applications using Java Message Service (JMS).

Distributed applications are proliferating, as are a host of previously unexplored problems of synchronization, reliability, scalability, and security. One solution is a Messaging System built from loosely coupled components communicating through messages.

The Java Message Service provides a consistent API set that gives developers access to the common features of many messaging system products.

What is a Messaging System?

In its essence, a messaging system allows separate, uncoupled applications to reliably communicate asynchronously. The messaging system architecture generally replaces the client/server model with a peer-to-peer relationship between individual components, where each peer can send and receive messages to and from other peers.

Messaging systems provide a host of powerful advantages over other, more conventional distributed computing models. Primarily, they encourage "loose coupling" between message consumers and message producers. There is a high degree of anonymity between producer and consumer: to the message consumer, it doesn't matter who produced the message, where the producer lives on the network, or when the message was produced.

This permits dynamic, reliable, and flexible systems to be built, whereby entire ensembles of sub-applications can be modified without affecting the rest of the system.

Other advantages of messaging systems include high scalability (commercial implementations boast the ability to support tens of thousands of clients and tens of thousands of operations per second), easy integration into heterogeneous networks, and reliability due to lack of a single point of failure.

Because of the reliable and scalable nature of messaging systems, they are used to solve many business and computing science problems. For example, they are the basis of such diverse applications as workflow, network management, communication services (voice over IP, voicemail, pager, email), customer care, weather forecasting, supply chain management, and many other systems. In addition, messaging systems are also invaluable as "glue" to bring together the disparate systems that inevitably result from mergers and acquisitions.

Message System Types

Two messaging systems models are in common use.

Publish/Subscribe

A publish/subscribe (pub/sub) messaging system supports an event driven model where information consumers and producers participate in the transmission of messages. Producers "publish" events, while consumers "subscribe" to events of interest, and consume the events. Producers associate messages with a specific topic, and the messaging system routes messages to consumers based on the topics the consumers register interest in.

Point-To-Point

In point to point messaging systems, messages are routed to an individual consumer which maintains a queue of "incoming" messages. Messaging applications send messages to a specified queue, and clients retrieve messages from a queue.

Frequently vendors will support either point-to-point, or publish/subscribe messaging models, or both.

Having looked at message systems in general, we now see how Java developers can take advantage of their power.

The Java Message Service

Java Message Service, part of the J2EE (Java 2 Enterprise Edition) suite, provides standard APIs that Java developers can use to access the common features of enterprise message systems. JMS supports the publish/subscribe and point-to-point models and allows the creation of message types consisting of arbitrary Java objects.

Design Goals

A fundamental design goal of JMS is to provide a consistent set of interfaces that messaging system clients can use independent of the underlying message system provider.

This way, not only are client applications portable across machine architectures and operating systems, they're also portable across messaging products. Client applications written to JMS will work without modification on all JMS compliant messaging systems. (This can be compared to the independence of Enterprise Java Beans components on the underlying middleware where the components run.)

JMS was also designed to:

  • Minimize the effort required by messaging system providers to implement the JMS APIs for their products.
  • Provide most of the functionality of common messaging systems.

Many messaging system vendors have implemented JMS for their products, allowing Java access to the functionality of their systems.

JMS Clients Can Use Java Facilities

JMS clients, since they are based on Java, can make use of existing Java APIs such as JDBC for database access, the JavaBeans components model, JNDI for naming services, JTA for client transaction control, or any of the J2SE and J2EE APIs for enterprise application services.

JMS Details

We now look at the details of building a messaging system client using JMS, starting with messages.

What is a Message?

In messaging systems the point of communication between applications is the message itself, so a developer using JMS must understand messages..

Although the definition of a message varies greatly between messaging systems, JMS provides a unified means of describing and accessing messages. A JMS message consists of three parts:

Message header
For message identification. For example, the header is used to determine if a given message is appropriate for a "subscriber"
Properties
For application-specific, provider-specific, and optional header fields
Body
Holds the content of the message. Several formats are supported, including TextMessages, which wrap a simple String; and ObjectMessages, that wrap arbitrary Java objects (which must be serializable). Other formats are supported as well.

TextMessages

A TextMessage wraps a simple String object. This is useful in situations where only strings are being passed. It is expected that many messaging systems will be based on XML, and TextMessages are a natural container for these.

Creation of a TextMessage object is simple, as these two lines of code indicate:

       TextMessage message = 
              session.createMessage();
       message.setText("hello world");
    

(We'll see the "session" object in the next section.)

A TextMessage created in this way is ready to be published to a messaging system.

ObjectMessages

An ObjectMessage, as its name implies, is a message wrapping a Java object. Any serializable Java object can be used as an ObjectMessage. If multiple objects must be transmitted in a single message, then a Collection object (such as a List or a Set) containing several serializable objects can be used.

This is how an Object message is created:

       ObjectMessage message = session.createObjectMessage();
       message.setObject(myObject);
    

Note on JNDI

JMS, like many of the J2EE APIs, makes use of JNDI (Java Naming and Directory Interface) to discover needed resources. A detailed discussion of JNDI is beyond the scope of this article, but more information can be found at Java Naming and Directory Interface (JNDI)

Building a JMS Client

A typical JMS client can be built following these basic steps:

  1. Create a connection to the messaging system provider
  2. Create sessions, for sending and receiving messages
  3. Create MessageProducers and MessageConsumers to create or receive messages

Once these steps have been performed, a message-producing client will create messages and publish them to topics, while a message-consuming client will listen for messages associated with a topic, and consume them as they arrive.

To illustrate in detail how this works, we examine a typical message producer, used to publish messages to a topic in a pub/sub messaging system. Note that all exception handing code has been omitted for clarity.

Create a Connection

A Connection provides the client access to the underlying messaging system, and performs resource allocation and management. Connections are created using a ConnectionFactory, which is typically located using JNDI.

This code illustrates the steps involved in creating a connection:

    Context messaging = new InitialContext();  
    // get JNDI context
    TopicConnectionFactory topicConnectionFactory = 
       (TopicConnectionFactory) 
          messaging.lookup("TopicConnectionFactory");
    TopicConnection topicConnection =
      topicConnectionFactory.createTopicConnection();
        

Create Sessions

Sessions are lightweight JMS objects which provide a context for producing and consuming messages. Sessions are used to build message producers and message consumers, as well as to build the messages themselves.

       TopicSession session = 
          topicConnection.createTopicSession(false,
                          Session.CLIENT_ACKNOWLEDGE);
        

The two parameters to createTopicSession() control transactions and message acknowledgment.

Locate a Topic

A topic (also known as a subject, group, or channel) is located through JNDI. The topic identifies the messages being sent or received. In pub/sub systems, the subscribers subscribe to a given topic, while the publishers associate topics with the messages they publish.

Here we create a topic called "WeatherData."

     Topic weatherTopic = messaging.lookup("WeatherData");
        

Start the Connection

During the above initialization steps, message flow is inhibited to prevent unpredictable behavior during initialization. Once initialization is complete, the connection must be told to initiate the message flow.

        topicConnection.start();
        

Create a Message Producer

In the publish/subscribe domain, a producer publishes messages to a given topic. This code shows the creation of a publisher and the subsequent building and publishing of a simple text message.

      TopicPublisher publisher = 
            session.createPublisher(weatherData);
      TextMessage message = session.createMessage();
      message.setText("temperature: 35 degrees");

      publisher.publish(message);
        

A similar process is followed to create subscribers, as well as JMS clients for point-to-point systems. Complete details of this process can be found in [1].

Conclusion

We have seen the basic concepts involved in using JMS to build a messaging based application. Before writing JMS code, you will need access to a JMS compliant messaging system. A list of JMS compliant vendors is available at:

   JMS Vendors

Creating and building a JMS based application is simple, yet provides the basis for building powerful, scalable, and highly reliable distributed systems.

Note that JMS is far more complex than is discussed in this article and provides support for administration, security, error handling and recovery, optimization, distributed transactions, message ordering, message acknowledgment, and more.

For more information and documentation on the Java Message Service, see:

   Java Message Service Documentation

References

Much of this article is based on the Java Message Service Documentation

Reprinted with permission of SunServer.

Coffecup Logo

About the Author

John Wetherill is a Staff Engineer and Technology Evangelist at Sun Microsystems, currently focusing on Jini and JavaSpaces technologies, and distributed systems in general. In his spare time he is working on the development of a Java and Jini technologies enabled house in the Santa Cruz mountains, integrating this with wearable technology.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.