Learn the architecture of the Java Message Service (JMS) in this guest post by Abdalla Mahmoud, the author of Developing Middleware in Java EE 8.
JMS is the Java standard API for implementing message-oriented middleware. Any typical Java EE application server (Glassfish, Wildfly, WebLogic, and so on) will have its own implementation for this API. In other words, you don’t care as a Java EE application developer about the actual implementation used within an application server, and you will be focusing more on API concepts.
In the coming section, you’ll be taken through the architecture and the constituent parts of a typical JMS application.
JMS is a platform-neutral Java API, which means that it can be used within the context of any Java SE application and is not limited to Java EE. In the following sections, you’ll see the different parts that make up a typical JMS application, but with a focus on JMS usage from the perspective of Java EE.
JMS provider is an implementation of the JMS API, always bundled with any Java EE application server. However, you can use an independent implementation within a Java SE application.
JMS clients are software components that communicate with each other. There are two types of JMS clients:
- Producers: Software components that send messages
- Consumers: Software components that receive messages and process them
In JMS, you can nearly write client-consuming messages inside any type of Java classes—POJOs, session beans, servlets, and so on. However, in the Java EE platform, message-driven beans are the standard way to implement JMS clients, as they integrate well with the application server and other services it provides.
Messages are the main concern of JMS; they are objects passed from a producer to one or more consumers. A message contains information that is used by the consumer to determine which action to perform and the required parameters to use. In JMS, there are different types of messages, as listed in the following table:
|TextMessage||A payload of a string value.|
|MapMessage||A payload of a Java map to a set of pairs; a string value is used as a key, and any other Java primitive value (including strings and byte arrays) can be used as a value for each key. Note that the order of keys is not guaranteed, like in any Java map.|
|BytesMessage||A payload of arbitrary bytes.|
|StreamMessage||A payload of Java primitive values, read and written sequentially.|
|ObjectMessage||A payload of Java Serializable objects.|
|Message||A message with headers and properties only, without a payload.|
JMS managed objects are objects configured to be used by JMS clients. There are two kinds of managed objects that you should use within any JMS application:
- Connection Factories: These are objects used by JMS clients to establish a connection with a JMS provider, fed with the required connection configuration prepared by the system administrator.
- Destinations: A destination is an object used by JMS client to specify the target component(s) that should be receiving this message. Two destination types are available in JMS:
- Queue (used in the point-to-point messaging style)
- Topic (used in the publish-subscribe messaging style)
These two messaging styles will be discussed in the next section.
In JMS, two messaging styles are available to choose from when deciding to use a message-oriented architecture. Each style can address a different business problem, while providing nearly the same messaging interface.
In point-to-point messaging (P2P for short), the message broker maintains a destination queue with an ID. When a producer sends a message targeting a specific queue by ID, the broker enqueues the message in this queue. When a consumer asks to receive and process a new message from this queue, the message broker will dequeue a single message in a first-in-first-out manner and deliver it to this producer.
Queues in messaging can provide scaling capabilities with low costs, as this model supports processing a large queue with messages using a limited number of concurrent consumers. A large number of messages can be waiting in a queue to be served once a single consumer is free to accept more messages.
In the publish-subscribe messaging style, the message broker maintains a destination topic with an ID. One or more interested consumers will subscribe to this topic. When a producer sends a message to this topic, all interested (subscribed) consumers will be notified with the new message.
Topics in messaging can provide multiple consumers for a single message; this allows distributing the message to different consumers concurrently, as each consumer is interested in performing a single kind of post-processing action, according to the message. JMS states that only messages sent after subscription to this topic will be delivered to the consumer, with no delivery of messages sent before this subscription or in the case of inactivity by the consumer. However, JMS can extend this concept using durable subscriptions, which also deliver messages sent during inactivity.
That’s it; you now know the basic architecture of JMS. If you wish to learn more about Java EE 8, you can explore Developing Middleware in Java EE 8. The book follows a hands-on approach to teach you how to design and implement professional enterprise middleware solutions using the latest features provided by the Java EE 8 platform.