1.0    Introduction

 

In October 1998, JavaSoft released the Java Message Service (JMS) specification v1.0.1, an API for accessing enterprise messaging  systems from Java.

 

         

1.1           What is Enterprise messaging ? 

 

Enterprise messaging is a method for transmitting data  from one enterprise application to another. Its main advantage is that enterprise messaging eliminates the need to synchronize applications from multiple vendors running on different platforms. Such program-to-program messaging products will become increasingly important as corporate IT groups build electronic commerce systems, which typically consist of a loose federation of applications that   communicates over the Internet.

 

The Object Management Group (OMG), Microsoft, and Sun's JavaSoft are all working to make Enterprise messaging mechanisms which handles the transmission of messages between systems at different times, through store-and-forward mechanisms, or message queues. (Bowen , 1998).

 

The common building block of a message is a “message”. Messages are events, requests and replies that are created by and delivered to enterprise applications. Messages contain formatted data with specific business meaning. (Sundsted 1999 January)

 

Enterprise messaging is not relatively well known as other distributed computing technologies such as Common Object Request Broker Architecture (CORBA) and Component Object Model (COM).  These models are based on the Remote Procedure Call (RPC) architecture. RPC allows one application to request a service from another application running on another platform. It is a "synchronous" operation, which means the requesting application must cease running until the data from the other application is received.

 

Enterprise messaging, on the other hand, is "asynchronous," according to Ian Brackenbury, an IBM engineer and chief scientist in the company's Hursley Laboratory in Hursley, England. "A messaging infrastructure puts up a queue between an application on Machine One and an application on Machine Two," he says. "It provides the buffer between the different protocols and architectures on either side." (Nerney, 1999)

 

 

That's where the Java Messaging Service (JMS) comes in. JMS describes how to create reliable message queues. These queues stores packages that contain transaction or other information and the procedures used by the queues to exchange these packages. If a message queue at another application can't be accessed because it's too full with other messages or because the network isn't available, the message remains in protective storage until a new connection is made. This API is intended to support messaging features such as reliable queues, publish/subscribe support, and capabilities for "push" and "pull" services. (Kadel 1997)

 

 

 

1.2           What is Java Messaging Service ? 

 

 

JMS is a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging  product. Enterprise messaging is recognized as an essential tool for building enterprise applications and Ecommerce systems, and JMS   provides a common way for Java programs to create, send, receive, and read an enterprise messaging system's messages.

 

Rather than communicate directly with each other, the components in an application based around a message service send messages to a message server. The message server, in turn, delivers the messages to the specified recipients. This might seem like an extra, unnecessary layer of software, but the advantages a message service provide often outweigh the disadvantages. The message service model is much like the model behind the postal service. We could directly deliver our own mail, but letting someone else do it greatly simplifies our life. The addition of the messaging service adds another layer to the application, but it greatly simplifies the design of both the clients and the servers (they are no longer responsible for handling communications issues), and it greatly enhances scalability. (Sundsted, 1999 January)


 

 


(Sundsted, 1999 January)

 

 

1.3    Specific goals of the JMS API specification :

 

·         A key goal of the JMS API is to unify the packaging of these capabilities and to minimize the set of concepts a Java programmer must learn in order to use messaging products.

 

·         Provide an API suitable for the creation of messages that match the format used by existing, non-JMS applications

 

·         Support the development of heterogeneous applications that span operating systems, platforms, architectures, and computer languages

 

·         Support messages that contain serialized Java objects

 

·         Support messages that contain XML pages.

 

(Sundsted, 1999 January)

1.4    The advantages of JMS

 

 

 

·         JMS component architecture will let programmers built software products which are independent of messaging mechanisms. The coupling between the resources of the application will be minimal. This will enhance the  reusability of the  components and minismise development time for the application.

 

 

·         Most of the IT systems undergo heavy modifications and upgrade processes in a very short amount of time. This may result in changes at both client and server architectures. This problem of scalability is well addressed by JMS. Since the messaging mechanism is independent from the application JMS will handle the alterations in the system.

 

 

