Asynchronous messaging is a proven communication model for developing large-scale, distributed enterprise integration solutions. As opposed to regular request/reply-based communications in traditional client-server systems, messaging provides more flexibility and scalability because senders and receivers of messages are decoupled and are no longer required to execute in lockstep.
In addition to the traditional requirements for a messaging system, most application integration solutions also have a basic need for interoperability of messaging, since components often execute in a heterogeneous environment. Although Java Message Service (JMS) is a powerful API for pure Java environments, many integration solutions being developed today require the JMS server to be capable of communicating with:
These requirements are adequately met by the CORBA Notification products available from several messaging vendors. In response to the demonstrated need to integrate CORBA Notification and JMS, the OMG (Object Management Group) is currently working on standardizing interworking. Vendors such as PrismTech are also working ahead of the standards efforts to produce commercial solutions.
This article introduces JMS and CORBA Notification and describes the challenges being addressed by the OMG in providing an interworking solution.
The Notification Service is an OMG standard that allows multiple event suppliers to send events to multiple event consumers. It is a mature standard that has been one of the OMG's success stories. It has been widely used in a range of scenarios, such as the integrating mechanism for disparate telecom equipment, within large- scale routers on the Internet backbone, part of e-commerce frameworks for major banks, and as the messaging infrastructure to link satellites and their ground stations.
Notification differs from JMS in that its specification covers both the client interface and the messaging engine. Suppliers are de-coupled from consumers by means of an event channel, which takes care of client registration and de-registration and dissemination of events to multiple consumers. The channel also accommodates slow or unavailable consumers.
The Notification Service supports both push and pull models, and the architecture allows event channels to be federated without the use of intermediators. It extends the event service to include event filtering and a comprehensive "quality of service" (QoS) framework. Some of the more important QoS properties include:
The Notification Service also supports the concept of a structured event, which
qualifies as a "proper" message in terms of message middleware systems.
The main interfaces in the Notification Service are depicted in Figure 1, which
also shows that the Notification Service supports un-typed, structured, and sequence
client types for sending and receiving events.
A developer will typically perform the following steps in Notification Service client applications:
One of the more important architectural features of the Notification Service is that it supports channel federation without the use of intermediators that forward events from one channel to another; a proxy supplier can be connected directly to a proxy consumer. This feature implies that routing with the Notification Service can be achieved very easily for improved reliability, scalability, and performance. Since the Notification Service is based on the CORBA architecture, it also supports integration with applications not written in Java.
Several commercial implementations of the Notification Service are available from Hitachi, NEC, Fujitsu, and PrismTech. Typically, these products also include a suite of management tools to support the service.
The Java Message Service (JMS) defines a standard API that allows Java developers to easily build enterprise integration solutions. JMS is important in its own right because it provides a simplified and common way for Java clients to access message-oriented middleware. For example, JMS interfaces have been produced to both IBM and Tibco's messaging products. More importantly, with the introduction of message-driven beans (MDB), JMS has become even more tightly integrated into J2EE. This provides an asynchronous manner for Enterprise Java Beans (EJBs) to communicate with other elements in a distributed architecture. In a relatively short space of time, JMS has become an enormously popular messaging paradigm and enjoys support from all of the major messaging vendors.
It should also be recognized that JMS was designed as an abstraction over existing (and new) messaging products. This has a number of benefits, including the ability to replace message systems with no or few client modifications. This abstraction has also resulted in the following characteristics:
JMS supports a point-to-point (or queue) model and a publish/subscribe model, and it defines a number of message types that publishers and subscribers can exchange. Messages support properties that define how they should be treated by the message system. Subscribers can filter messages using an SQL grammar. Clients can be transient or durable, and messages can be sent or received in the context of a transaction.
Figure 2 shows the main concepts in JMS. Although the publish/subscribe and point-to-point communication models are very different from a conceptual point of view, the authors of JMS realized that the models have a lot in common. JMS is therefore centered on a generic messaging model, and publish/subscribe and point-to-point are derived (in the sense of interface inheritance) from the generic model.
The boxes in Figure 2 represent interfaces with the point-to-point interfaces on the left and the publish/subscribe interfaces on the right. The arrows leading from top to bottom in the figure represents the typical steps that a JMS developer performs developing client applications:
MessageProducer; if the application is a consumer, create a
MessageConsumerfrom the session.
JMS supports six different kinds of messages, which are used to carry different types of payload. The header of a message is the same regardless of the payload, which means that filtering is the same for all six message types. A message supports a number of properties to set priority, reliability, and other QoS properties, which will be interpreted and handled by the JMS server.
In order to properly support durable messages, JMS uses the notion of a durable subscriber. This is only necessary in the publish/subscribe model, as messages on a queue will be consumed by any queue receiver that connects to the queue in question. A durable subscriber is identified by a name, and the same operation is conveniently used to both create and re-create the subscriber.
In addition to the interfaces depicted in Figure 2, JMS supports a number of interfaces for transactional message delivery and consumption. The connection factory, connection, and session interfaces each have an interface with the XA prefix, which supports the Java Transaction API (JTA) for distributed transactions. This is typically supported when JMS is integrated into an application server.
Finally, JMS supports an expert facility called a "connection consumer." Although regular JMS clients will seldom use this API, it supports a portable way for integrating a JMS system into an application service. The connection consumer is used by application services to link a Message-Driven Bean to the functionality provided by a JMS vendor.
Although there is a comfortable overlap between the JMS and Notification Service communication models and capabilities, there are three areas where the integration must necessarily be defined:
We will describe how these issues are being addressed by the OMG standards work and by commercial implementations such as PrismTech's OpenFusion.
The JMS specification defines five different messages that all derive common functionality from the base Message interface. JMS messages are conceptually transmitted using the Notification Service, as depicted in Figure 3. Since JMS does not define a wire protocol, some type of message mapping is required.
JMS supports two ways of receiving events: a pull model or a push model. In the pull model, a JMS client invokes a method on the message consumer
in order to receive an event. In the push model, the consumer registers a callback
object with the consumer or session and messages are received asynchronously
by invocations of the
onMessage method in the callback interface.
Both models for receiving events map well to the Notification Service push and pull models. It is not possible, however, for a Notification Service consumer to be both a push and a pull consumer. It is expected, therefore, that the Notification Service will be extended to support a new delivery queue object that is similar to the JMS message consumer interface.
The Message interface is a base interface for all JMS messages. Since all JMS messages are interfaces, it is the responsibility of vendors of JMS client libraries to provide message implementations. A JMS message consists of a header, a set of properties and a body. The body part is different for each of the five different JMS message types. The header and properties are the same for all message types.
JMS only allows clients to filter on the message properties. To ensure that only message headers may be filtered, this information must be packaged into the filterable body of a structured event. This is the only information from JMS messages that becomes part of the filterable body. The Message interface supports three attributes that have well-defined meanings in the Notification Service:
EventReliabilityQoS in the variable header of a structured event is set to
Persistent. If delivery mode is
NON_PERSISTENT, the Notification
EventReliabilityQoS is set to
TimeoutQoS in the variable header of structured events. Expired messages are not visible to clients.
PriorityQoS in the variable header of structured events. Priority delivery mode is used to ensure that messages with higher priority are delivered before messages with lower priority.
The user-defined name/value pairs of a message can be any of the Java types
String; these types are converted
to IDL using the standard language mapping.
map message supports the
Message interface and provides a body of name/value
pairs. The body can conveniently be inserted into the remainder of the body field
of a structured event using the
PropertySeq data type, which is a sequence of
name/value pairs defined in the Notification Service IDL.
bytes message supports a body with uninterpreted data. The message supports
the methods of the
DataOutputStream interfaces from the
Java I/O package. As the body is an array of bytes, it is written to the remainder
of the body field of a structured event using an IDL octet sequence.
object message provides a body that can contain any Java object that supports
Serializable interface. This type of message is serialized onto a byte sequence
and written onto the array in the remainder of the body using the same
data type described above. On the receiver side, the byte sequence is converted
to an object input stream from which the object is read.
stream message adds a body that is a stream of objects. The objects on the
stream stack are written onto the remainder of the body using the
type. The elements in this sequence are mapped using the standard Java-to-IDL
text message provides a body, which is a Java String. The body is inserted
into a structured event by simply inserting the string into the
The Notification Service filtering uses a very rich grammar known as the Extended
Trader Constraint Language, while JMS uses the
where clause from SQL92. In order
to produce an interworking solution, it is necessary to extend the Notification
Service to support the SQL92 grammar defined in the JMS specification. In the
Notification Service, this grammar allows application developers to filter on
properties in the filterable body of structured events. The advantages of this
design are that filtering occurs on the server side to reduce network traffic
and that non-JMS applications can filter using SQL92.
The Notification Service is conceptually centered around a master queue, which contains all events that have been delivered to an event channel but not yet delivered to all connected consumers. Events in the master queue can be marked as persistent using different databases, in which case they will be recovered and re-delivered after a server crash.
The master queue disseminates events into a set of connected delivery queues. Each delivery queue represents an event consumer. The delivery queue supports various QoS properties such as ordering and discard policies, maximum queue size, etc. Also, the delivery queue supports fine-grained filtering using a variety of different constraint languages.
The delivery queue interface is similar to the JMS message consumer, which makes it easy for a JMS consumer to connect to and receive messages from a delivery queue. Since topics are implemented using the coarse-grained filtering, it is feasible to have one channel that receives and disseminates the publish/subscribe messages.
The master queues which are used as message stores by event channels support additional QoS properties that allow them to support JMS point-to-point functionality:
In addition to the general queue QoS properties described above, the OpenFusion Notification Service supports a QoS property to set the message acknowledge mode. This QoS property applies to the delivery queue and can be set to automatic, client, or lazy, in a similar manner to the JMS acknowledge modes. Again, this allows non-JMS applications to take advantage of these additional QoS properties.
Table 1 shows how interfaces in the Notification Service correspond to interfaces in JMS. As described above, topics are represented as event types that all get communicated on an event channel with the channel name "pubsub" while queues corresponds to individual channels with a name corresponding to the queue name. Structured events are mapped to messages as described earlier.
A JMS message consumer is a structured push consumer, which is connected to a delivery queue. This means the message consumer can be either a pull or a push consumer depending on the preferred style of the developer. Finally, a message producer is a structured push supplier, which simply sends messages using a push model.
Table 1: Relation between Notification Service and JMS interfaces.
|Notification Service||Java Message Service|
The Java Message Service is an important API because it provides simplified access to enterprise messaging systems from Java applications. Also, JMS is the API for messaging in an EJB environment, which is now becoming the platform of choice for service-side Java development. Although the JMS API is quite straightforward, it provides all the features that are expected from messaging middleware systems.
Many new applications are being built on the Java platform, but there will always be a need to integrate applications across operating systems and programming languages. Although fast, reliable, and transactional message delivery is provided by JMS, many applications will also require that JMS integrate easily with both non-Java components and other messaging systems.
This article has described how the CORBA Notification Service is being expanded
to support JMS. The mapping between the Notification Service and JMS is open
and easy to use, which means that it is straightforward to support integration
between pure JMS applications and other non-Java applications.
Steve Trythall is a senior manager for Prismtech Ltd, and an expert Java developer with experience in CORBA technologies and Java-CORBA interoperability.
Return to ONJava.com.
Copyright © 2009 O'Reilly Media, Inc.