The Java Message Service (JMS) is a Java API that allows applications to create, send, receive, and read messages. The JMS API defines a common set of interfaces and associated semantics that allow programs written in the Java to communicate with other messaging implementations.
Messaging is a method of communication between software components or applications. A messaging system is a peer-to-peer facility: A messaging client can send messages to, and receive messages from, any other client. Each client connects to a messaging agent that provides facilities for creating, sending, receiving, and reading messages.
JMS enables distributed communication:
- loosely coupled: The sender and the receiver do not have to be available at the same time in order to communicate. In fact, the sender does not need to know anything about the receiver, nor does the receiver need to know anything about the sender, except which message format and which destination to use. Differs from tightly coupled technologies, such as RMI, which require an application to know a remote application’s methods. Since the components do not depend on information about other component’s interfaces, components can be easily replaced.
- Asynchronous: A receiving client does not have to receive messages at the same time the sending client sends them. The sending client can send them and go on to other tasks. The receiving client can receive them much later.
- Reliable: A messaging provider that implements the JMS API can ensure that a message is delivered once and only once. Lower levels of reliability are available for applications that can afford to miss messages or to receive duplicate messages. Allow application to run whether or not all components are up and running simultaneously
Integration with the Java EE Platform
The JMS API was first introduced in the Java EE Platform to allow apps to access existing messaging-oriented middleware (MOM) systems. In the Java EE platform has the following features:
- Application clients, EJB and web components can send or synchronously receive a JMS message. Application clients can in addition set a message listener that allows JMS messages to be delivered to it asynchronously by being notified when a message is available.
- Message-driven beans, enable the asynchronous consumption of messages in the EJB container. An AS typically pools message-driven beans to implement concurrent processing of messages.
- Message send and receive operations can participate in JTA transactions, which allow JMS operations and database accesses to take place within a single transaction.
The JMS provider can be integrated with the AS using the JCA, accessing the JMS provider through a resource adapter. This capability allows vendors to create JMS providers that can be plugged in to multiple AS and allows to support multiple JMS providers.
A JMS application is composed of the following parts:
- A JMS provider is a messaging system that implements the JMS interfaces and provides administrative and control features. An implementation of the Java EE platform that supports the full profile includes a JMS provider.
- JMS clients are the programs or components, written in the Java, that produce and consume messages. Any Java EE application component or Java SE applications can act as a JMS client.
- Messages are the objects that communicate information between JMS clients.
- Administered objects are JMS objects configured for the use of clients. The two kinds of JMS administered objects are destinations and connection factories.
Administrative tools or annotations allow you to bind destinations and connection factories into a JNDI namespace. A JMS client can then use resource injection to access the administered objects in the namespace and then establish a logical connection to the same objects through the JMS provider.
The JMS specification defines compliance for the point-to-point or the publish/subscribe style of messaging. A JMS provider must implement both styles, and the JMS API provides interfaces that are specific to each.
The JMS API makes it unnecessary to use only one of the two styles. It allows you to use the same code to send and receive messages using either the PTP or the pub/sub style. The destinations you use remain specific to one style, and the behavior of the application will depend in part on whether you are using a queue or a topic.
Point-to-Point Messaging Style
A point-to-point (PTP) app is built on the concept of message queues, senders, and receivers. Each message is addressed to a specific queue and receiving clients extract messages from the queues established to hold their messages.
Has the following characteristics:
- Each message has only one consumer, delivered in the order sent and processed only once.
- Every message successfully processed is acknowledged by the consumer.
- The receiver can fetch the message whether or not it was running when the client sent the message.
- Queues knows who the consumer is and retain all messages sent to them until the messages are consumed or expire.
Publish/Subscribe Messaging Style
In a publish/subscribe (pub/sub) app, clients address messages to a topic. Publishers and subscribers can dynamically publish or subscribe to the topic. The system takes care of distributing the messages arriving from a topic’s multiple publishers to its multiple subscribers. Topics retain messages only as long as it takes to distribute them to subscribers.
With pub/sub messaging, it is important to distinguish between the consumer that subscribes to a topic (the subscriber) and the subscription that is created. The consumer is a JMS object within an application, while the subscription is an entity within the JMS provider. Normally, a topic can have many consumers, but a subscription has only one subscriber. It is possible, however, to create shared subscriptions.
Has the following characteristics:
- Each message can have multiple consumers, with no guarantee to be delivered in the order sent or processed only once.
- A message successfully processed is not acknowledged by the consumer/subscriber.
- The subscriber needs to the active when the messages are produced by the producer, unless the subscription was a durable subscription.
- The Topic, have multiple subscribers and there is a chance that the topic does not know all the subscribers. The destination is unknown.
There is no timing dependency between the production and the consumption of a message, however messages can be consumed in either of two ways:
- Synchronously: A consumer explicitly fetches the message from the destination by calling the receive method. The receive method can block until a message arrives or can time out if a message does not arrive within a specified time limit.
- Asynchronously: A client can register a message listener with a consumer. Whenever a message arrives at the destination, the JMS provider delivers the message which acts on the contents of the message.
JMS Administered Objects
Two parts of a JMS application, destinations and connection factories, are commonly maintained administratively rather than programmatically. JMS clients access administered objects through interfaces that are portable, so a client application can run with little or no change on more than one implementation of the JMS API. Ordinarily, an administrator configures administered objects in a JNDI namespace, and JMS clients then access them by using resource injection.
- A connection factory is the object a client uses to create a connection to a provider. Encapsulates a set of connection configuration parameters that has been defined by an administrator. Each connection factory is an instance of the
- A destination is the object a client uses to specify the target of messages it produces and the source of messages it consumes. In the PTP messaging style, destinations are called queues. In the pub/sub messaging style, destinations are called topics.
- A connection encapsulates a virtual connection with a JMS provider. For example, a connection could represent an open TCP/IP socket between a client and a provider service daemon. You use a connection to create one or more sessions.
- A session is a single-threaded context for producing and consuming messages. Sessions serialize the execution of message listeners and provides a transactional context with which to group a set of sends and receives into an atomic unit of work.
- A JMSContext object combines a connection and a session in a single object. That is, it provides both an active connection to a JMS provider and a single-threaded context for sending and receiving messages.
- JMS Message Producers is a message producer, an object that is created by a JMSContext or a session and used for sending messages to a destination.
- JMS Message Consumers is a message consumer, an object that is created by a JMSContext or a session and used for receiving messages sent to a destination.
A JMS message can have three parts: a header, properties, and a body. Only the header is required.
- Message Headers: A JMS message header contains a number of predefined fields that contain values used by both clients and providers to identify and route messages. Each header field has associated setter and getter methods, which are documented in the description of the Message interface. Some header fields are intended to be set by a client, but many are set automatically by the send method, which overrides any client-set values.
- Message Properties: You can create and set properties for messages if you need values in addition to those provided by the header fields. You can use properties to provide compatibility with other messaging systems, or you can use them to create message selectors. The JMS API provides some predefined property names that begin with JMSX. A JMS provider is required to implement only one of these, JMSXDeliveryCount (which specifies the number of times a message has been delivered); the rest are optional. The use of these predefined properties or of user-defined properties in applications is optional.
- Message Bodies: The JMS API defines six different types of messages. Each message type corresponds to a different message body. These message types allow you to send and receive data in many different forms.
Learn more in the Java EE documentation