·         Most of Enterprise applications reside in multiple platforms. These heterogeneous platforms may receive / submit different types of messages. JMS is purely written in Java. As long the different components could understand the  JMS message architecture, the platform which they reside and the programming language they are written is irrelevant.

 

·         The messaging service is responsible for quality of service issues such as reliable delivery. This frees the components (which may be custom built) of the application from having to deal with these fairly generic issues.

 

·         JMS is responsible for delivering and queuing the messages to the clients. This will free up the servers to process more information.

 

 

 

2.0      JMS  Messaging architecture

 

 

Java Message Service Specification  defines many interface for message services but does not define an implementation. This is deliberately done by the JMS inventors to support the existing message handling software. Their strategy was to let programmers develop JMS applications wrapping existing software infrastructures. This way the programmers need not to rewrite a whole application to implement JMS and will not have any dependency to a particular software vendor. Therefore JMS will be vendor neutral and comply with existing products (Sundsted, 1999 March)

 

The JMS API specification defines two different messaging paradigms: point-to-point and publish/subscribe. These two paradigms, or domains, represent the two leading models of messaging provided by existing messaging products.

 

Both these models are very similar. The table below will illustrate  the key interfaces of both models. Both models will have the same parent interfaces (described in the first column). The second and third columns will illustrate the variations of the JMS parent classes in different models.

 

2.1    JMS  Key Interface clasess

 

 

Table 0-1 Relationship of Point-to-Point and Publish/Subscribe interfaces

 

JMS Key Interface

Publish/Subscribe Model

Point To Point Model

 

 

 

ConnectionFactory

QueueConnectionFactory

TopicConnectionFactory

Connection

QueueConnection

TopicConnection

Destination

Queue

Topic

Session

QueueSession

TopicSession

MessageProducer

QueueSender

TopicPublisher

MessageConsumer

QueueReceiver, QueueBrowser

TopicSubscriber

 

 

 

2.1.1 How these interfaces support to build JMS applications

 

The ConnectionFactory is an administered object used by a client to create a Connection, which itself is an active connection to a JMS provider. Because of the authentication and communication setup processed when a Connection is created (most clients will do all their messaging with only one), it is a relatively heavyweight JMS object. The Destination encapsulates the identity of a message destination and contains provider-specific address and configuration information.

 

Sessions are the JMS entities that support transactions and asynchronous message consumption. Sessions provide the throughput advantages of concurrency with the ease of single-threaded programming to send and receive messages. A single Session is responsible for sending a message from a MessageProducer to a MessageConsumer.

 

MessageProducer and MessageConsumer objects are created by a Session and are used for sending and receiving messages, respectively. In order to guarantee the delivery of a message, messages to and from the remote server object should be sent in persistent mode. The persistent mode instructs the JMS provider to log the message to stable storage as part of the client's send operation. This in turn ensures that the message will survive a JMS provider failure.

 

Session, MessageProducer, and MessageConsumer JMS objects do not support concurrent use, while ConnectionFactory, Destination, and Connection objects do. After these objects and common facilities are in place, a client application has the basic JMS setup needed to produce and consume messages.

(Sun Micro Systems, 1998)

 

 

2.1.2 Types of Messages communicated by JMS

 

JMS has five types of message, and while the type used depends on the requirements of the application, most client implementations use either MapMessage or ObjectMessage.

 

ObjectMessages  messages containing a serializable Java objects. MapMessages use a set of name-value pairs, where names are strings and values are Java primitive types. Alternatively, JMS TextMessages might be more appropriate for XML-based messages, where JMS is used for the transport layer, but not data definition.

 

All JMS messages support the acknowledged method for use; if a client uses automatic acknowledgment, calls to acknowledge are ignored. JMS messages sent by a Session to a Destination must be received in the order in which they were sent, so their implementations must provide for the sequencing of incoming messages.

(Sun Micro Systems, 1998)

 

JMS applications requires Remote Method Invocation (RMI) or Java Naming and Directory Interface (JNDI) to lookup the different client, server objects. RMI method is used for the purpose of this research paper.

 

