1 Messaging and JMS
1.1 What is messaging?
1.2 Different types of message architectures
1.3 Existing JMS provider
2 Java Messaging Service API
2.2 What JMS does not include
2.3 JMS details
2.4 JMS message model
2.5 JMS common facilities
2.6 JMS point-to-point model
2.7 JMS publish/subscribe model
2.8 Remaining API
3 Overview Infomatec Messaging Queue
3.2 UML design
4 The basic message system
4.2 Create connection
4.3 Send messages
4.4 Storing of objects
4.5 Receive messages
4.6 Close connection
5 Extension of IMQ
5.2 Basic Publish/Subscribe
5.4 Message types
5.6 Error handling
5.7 Dynamic class loading
5.8 Distribution of class files
5.9 Log file
5.11 Server command line
5.12 IMQ and Applets
6.1 Properties files
6.2 Administrative objects
6.3 Administration tool
7 The Infomatec package
7.1 JNDI browser
7.3 IMQ dependent administrative objects
8 Using and testing IMQ
8.1 Setting up the system
8.2 Example and test programs
9.1 Remaining Features
9.3 RMI over HOP
9.4 Multiple server system
9.5 RMI and firewalls
A Error Codes
C Function categories
D. l Server
D.5 Possible settings on the client side:
E Administration tool tabs
F CD - content
G Source code
H Used tools
I JMS provider
List of Figures
1.1 Fully connected Network
1.2 Virtual Fully Connected Network
2.1 Relationship of PTP and Pub/Sub interfaces classdiagram
2.2 JMS Message
2.3 Point to point model
2.4 Publish / Subscribe model
3.1 A generic naming service
3.2 RMI interface - implementation separation
3.3 RMI architecture
4.1 Use case diagram of the basic messaging system
4.2 Direct access between connections and queues
4.3 Each connection has a control thread
4.4 One distribution thread for all connections
4.5 Extra distribution thread for reading and for writing of messages
4.6 RMI connection setup
4.7 Sending a message
4.8 Priority linked list structure
4.9 Persistent messages interface
4.10 Modified connection ArrayList
4.11 Queue registration
4.12 Server registration
4.13 Receiving part of the client
5.2 Publish/Subscribe model
5.3 Public/Subscribe architecture
5.4 Publish/Subscribe distribution solutions
5.5 Sending a topic message
LIST OF FIGURES
5.6 Request and reply
5.7 Queue browser
5.8 Dynamic class loading on the client side
5.9 User/password checking
6.1 Administrative objects
6.2 Administration tool
7.1 Browser info in JNDI
7.2 Server info - getTopicSubscriber()
7.3 Serverlnfo - get Active Queues ()
7.4 Provider dependent ConnectionFactory
9.1 Message selector
9.2 Protocol manager interfaces
9.3 JMS Performance Chart
9.4 RMI vs. CORBA world
9.5 RMI-ΠΟΡ overview
9.6 Multi router message system
9.7 RMI client behind a firewall
9.8 RMI client and server behind a firewall
E. l Server tab
E.2 Client tab
E.3 JNDI tab
E.4 Protocol tab
E. 5 User tab
F. l CD content
List of Tables
2.2 Relationship of PTP and Pub/Sub interfaces
2.3 JMS objects that support concurrent use
3.1 Template for a contract
A.l Error codes
C.l Function categories
The Java Messaging Service (JMS) is a middleware messaging specification which enables application developers to use messages easy and reliable in an enterprise system.
Goal of the master thesis was to evaluate the JMS API 1.0.2 and provide an implementation with all the main features specified. The result is IMQ, a fast and stable open protocol, open database solution with two working wire protocols - RMI and Sockets.
The main features of IMQ are:
- A fast and stable JMS implementation
- Point-to-Point and Publish/Subscribe support
- Dynamic open protocol
- Open database
- Full JNDI support
- Graphical administration tool
- JMS extensions like JNDIBrowser, server command line and log files.
I want to thank Infomatec Augsburg and Infomatec Australia for the opportunity to do my master thesis in Sydney /Australia. A lot of organization had to be done to make this stay possible. Especially Quy and Pauline Tonthat in Sydney and Doris Schilling in Augsburg did a great job to get my visum for Australia.
Furthermore, I want to thank Prof. Dr. Gerhard Meixner, who agreed to look after this thesis over a distance of 16 400 km and 9 time zones.
The support of Infomtec Australia was excellent. They did everything to make the five months in Sydney as easy as possible by helping me to find a place to stay and showing me around in the first few weeks.
The thesis has several references to classes and function names. Their names are displayed in emphasized style: e.g. RemoteException, getMessage()
Code segments show only relevant sections and will be displayed like this:
illustration not visible in this excerpt
To make the code easier to read, own conventions have been used during the development of the prototype:
- Local variables start with an underscore: e.g. strName
- Parameters do not have an underscore.
For the naming of the classes the following scheme is used:
illustration not visible in this excerpt
Chapter 1 Messaging and JMS
1.1 What is messaging?
Messaging is playing an increasingly important role in enterprise computing. Its advantages are a natural result of several factors: the trend towards peer-to-peer computing, greater platform heterogeneity, and greater modularity, coupled with the trend away from synchronous communication between processes.
In its effort to stay on top of important industry trends, Sun announced April 1998 (at the JavaOne Developer Conference) its plans to publish the Java Message Service (JMS) API, an interface for using existing enterprise messaging systems in a uniform manner. The version 1.0 specification, which was released in July, provides a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging product.
Since its release, almost twenty vendors have stepped up to endorse the specification (including companies like IBM, Oracle, and BEA) and many companies have produced implement at ions.
1.1.1 Messaging services
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 provides often outweigh this single disadvantage. 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 common building block of a messaging service is the message. Messages are events, requests, and replies that are created by and delivered to enterprise applications.
Messages contain formatted data with specific business meanings.
Beyond the message, however, messaging services display a surprising degree of diversity. For example, a messaging service may:
- Allow messages to be prioritized
- Deliver messages either synchronously or asynchronously
- Guarantee messages are delivered once and only once
- Support message delivery notification
- Support message time-to-live
- Support transactions
In addition, every messaging service packages these capabilities slightly differently.
1.1.2 How does the JMS API fit in?
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. As its secondary goal, it strives to maximize the portability of messaging applications. Specific goals of the JMS API specification are to:
- Provide a single, unified message API
- 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
The JMS API is divided into two nearly identical pieces. One implements the point- to-point model of messaging, and the other implements the publish/subscribe model of messaging. Each of these models is called a domain. The APIs are almost identical between these domains. This greatly improves the feeling of cohesiveness throughout the API.
The point-to-point and publish/subscribe models were selected because they represent the two largest paradigms behind existing messaging services. While sharing many characteristics, they differ in enough ways that they can be thought of as two separate services. They’re not necessarily incompatible - both can be used in an application. However, most applications tend to use one or the other. The separation of the API into two domains relieves vendors that support only one messaging model from providing facilities their product doesn’t natively support.
1.1.3 The advantages of messaging
Messaging provides three clear advantages when used in an enterprise application.
First, it decouples resources. Messaging allows business components to be combined into a reliable, flexible system with extremely loose coupling between components. This characteristic is desirable for two reasons: it makes the application more modular (and therefore more open to reuse) and it makes the application more reliable (a failure in one part of the application is less likely to affect an unrelated part of the application).
Second, messaging provides scalability. An application built around a messaging architecture scales well as both clients and servers are added to the system. It will also scale well as the volume of messages increases.
Third, messaging masks both heterogeneity and change. Remember that the common element in a messaging application is the message. As long as components can read and understand the message, the platform on which they reside and the languages in which they are written is unimportant, (based on ’Messaging helps move Java into the enterprise’ ,[!]).
1.2 Different types of message architectures
The design of the messaging network has important implications for the efficiency of the messaging delivery. Efficiency can be thought of both in terms of the speed and certainty with which messages are delivered, as well as programming effort to create and maintain and extend the system. Two common data distribution architectures are the fully connected network and the virtual fully-connected network. Although they are similarly named, there are differences.
1.2.1 Fully Connected Network
In a fully connected network, all processes are directly connected to all other processes. Figure 1.1 shows an example of such a system. Any process in this system can read or write information to or from any other process. In most implementations of such a network, each process would have an open file descriptor for every other process and would have to keep track of its connections with those processes. This results in significant overhead from both a system and programming perspective.
illustration not visible in this excerpt
Figure 1.1: Fully connected Network
1.2.2 Virtual Fully Connected Network
The Java Message Queue product implements a virtual fully connected network, as shown in Figure 1.2. The arrangement removes the burden of managing connections from the user program by making a separate process, called the router, responsible for maintaining all necessary connections. The user program has only a single connection with its local Java Message Queue router. This simplification not only reduces the complexity of the user code, but also improves performance by optimizing the data distribution. The router (or routers) handle all intraprocess (within router) and interprocess communications automatically.
illustration not visible in this excerpt
Figure 1.2: Virtual Fully Connected Network
This supports the advantages mentioned for messaging above:
- The application scales well. All that is required to increase server capacity is to add servers to the pool. The application itself does not have to be re-architected. Likewise, when components fail the application degrades gracefully.
- Asynchronous communication is possible. Components can perform other tasks while not busy handling requests. They can either poll the message server when ready or receive notification via a callback when a message is waiting. It is unnecessary to wait in a loop.
- The application is modular. 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.
- The application is flexible. Because the application API is defined by the format of the messages exchanged, components of the system can run on almost any platform and can be written in almost any programming language. They can also be replaced with minimal system impact.
A big disadvantage of the introduction of a messaging component admits a potential bottleneck and a single-point-of-failure into the system. Both of these issues can be address by replicating the messaging server and its contents (based on JMQ quickstart.pdf, ).
1.3 Existing JMS provider
Since the introduction of JMS in 1998 minor changes of JMS API have been done by sun. The actual version is 1.0.2 and was released at the 9th November 1999. More and more companies1 provide implementations for this API because the need of a fast, reliable and easy to use message system is like never before. Therefore implementations of other providers where tested and evaluated. The main highlights of some of the provider are listed below. To get more detailed information please visit the web pages listed in appendix I, JMS provider. All presented provider have demo/full versions, which can be found on the CD of the thesis.
1.3.1 JMQ - Java Messaging Queue
Java Message Queue software implements a hub/spoke architecture, operating as a virtual, fully connected system, minimize scalability of routers and connectors without sacrificing performance. One of the key determinants of performance and scalability in Java technology-based distributed applications is the efficiency of the mechanism used to route information between the cooperating components of the system. Java Message Queue software’s property-based intelligent routing agent architecture is natively multi-point, providing a robust infrastructure for constructing scalable applications and ensuring that messages are routed reliably and efficiently throughout networked environments.
Java Message Queue software provides a number of utilities that simplify the critical tasks of testing, debugging, tuning, and monitoring distributed applications. These tools enable users to manage distributed applications almost as if they were a single application running on a single processor.
JMQ is written in C++ and only available for Windows and Solaris right now. Further releases will support different platforms as well.
The SonicMQ product is a 100% Pure Java implementation, and with its full compliance with JavaSoft’s Java Message Service, version 1.0.1 specification, developers can easily and efficiently implement platform independent and J2EE-compliant messaging systems that fit into their existing infrastructure.
Multiple servers can be clustered (connected) together, allowing clients connected to one server to exchange information with clients connected to another server, without having to connect explicitly to each server. This allows the workload to be shared among all the servers, thereby avoiding overburdening of any one process and improving performance in a multi-user environment.
By providing support for identification and authentication, authorization and access control, digital certificates and 40- and 128-bit encryption, developers can build information systems that enforce their security policies easily and effectively. SonicMQ extends the basic JMS message types to include an XML message type. (XML is rapidly becoming the standard for exchanging information). Given that XML is a self-describing format, developers are offered greater flexibility in address messaging over pure JMS. Message Delivery Client applications can specify a particular quality of service (QoS) level for their messages.
In addition to the embedded database provided with the product, SonicMQ allows external databases to be used for persistent message storage. In this way, developers can leverage investments already made in database and tools technologies. The ability to monitor, administer and maintain brokers on local and remote systems is provided with through both a character and graphical tool set. Remote administration capability allows message systems to be monitored from a central location. SonicMQ provides the ability to define a number of topics in a hierarchy, so that topics themselves could contain subtopics. This concept can be mapped to the sales structure of a large organization. Sales (itself a topic), could be further divided into Western, Eastern and Central subtopics. These subtopics can be further broken down into individual cities. In this way, a client can intelligently subscribe to multiple related topics to provide the level of information most relevant to it.
FioranoMQ supports the complete JMS 1.02 API, including all documented PTP (point to point) and Publish/Subscribe functionality, in addition to supporting comprehensive security, administration and scalability features.
Using the FioranoMQ XML Interoperability Toolkit, a JMS message can be transformed into an XML format, allowing JMS applications to easily communicate with any external system. Users can also send an XML document as a JMS message. Developers can now build reliable applications in confidence using the XML data format exchange standard. FioranoMQ’s standards-based location-independent communication APIs can be used within browser-hosted applets, and across client-side corporate firewalls via HTTP Tunneling. FioranoMQ’s HTTP tunneling works with HTTP 1.1 compliant browsers only.
Comprehensive support for security is included in FioranoMQ. Besides providing support for encryption (40 and 128-bit), FioranoMQ incorporates Destination-based security - the administrator can use an available external administration tool to set access control lists (ACLs) for Topics and Queues; ACLs allow the administrator to control who can publish, subscribe or request guaranteed delivery on a given Destination. The security implementation is completely standards-based and implements the java.security API. In addition to providing support for encryption (40 and 128-bit), FioranoMQ 4.0 implements highly configurable Software Firewalls that allow administrators to selectively block incoming and outgoing information to and from any given server. The Fiorano Administrator now enables system administrators to set Access Control Lists (ACLs) at the Topic, User and Server level!
FioranoMQ incorporates a comprehensive administration API, which allows administered objects to be created and monitored externally. The FioranoMQ administrator can create, delete, modify and set properties for various administered objects through an available Administration Tool (which ships with the base release of the platform).
C++ programmers can access JMS publish/subscribe and point-to-point Messaging facilities using a C++ API derived from the based Java API. FioranoMQ thus allows C++ and Java programs to share data seamlessly. The FioranoMQ C++ runtime library can be used to build COM interfaces (ActiveX controls) to allow Visual Basic and Microsoft Excel applications to access JMS Services.
FioranoMQ implements server-to-server communication, allowing you to deploy highly fault tolerant distributed solutions. This feature allows multiple servers to be connected together, allowing clients connected to one server to exchange information (using normal JMS publish/subscribe APIs) with clients connected to another server, without each client having to connect explicitly to each server. Network failures do not affect local publish or subscribe operations, and the FioranoMQ server automatically buffers data transmitted when the network is down. When connections are later re-established, all pending data is sent to the proper recipient automatically, without any intervention from the user. Multiple servers can be clustered together while accessing the same offline database. Servers can be added to a single cluster to support increasing numbers of connections. If any of the servers goes down, client applications will automatically reconnect to one of the available servers, without any loss of persistent information.
SoftWired’s iBus is implemented entirely in the Java language. It runs on any hardware and operating system that offers a Java execution environment, such as Linux, Windows 9x, NT and 2000, Sun Solaris or other Unix dérivâtes.
The iBus product family is highly modular and consists of two core products. The core products are the lightweight, fully distributed, and fault-tolerant iBus//MessageBus, and the network-centric iBus//MessageServer product. All core products feature the standard Java Message Service (JMS) API, as well as an ANSI-C implementation of JMS for easy integration with non-Java applications. For wireless devices such as PDAs and cellular phones, an embeddable version of iBus is available: iBus//Mobile.
The iBus//MessageBus is the only fully distributed serverless JMS product available on the market. It is uniquely designed for local applications requiring a zero down time, zero administration operation with the highest possible publish/subscribe message delivery rate and group coordination features
Bus//MessageServer differs from competing products in that it can be configured to use any transport protocol on any transportation media. iBus//MessageServer supports TCP/IP, HTTP and SSL. The SSL tunneling feature operates not only through firewalls, but also via HTTP proxy servers.
You can implement your own protocols (e.g., for wireless communication) and "plug" them into iBus//MessageServer easily.
iBus//MessageServer transparently translates between protocols: A producer submits messages by TCP/IP, for example. The message server forwards these messages by HTTP to web clients, by WAP or SMS to handheld devices, and so forth.
1.3.5 Free implementations of JMS ObjectEvents
ObjectEvents is distributed as open source software as part of the Enhydra J2EE application server. It is entirely written in Java, but non-Java clients can access the middleware since the protocol is open and based on TCP/IP and XML. The whole project is still in development stage and could not be used for this master thesis. The first beta release of the source code was in August 2000. ObjectEvents supports the main features of JMS which are required. But is does not implement features like Load Balancing, Transactions, Fault Tolerance, Delivery Notification, Security and Message Repository. Depending on the demand of the customers these features will be added in the future. The source code is now available at the Enhydra web page .
The Swift message queue is an implementation of the JMS 1.0.2 API, which is free for private and commercial use, for deployment and bundling. All the JMS required features are supported.
Multiple routers with any topology and body compression are only some of the main features of SwiftMQ. Even it is free, it is a stable and very fast JMS solution. A powerful graphical administration and monitoring tool is also part as a text-based administration and monitoring tool with scripting abilities.
Automatic reconnection and security features are implemented as well. Persistent messages are stored on the local file system. The advantage and disadvantages of this solution is explained later in this thesis.
Swift is a small German company, which tries to distribute their middleware solution for free because they do not have the budget to run a big marketing campaign. They want to offer services like training for their product to make the money. SwiftMQ will not be open source sometimes because Swift wants to have control over the design, development and future.
Right now it seems that everybody claims to have the best JMS implementation on the market. Each of them have test results where they are much better than anybody else on the market. Suns JMQ is the most popular distribution right now. But regarding the features other providers are offering it should be only a matter of time until these products will catch up. A lot of the shown features like XML support are not something special because they are covered by JMS itself already.
SonicMQ and FioranoMQ seem to be the most complete and most powerful JMS implementations which where tested. They are both 100% pure-Java and come with all features which can be expected from a messaging system. iBus differs from the common JMS products because of its ability to work serverless and the open protocol infrastructure. It has the most flexibility regarding future trends like mobile communication and is also the only provider right now that supports a wireless communication protocol.
The ObjectEvents project does not have any special features but it is only in an early beta stage right now and the final release seems to be a stable and powerful implementation of JMS.
However, SwiftMQ is the best choice of the shown provider: It has everything that is needed, is stable, fast and free! All the other products range between $1000 - $3000 a license. Depending on the environment this may be a reasonable amount but most of the time the special features of the expensive solutions are not used at all. And JMS is an open standard. If the client application is only using plain JMS, the provider can be switched without any problems at all.
Chapter 2 Java Messaging Service API
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. 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, client applications are not only portable across machine architectures and operating systems, they are 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 and provide most of the functionality of common messaging systems.
Messaging products can be broadly classified as either point-to-point or publish- subscribe systems. 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. Publish and subscribe (Pub/Sub) clients address messages to some node in a content hierarchy. Publishers and subscribers are generally anonymous and may dynamically publish or subscribe to the cowayntent hierarchy. The system takes care of distributing the messages arriving from a node’s multiple publishers to its multiple subscribers. JMS provides client interfaces tailored for each domain.
The following chapter is an abstract of the Java Message Service Documentation .
2.1.1 Is This a Mail API?
The term messaging is quite broadly defined in computing. It is used for describing various operating system concepts; it is used to describe e-mail and fax systems; and here, it is used to describe asynchronous communication between enterprise applications.
Messages, as described here, are asynchronous requests, reports or events that are consumed by enterprise applications, not humans. They contain vital information needed to coordinate these systems. They contain precisely formatted data that describe specific business actions. Through the exchange of these messages each application tracks the progress of the enterprise.
2.1.2 JMS Objectives
If JMS provided a union of all the existing features of messaging systems it would be much too complicated for its intended users. On the other hand, JMS is more than an intersection of the messaging features common to all products. It is crucial that JMS include the functionality needed to implement sophisticated enterprise applications. JMS defines a common set of enterprise messaging concepts and facilities. It attempts to minimize the set of concepts a Java language programmer must learn to use enterprisemessaging products, while it strives to maximize the portability of messaging applications.
2.2 What JMS does not include
JMS does not address the following functionality:
- Load Balancing/Fault Tolerance - Many products provide support for multiple, cooperating clients implementing a critical service. The JMS API does not specify how such clients cooperate to appear to be a single, unified service.
- Error/Advisory Notification - Most messaging products define system messages that provide asynchronous notification of problems or system events to clients. JMS does not attempt to standardize these messages. By following the guidelines defined by JMS, clients can avoid using these messages and thus prevent the portability problems their use introduces.
- Administration - JMS does not define an API for administering messaging products.
- Security - JMS does not specify an API for controlling the privacy and integrity of messages. It also does not specify how digital signatures or keys are distributed to clients. Security is considered to be a JMS provider-specific feature that is configured by an administrator rather than controlled via the JMS API by clients.
- Wire Protocol - JMS does not define a wire protocol for messaging.
- Message Type Repository - JMS does not define a repository for storing message type definitions and it does not define a language for creating message type definitions.
2.3 JMS details
This part will give a brief overview about the JMS API and will point out the key features.
A JMS application is composed of the following parts:
- JMS Clients - These are the Java language programs that send and receive messages.
- Non-JMS Clients - These are clients that use a message systems native client API instead of JMS. If the application predated the availability of JMS it is likely that it will include both JMS and non-JMS clients.
- Messages - Each application defines a set of messages that are used to communicate information between its clients.
- JMS Provider - This is a messaging system that implements JMS in addition to the other administrative and control functionality required of a full featured messaging product.
- Administered Objects - Administered objects are preconfigured JMS objects created by an administrator for the use of clients.
It is expected that each JMS provider will differ significantly in their underlying messaging technology. It is also expected there will be major differences in how a provider’s system is installed and administered. If JMS clients are to be portable, they must be isolated from these proprietary aspects of a provider. This is done by defining JMS administered objects that are created and customized by a provider’s administrator and later used by clients. The client uses them through JMS interfaces that are portable. The administrator creates them using provider-specific facilities.
There are two types of JMS administered objects:
- ConneciionFaciory - This is the object a client uses to create a connection with a provider.
- Destination - This is the object a client uses to specify the destination of messages it is sending and the source of messages it receives.
Administered objects are placed in a JNDI name space by an administrator. A JMS client typically notes in its documentation the JMS administered objects it requires and how the JNDI names of these objects should be provided to it.
A JMS application either uses the point-to-point (PTP) or publish-and-subscribe (Pub/Sub) style of messaging. Nothing prevents these styles from being combined in a single application; however, JMS focuses on applications that use one or the other. JMS defines these two styles because they represent the two dominant approaches to messaging currently in use. Since many messaging systems only support one of these styles, JMS provides a separate domain for each and defines compliance for each domain.
2.3.2 JMS Interfaces
JMS is based on a set of common messaging concepts. The following provides a brief definition of these JMS concepts.
- ConneciionFaciory - an administered object used by a client to create a Connection
- Connection - an active connection to a JMS provider
- Destination - encapsulates the identity of a message destination
- Session - a single threaded context for sending and receiving messages
- MessageProducer - an object created by a Session that is used for sending messages to a destination
- Message Consumer - an object created by a Session that is used for receiving messages sent to a destination
The term consume is used in this document to mean the receipt of a message by a JMS client, i.e. a JMS provider has received a message and has given it to its client. Since JMS supports both synchronous and asynchronous receipt of messages, the term consume is used when there is no need to make a distinction between them. The term produce is used as the most general term for sending a message. It means giving a message to a JMS provider for delivery to a destination.
Each JMS messaging domain - PTP and Pub/Sub - define their customized set of interfaces for these concepts. Table 2.2 shows the relation between the different messaging modes.
illustration not visible in this excerpt
Table 2.2: Relationship of PTP and Pub/Sub interfaces
illustration not visible in this excerpt
illustration not visible in this excerpt
Figure 2.1: Relationship of PTP and Pub/Sub interfaces classdiagram
JMS could have required that all its objects support concurrent use. Since support for concurrent access typically adds some overhead and complexity, the JMS design restricts its requirement for concurrent access to those objects that would naturally be shared by a multi-threaded client. The remainder are designed to be accessed by one logical thread of control at a time. Table 2.3 shows which components support concurrent use.
illustration not visible in this excerpt
Table 2.3: JMS objects that support concurrent use
JMS defines some specific rules that restrict the concurrent use of Sessions. Since they require more knowledge of JMS specifics than we have presented at this point, they will be described later. Here we will describe the rationale for imposing them. There are two reasons for restricting concurrent access to sessions. First, sessions are the JMS entity that supports transactions. It is very difficult to implement transactions that are multi- threaded. Second, sessions support asynchronous message consumption. It is important that JMS does not require that client code used for asynchronous message consumption has to be capable of handling multiple, concurrent messages. In addition, if a Session has been set up with multiple, asynchronous consumers, it is important that the client is not forced to handle the case where these separate consumers are concurrently executing. These restrictions make JMS easier to use for typical clients. More sophisticated clients can get the concurrency they desire by using multiple sessions.
JMS provides the JMSReplyTo message header field for specifying the Destination where a reply to a message should be sent. The JMSCorrelationID header field of the reply can be used to reference the original request. See section 2.4.2, Message Header Fields for more information. In addition, JMS provides a facility for creating temporary queues and topics that can be used as a unique destination for replies.
There are many styles of request/reply supported by enterprise messaging products. Rather than architect a specific JMS request/reply abstraction, JMS provides the basic facilities on which many variations can be built.
For convenience, JMS defines request/reply helper classes (classes written using JMS) for both the PTP and Pub/Sub domains that implement a basic form of request/reply. JMS providers and clients may provide more specialized implementations.
2.4 JMS message model
Enterprise messaging products treat messages as lightweight entities that consist of a header and a body. The header contains fields used for message routing and identification; the body contains the application data being sent. Within this general form, the definition of a message varies significantly across products. There are major differences in the content and semantics of headers. Some products use a self-describing, canonical encoding of message data; others treat data as completely opaque. Some products provide a repository for storing message descriptions that can be used to identify and interpret message content; others do not. It would be quite difficult for JMS to capture the breadth of this, sometimes conflicting, union of message models.
The JMS message model has the following goals:
- Provide a single, unified message API
- Provide an API suitable for creating messages that match the format used by existing, non-JMS applications
- Support the development of heterogeneous applications that span operating systems, machine architectures, and computer languages
- Support messages containing Java objects
- Support messages containing Extensible Markup Language pages (see http://www.w3.org/XML).
2.4.1 JMS Messages
JMS messages are composed of the following parts (see figure 2.2):
- Header - All messages support the same set of header fields. Header fields contain values used by both clients and providers to identify and route messages.
- Properties - In addition to the standard header fields, messages provide a built-in facility for adding optional header fields to a message.
- Application-specific properties - In effect, this provides a mechanism for adding application specific header fields to a message.
- Standard properties - JMS defines some standard properties that are, in effect, optional header fields.
- Provider-specific properties - Integrating a JMS client with a JMS provider native client may require the use of provider-specific properties. JMS defines a naming convention for these.
- Body - JMS defines several types of message body, which cover the majority of messaging styles currently in use.
illustration not visible in this excerpt
Figure 2.2: JMS Message
2.4.2 Message Header Fields
The following subsections describe each JMS message header field. A message’s complete header is transmitted to all JMS clients that receive the message. JMS does not define the header fields transmitted to non-JMS clients.
JMSDestination The JMSDestination header field contains the destination to which the message is being sent. When a message is sent this value is ignored. When a message is received, its destination value must be equivalent to the value assigned when it was sent.
JMSDeliveryMode The JMSDeliveryMode header field contains the delivery mode specified when the message was sent. When a message is sent this value is ignored. After completion of the send it holds the delivery mode specified by the sending method.
JMSMessagelD The JMSMessagelD header field contains a value that uniquely identifies each message sent by a provider. When a message is sent, JMSMessagelD is ignored. When the send method returns it contains a provider-assigned value. A JMSMessagelD is a String value, which should function as a unique key for identifying messages in a historical repository. The exact scope of uniqueness is provider defined. All JMSMessagelD values must start with the prefix "ID:".
JMSTimestamp The JMSTimestamp header field contains the time a message was handed over to a provider to be sent. It is not the time the message was actually transmitted because the actual send may occur later due to transactions or other client side queueing of messages. It is in the format of a normal Java millis time value.
JMSCorrelationID A client can use the JMSCorrelationID header field to link one message with another. A typically use is to link a response message with its request message. JMSCorrelationID can hold a provider-specific message, an application-specific Siring or a provider-native bytefj value.
Since each message, which a JMS provider sends, is assigned a message ID value, it is convenient to link messages via message ID. All message ID values must start with the ID: prefix.
JMSReplyTo The JMSReplyTo header field contains a Destination supplied by a client when a message is sent. It is the destination where a reply to the message should be sent. Messages sent with a null JMSReplyTo value may be a notification of some event or they may just be some data the sender thinks is of interest. Messages sent with a JMSReplyTo value are typically expecting a response. A response may be optional, it is up to the client to decide.
JMSRedelivered If a client receives a message with the JMSRedelivered indicator set, it is likely, but not guaranteed, that this message was delivered to the client earlier but the client did not acknowledge its receipt at that earlier time. This header field has no meaning on send and is left unassigned by the sending method.
JMS Type The JMSType header field contains a message type identifier supplied by a client when a message is sent. The type header field may reference a message’s definition in the provider’s repository. JMS does not define a standard message definition repository nor does it define a naming policy for the definitions it contains.
JMSExpiration When a message is sent, its expiration time is calculated as the sum of the time-to-live value specified on the send method and the current GMT. On return from the send method, the message’s JMSExpiration header field contains this value. When a message is received its JMSExpiration header field contains this same value. If the time-to-live is specified as zero, expiration is set to zero, which indicates the message does not expire. When GMT is later than a message’s expiration time, the message should be destroyed.
JMSPriority The JMSPrioriiy header field contains the message’s priority. When a message is sent this value is ignored. After completion of the send it holds the value specified by the method sending the message. JMS defines a ten level priority value with 0 as the lowest priority and 9 as the highest. In addition, clients should consider priorities 0-4 as gradations of normal priority and priorities 5-9 as gradations of expedited priority.
2.4.3 Message Properties
In addition to the header fields defined here, messages contains a built-in facility for supporting property values. In effect, this provides a mechanism for adding optional header fields to a message. Properties can be be boolean, byte, short, int, long, float, double, and String values. Property values are set prior to sending a message and can not be modified by the receiver. Iteration and storing of objects are also supported.
JMS reserves the JMSX property name prefix for JMS defined properties. New JMS defined properties may be added in later versions of JMS. Unless noted otherwise, support for these properties is optional. The JMS <vendor name> property name prefix should be used for provider-specific properties. Each provider defines their own value of <vendorname>. This is the mechanism a JMS provider uses to make its special per message services available to a JMS client.
2.4.4 Message Selection
Many messaging applications need to filter and categorize the messages they produce. In the case where a message is sent to a single receiver, this can be done with reasonable efficiency by putting the criteria in the message and having the receiving client discard the ones it is not interested in.
When a message is broadcast to many clients, it becomes useful to place the criteria into the message header so that it is visible to the JMS provider. This allows the provider to handle much of the filtering and routing work that would otherwise need to be done by the application. JMS provides a facility that allows clients to delegate message selection to their JMS provider. This simplifies the work of the client and allows JMS providers to eliminate the time and bandwidth they would otherwise waste sending messages to clients that do not need them.
Clients attach application-specific selection criteria to messages using message properties and specify message selection criteria using JMS message selector expressions.
2.4.5 Message Body
JMS provides five forms of message body. Each form is defined by a message interface:
- TextMessage - a message whose body contains a java.lang.String. The inclusion of this message type is based on our presumption that String messages will be used extensively. One reason for this is that XML will likely become a popular mechanism for representing the content of JMS messages.
- ObjectMessage - a message that contains a Serializable Java object. If a collection of Java objects is needed, one of the collection classes provided in JDK 1.2 can be used.
- StreamMessage - a message whose body contains a stream of Java primitive values. It is filled and read sequentially.
- MapMessage - a message whose body contains a set of name-value pairs where names are Strings and values are Java primitive types. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined.
- BytesMessage - a message that contains a stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. In many cases, it will be possible to use one of the other, self-defining, message types instead.
When a message is received its body is read only. It is also possible to delete the body of a message separately. Both StreamMessage and MapMessage support conversion of their data values. A conversion table defines, what has to be supported and what has to throw an exception (See JMS API  for more details).
2.5 JMS common facilities
JMS defines basic facilities that are shared by both the PTP and Pub/Sub domains. The client does not use these components directly. Every class acts as base for the PTP and the Pub/Sub model.
2.5.1 Administrated objects
JMS administrated objects are objects containing JMS configuration information that are created by a JMS administrator and later used by JMS clients. They make it practical to administer JMS applications in the enterprise. Although the interfaces for administered objects do not explicitly depend on JNDI, JMS establishes the convention that JMS clients find them by looking them up in a name space using JNDI. An administrator can place an administered object anywhere in a name space. JMS does not define a naming policy. This strategy of partitioning JMS and administration provides several benefits:
- It hides provider-specific configuration details from JMS clients.
- It abstracts JMS administrative information into Java objects that are easily organized and administered from a common management console.
- Since there will be JNDI providers for all popular naming services, this means JMS providers can deliver one implementation of administered objects that will run everywhere.
An administrated object should not hold on to any remote resources and its lookup should not use remote resources other than those used by JNDI itself. Clients should think of administered objects as local Java objects. Looking them up should not have any hidden side effects or use surprising amounts of local resources. JMS defines two administered objects, Destination and ConneciionFaciory. It is expected that JMS providers will provide the tools an administrator needs to create and configure administered objects in a JNDI name space. JMS provider implementations of administered objects should be both javax.naming.Referenceable and java.io.Serializable so that they can be stored in all JNDI naming contexts. In addition, it is recommended that these implementations follow the JavaBeans design patterns.
Destination JMS does not define a standard address syntax. Although this was considered, it was decided that the differences in address semantics between existing enterprise messaging products was too wide to bridge with a single syntax. Instead, JMS defines the Destination object, which encapsulates provider-specific addresses. Since Destination is an administered object it may also contain provider-specific configuration information in addition to its address.
ConnectionFactory A ConnectionFactory encapsulates a set of connection configuration parameters that has been defined by an administrator. A client uses it to create a Connection with a JMS provider.
A JMS Connection is a client’s active connection to its JMS provider. It will typically allocate provider resources outside the Java virtual machine. Connections support concurrent use. A Connection serves several purposes:
- It encapsulates an open connection with a JMS provider. It typically represents an open TCP/IP socket between a client and a provider’s service daemon.
- Its creation is where client authenticating takes place.
- It can specify a unique client identifier.
- It creates Sessions.
- It provides ConnectionMetaData.
- It supports an optional ExceptionListener.
Due to the authentication and communication setup done when a connection is created, a Connection is a relatively heavy-weight JMS object. Most clients will do all their messaging with a single connection. Other more advanced applications may use several connections.
When creating a connection, a client may specify his credentials as name/password. It is not defined by JMS right now how this should be handled. It is up to the provider to provide this. When a connection is created a client identifier has to be assigned. This could be done by the system itself or has to be provided by the client application. If a client explicitly does the set it must do this immediately after creating the connection and before any other action on the connection is taken. After this point, setting the client identifier is a programming error that should throw an IllegalStateException.
Usage of connections
A JMS client typically creates a Connection; one or more Sessions; and a number of MessageProducers and Message Consumers. A connection is created in stopped mode. That means that no messages are being delivered to it. It is typical to leave the connection in stopped mode until setup is complete. At that point the connection’s start() method is called and messages begin arriving at the connection’s consumers. This setup convention minimizes any client confusion that may result from asynchronous message delivery while the client is still in the process of setting itself up. A connection can immediately be started and the setup can be done afterwards. Clients that do this must be prepared to handle asynchronous message delivery while they are still in the process of setting up.
A connection’s delivery of incoming messages can be temporarily stopped using its stop() method. It can be restarted using its start() method. When stopped, delivery to all the connection’s MessageConsumers is inhibited: synchronous receive is blocked and messages are not delivered to message listeners. Stopping a connection has no affect on its ability to send messages. Stopping a stopped connection and starting a started connection is ignored.
Since a provider typically allocates significant resources outside the JVM on behalf of a connection, clients should close them when they are not needed. A close terminates all pending message receives on the connection’s session’s consumers. The receivers may return with a message or null depending on whether there was a message or not available at the time of the close.
Once a connection has been closed an attempt to use it or its sessions or their message consumers and producers must throw an IllegalStateException.
A JMS Session is a single threaded context for producing and consuming messages. Although it may allocate provider resources outside the Java virtual machine, it is considered a light-weight JMS object.
A Session serves several purposes:
- It is a factory for its MessageProducers and MessageConsumers.
- It is a factory for temporary destinations.
- It provides a way to create Destination objects for those clients that need to dynamically manipulate provider-specific destination names.
- It supplies provider-optimized message factories.
- It supports a single series of transactions that combine work spanning this session’s producers and consumers into atomic units.
- A Session defines a serial order for the messages it consumes and the messages it produces.
- A Session retains messages it consumes until they have been acknowledged.
- A Session serializes execution of message listeners registered with it.
The close() operation of a Session close terminates all message processing on the session. When session close is invoked it should not return until its message processing has been orderly shut down. This means that none of its message listeners are running and that if there is a pending receive it has returned with either null or a message. When a session is closed there is no need to close its constituent message producers and consumers. The session close is sufficient to signal the JMS provider that all resources for the session should be released. Once a session has been closed an attempt to use it or its message consumers and producers must throw an IllegalStateException.
A session can create and service multiple MessageProducers and MessageConsumers. Although a session may create multiple producers and consumers, they are restricted to serial use.
Most clients will use Destinations that are JMS administered objects that they have looked up via JNDI. This is the most portable approach. Some specialized clients may need to create Destinations by dynamically manufacturing one using a provider specific destination name. Sessions provide a JMS provider-specific method for doing this. Temporary destinations are also provided by sessions. One typical use for a Temporary- Destination is as the JMSReplyTo destination for service requests.
Sessions are designed for serial use by one thread at a time. The only exception to this occurs during the orderly shutdown of the session or its connection. A typical use is to have one thread set up a session by creating its producers and one or more asynchronous consumers. In this case, the message producers are exclusively for the use of the consumer’s message listeners. Since the session serializes execution of its consumer’s MessageListeners, they can safely share the resources of their session.
If a connection is left in stopped mode while its sessions are being set up, a client does not have to deal with messages arriving before the client is fully prepared to handle them. This is the preferred strategy because it eliminates the possibility of unanticipated conflicts between setup and message processing.
 See http://www.javasoft.com/products/jms/vendors.html for an actual vendor list. See appendix I for the vendor list from the 10th September 2000.
 There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.