After understanding the key interface classes of JMS we can proceed to explore the two different models of JMS implementation.

 

·         Point-to-Point  Model

·         Publish / Subscribe Model

 

 

 

2.2        Point-to-Point  Model

 

Point-to-point (PTP) products are built around the concept of message queues. Each message is addressed to a specific queue; clients extract messages from the queue(s) established to hold their messages.

 

The destination in the point-to-point domain is called a “queue”. The simple point-to-point example in the diagram below contains a single queue and two clients. One client sends messages to the queue, and the other receives messages from the queue. Assume the queue and both of the clients already exist and are connected as illustrated.

 

 Both clients already hold active connections to the queue: both the QueueReceiver r and the QueueSender s have been initialized.  The receiver r and the sender s are used to communicate with the queue.

 

          These are the key steps in the message handling architecture.

 

1 The QueueSender s, sends Message m to the queue.

2 The QueueReceiver r is ready to receive the Message m from the Queue

3 The Queue sends Message m to QueueReceiver r


 

 


2.2.1 Creating Point To Point application

 

 

1) Creating QueueConnectionFactory. :- The system administrator has already created QueueConnectionFactory  RMI object.

 

QueueConnectionFactory queueconnectionfactory = null;

queueconnectionfactory= (QueueConnectionFactory)Naming.lookup(“connectionFactoryName”);

 

 

2) Getting a Message Queue :- The system administrator has already created message queue   RMI object.

 

Queue queue = null;

queue = (Queue)Naming.lookup(“QueueName”);

 

3) Getting a QueueConnection :-After getting a QueueConnectionFactory we create a QueueConnection

 

QueueConnection queueConnection;

queueConnection = queueConnectionFactory.createQueueConnection();

 

4) Creating a QueueSession

 

This will be used to create a QueueSender (if we want to send messages) or a QueueReceiver (if we want to receive messages).

We use the QueueConnection.createQueueSession method to do this, supplying two parameters:

 

• A boolean indicating whether this queue session will be transacted or not

• The mode of acknowledging message receipt

 

QueueSession session;

session = queueConnection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

 

5) Creating a QueueSender

 

Having obtained the QueueSession, we use it to create a QueueSender, if we are going to be sending messages to the queue. This is achieved with the QueueSession.createSender method. We supply one parameter; the queue we are going to be sending messages to.

 

QueueSender sender;

sender = session.createSender(queue);

 

6) Creating a QueueReceiver

 

Having obtained the QueueSession, we use it to create a QueueSender, if we are going to be sending messages to the queue. This is achieved with the QueueSession.createSender method. We supply one parameter; the queue we are going to be sending messages to.

 

QueueSender sender;

sender = session.createSender(queue);

 

7) Send the message

 

By invoking the “send” method in QueueSender the message is sent to the receiver.

 

QueueSender.send(new Message_Text(“text to be sent”));

 

(Sun Micro System 1998, Sundsted 1999 March)

 

 

 

2.3        Publish / Subscribe Model

 

In this model clients address messages to some node in the content hierarchy. 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 node’s multiple publishers to its multiple subscribers.

 

The destination in the publish/subscribe domain is called a “topic”. The simple publish/subscribe example in the diagram below contains a single topic and two clients. One client subscribes to the topic and the other publishes messages to the topic. The topic takes care of distributing messages from the publisher to the subscriber. Assume the topic and both clients already exist and are connected as illustrated.

 

Both clients already hold active connections to the topic: both the TopicPublisher p and the TopicSubscriber s have been initialized. The publisher p and the subscriber s are used to communicate with the topic.

 

The following are the key steps in this communication model.

 

1.During the subscriber's initialization, the subscriber registers an instance of a class that implements the MessageListener  interface by invoking s.setMessageListener(l) where ‘s’ is the subscriber and ‘l’ is the message listener. The topic keeps track of all of the subscribers subscribed to the topic.

 

 2.The publishing client arrives at a point in its processing when it needs to send a message. It creates the message and publishes it by invoking p.publish(m), where ‘p’ is the publisher and ‘m’ is the message.

 

3.Immediately, the topic delivers the message to the subscriber by invoking l.onMessage(m). l is a reference to the message listener instance registered earlier.

 

 Once all subscribers have been notified, the message is removed from the topic. (Sundsted, 1999 March)

 

 

 


 

 


2.3.1 Creating Publish/subscribe application

 

 

1) Creating TopicConnectionFactory.

 

The system administrator has already created TopicConnectionFactory RMI object.

 

TopicConnectionFactory topicConnectionFactory = null;

TopicConnectionFactory  = (TopicConnectionFactory)Naming.lookup(“connectionFactoryName”);

 

 

2) Creating  a Message Topic

 

An administrator has created and configured "StockQueue" for our use.

 

Topic stockTopic;

stockTopic = (Topic)Naming.lookup(“TopicName”);

 

 

 

3) Getting a TopicConnection

Having obtained the TopicConnectionFactory, we use it to create a

TopicConnection.

 

TopicConnection topicConnection;

topicConnection = topicConnectionFactory.createTopicConnection();

 

 

4) Getting a TopicSession

Having obtained the TopicConnection, we use it to create a TopicSession. This will be used to create a TopicPublisher (if we want to publish messages) or a TopicSubscriber (if we want to receive messages). We use the TopicConnection.createTopicSession method to do this, supplying two parameters:

 

• A boolean indicating whether this topic session will be transacted or not;

• The mode of acknowledging message receipt

TopicSession session;

 

 

session = topicConnection.createTopicSession(false,

Session.CLIENT_ACKNOWLEDGE);

 

5) Having obtained the TopicSession, we use it to obtain a TopicSubscriber if we are going to subscribe to the topic in order to receive messages. This is achieved with the TopicSession.createSubscriber method. We supply the topic we wish to subscribe to.

 

First we create a topic subscriber:

 

TopicSubscriber subscriber;

subscriber = session.createSubscriber(stockTopic);

 

In order to asynchronously receive messages as they are delivered to our subscriber, we need to create a message listener which implements the javax.jms.MessageListener interface.

Our listener class (lets call it StockListener.java) would look something like:

 

 

public class StockListener implements javax.jms.MessageListener

{

void onMessage(Message message)

{

// unpack and handle the messages we receive.

}

}

 

Next we register this message listener with our subscriber:

 

StockListener myListener;

subscriber.setMessageListener(myListener);

 

 

 

6) Getting a TopicPublisher

 

Having obtained the TopicSession, we use it to create a TopicPublisher if we are going to be publishing messages to the topic. This is achieved with the TopicSession.createPublisher method. We supply one parameter; the topic we are going to be publishing messages to.

 

TopicPublisher publisher;

publisher = session.createPublisher(stockTopic);

 

 

(Sun Micro System 1998)

 

 

2.4    What JMS does not support. 

 

·         Does not support load balancing mechanisms. Most products support multiple, cooperating clients implementing a critical service. The JMS API will not let different clients to act together to perform as a single client.

 

·         JMS does not specify how to control privacy issues or implement digital signatures to verify the authenticity.

 

·         JMS API does not define a API to administer the message products.

 

(Sun Micro System 1998)

 

2.5    JMS driven Products

 

“Progress SonicMQ”, is one of the first enterprise messaging middleware products to leverage the Java Message Service (JMS) specification. Going beyond the relatively new JMS specification, SonicMQ can distribute workloads, and it supports extensible markup language types, uses graphically based administration, and has the ability to address topics in a hierarchical nature, said Progress officials.  Not only will JMS be used to integrate disparate applications, but Progress expects it to soon integrate disparate messaging protocols as well, such as IBM's MQSeries and Microsoft Message Queue, as well as application integration products like Neon. (Gardner,1999)

 

Some other implementations of JMS are IBM’s “MQSeries” and Microsoft’s “MSMQ”. The diagram below rates these two products in action. (Network Computing, 1999).


 


3.0    Conclusion

 

 

Java Message Service is key element of the Enterprise Java architecture. JMS will let developers build robust and flexible software to manage message handling mechanisms on heterogeneous platforms. JMS  is a set of interfaces that could be easily wrapped into existing message handling systems or will let developers build message handling with much ease. It also acts as a standard message API to the software vendors to create new message handling software.

 

JMS could be implemented as two different models. Those are

·         Point to Point Model.

·         Publish / Subscribe Model.

 

Both these models will enable developers to create a variety of different message applications to support Java Enterprise software.

4.0    Appendices

 

4.1      Source Code for a Point to Point JMS Application. (Sundsted , 1999 March)

 

<PRE>

Queue interface

 

 

import java.rmi.Remote;

import java.rmi.RemoteException;

 

public interface Queue extends Remote

{

  public String  getQueueName()  throws RemoteException;

}

 

 

Then the Queue_Impl interface:

 

 

import java.rmi.RemoteException;

 

import java.rmi.server.UnicastRemoteObject;

 

public

class Queue_Impl

extends UnicastRemoteObject

implements Queue

{

  private String _stringQueueName = null;

 

  public Queue_Impl(String stringQueueName)throws RemoteException

  {

    _stringQueueName = stringQueueName;

  }

 

  public  String  getQueueName()  throws RemoteException

  {

    return _stringQueueName;

  }

 

  public  int  hashCode()

  {

    return _stringQueueName.hashCode();

  }

 

  public  boolean  equals(Object object)

  {

    return object.equals(_stringQueueName);

  }

}

 

 

Connection factories

 

import java.rmi.Remote;

import java.rmi.RemoteException;

 

public interface QueueConnectionFactory extends Remote

{

  public  QueueConnection  createQueueConnection()  throws RemoteException;

}

 

 

 

Then the QueueConnectionFactory_Impl interface:

 

 

import java.rmi.Naming;

import java.rmi.RemoteException;

 

import java.rmi.server.UnicastRemoteObject;

 

public class QueueConnectionFactory_Impl extends UnicastRemoteObject

implements QueueConnectionFactory

{

  public  QueueConnectionFactory_Impl()  throws RemoteException

  {

  }

 

  public  QueueConnection  createQueueConnection()  throws RemoteException

  {

    return new QueueConnection();

  }

 

  public  static  void  main(String [] rgstring)

  {

    try

    {

      Naming.rebind(rgstring[0], new QueueConnectionFactory_Impl());

    }

    catch (Exception exception)

    {

      System.out.println(exception);

    }

  }

}

 

 

Connections

 

import java.rmi.Naming;

import java.rmi.NotBoundException;

import java.rmi.UnknownHostException;

import java.rmi.RemoteException;

 

import java.net.MalformedURLException;

 

import java.io.Serializable;

import java.io.IOException;

 

import java.util.Hashtable;

 

public

class QueueConnection

implements Serializable

{

  private Hashtable _hashtable = new Hashtable();

 

  private HQueue  lookup(Queue queue)  throws MalformedURLException,

         NotBoundException,

         UnknownHostException,

         RemoteException,

         IOException

  {

    HQueue hqueue = null;

 

    if ((hqueue = (HQueue)_hashtable.get(queue)) != null)

    {

      return hqueue;

    }

 

    hqueue = (HQueue)Naming.lookup(queue.getQueueName());

 

    _hashtable.put(queue, hqueue);

 

    return hqueue;

  }

 

  void  send(Message message, Queue queue)  throws NotBoundException,

         RemoteException,

         IOException

  {

    lookup(queue).send(message);

  }

 

  Message  receive(Queue queue)  throws NotBoundException,

         RemoteException,

         IOException

  {

    return lookup(queue).receive();

  }

 

  public  QueueSession  createQueueSession()

  {

    return new QueueSession(this);

  }

}

 

 

Sessions

 

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

 

import java.io.Serializable;

import java.io.IOException;

 

public class QueueSession implements Serializable

{

  private QueueConnection _queueconnection = null;

 

  QueueSession(QueueConnection queueconnection)

  {

     _queueconnection = queueconnection;

  }

 

  void  send(Message message, Queue queue)  throws NotBoundException,

         RemoteException,

         IOException

  {

    _queueconnection.send(message, queue);

  }

 

  Message  receive(Queue queue)  throws NotBoundException,

         RemoteException,

         IOException

  {

    return _queueconnection.receive(queue);

  }

 

  public  QueueSender  createSender(Queue queue)

  {

    return new QueueSender(this, queue);

  }

 

  public  QueueReceiver  createReceiver(Queue queue)

  {

    return new QueueReceiver(this, queue);

  }

}

 

 

Message producers

 

 

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

 

import java.io.Serializable;

import java.io.IOException;

 

public class QueueSender implements Serializable

{

  private QueueSession _queuesession = null;

  private Queue _queue = null;

 

  QueueSender(QueueSession queuesession, Queue queue)

  {

    _queuesession = queuesession;

    _queue = queue;

  }

 

  public  void  send(Message message)  throws NotBoundException,

         RemoteException,

         IOException

  {

    _queuesession.send(message, _queue);

  }

}

 

 

Message consumers

 

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

 

import java.io.Serializable;

import java.io.IOException;

 

public class QueueReceiver implements Serializable

{

  private QueueSession _queuesession = null;

  private Queue _queue = null;

 

  QueueReceiver(QueueSession queuesession, Queue queue)

  {

    _queuesession = queuesession;

    _queue = queue;

  }

 

  public

  Message

  receive()

  throws NotBoundException,

         RemoteException,

         IOException

  {

    return _queuesession.receive(_queue);

  }

}

 

</PRE>


 

 

4.2  Installing and running the application

 

 

1) Copy the files in the floppy disk to a local directory in your hard drive.

 

2) Start the RMI registry.

This message service implementation relies heavily on the RMI registry for directory services. It must be running on the machine on which the application will run.

 

set CLASSPATH=.
start rmiregistry

 

3)  Create a queue

This step creates a queue, registers the queue with the RMI registry, and also creates an administered object of type Queue.

The queue must have a name. This is the name with which it will register itself with the RMI registry (so it must be a valid RMI name). It is also the name by which clients will locate the proper administered object.

 

start java TheQueue
 

 

4)  Create a connection factory of the appropriate type.

This step creates a queue connection factory and registers it with the RMI registry.

 

start java TheQueueConnectionFactory

 

5)  Run the program

You are now free to use the queue. ‘Main’ class has some sample code to implement a simple Point-to-Point JMS application

 

java Main TheQueue TheQueueConnectionFactory

 

 

5.0    Bibliography

 

·         Bowen, S. T., (1998),  “Vendors queue-up messaging “ , InfoWorld, February http://www.infoworld.com/cgi-bin/displayArchive.pl?/98/08/c02-08.31.htm

 

·         Gardner, D., (1999), “Progress Delivers Messaging Service based on JMS”, JavaWorld, October, http://www.javaworld.com/javaworld/jw-10-1999/jw-10-iw-progress.html

 

·         Kadel, R., (1997),  Java Solutions to Enterprise Computing “, JavaWorld http://www.javaworld.com/javaworld/javaone97/java1-97-enterprise.html

 

·         Network Computing,  (1999), “Living On Java “, October, http://www.nwc.com/910/910f14.html

 

·         Nerney, C. (1999)  Java boosts enterprise messaging”, Network World Fusion , August, http://www.nwfusion.com/news/temp/45871_08-17-1998.html

 

·         Sundsted  T., (1999)  “Messaging helps move Java into the enterprise ”, JavaWorld , January,

http://www.javaworld.com/javaworld/jw-01-1999/jw-01-jms.html

 

·         Sundsted  T., (1999)  “Messaging makes its move, Part 1 ”, JavaWorld, , February,

http://www.javaworld.com/javaworld/jw-02-1999/jw-02-howto.html

 

·         Sundsted  T., (1999)  “Messaging makes its move, Part 2 ”, JavaWorld, March

 http://www.javaworld.com/javaworld/jw-03-1999/jw-03-howto.html

 

·         Sun Micro Systems (1998),  “Java Messaging Service ”,

http://java.sun.com/products/jms/jms-101-spec.pdf