Messaging middleware allows components and applications to communicate by producing and consuming messages. The JMS API defines two patterns or messaging domains that govern this communication: point-to-point messaging and publish/subscribe messaging. The JMS API is organized to support these patterns. The basic JMS objects: connections, sessions, producers, consumers, destinations, and messages are used to specify messaging behavior in both domains.
In the point-to-point domain, message producers are called senders and consumers are called receivers. They exchange messages by means of a destination called a queue: senders produce messages to a queue; receivers consume messages from a queue.
Figure 2–1 shows the simplest messaging operation in the point-to-point domain. MyQueueSender sends Msg1 to the queue destination MyQueue1. Then, MyQueueReceiver obtains the message from MyQueue1.
Figure 2–2 shows a more complex picture of point-to-point messaging to illustrate the possibilities in this domain. Two senders, MyQSender1 and MyQSender2, use the same connection to send messages to MyQueue1. MyQSender3 uses an additional connection to send messages to MyQueue1. On the receiving side, MyQReceiver1 consumes messages from MyQueue1, and MyQReceiver2 and MyQReceiver3, share a connection in order to consume messages from MyQueue1.
This more complex picture illustrates a number of additional points about point-to-point messaging.
More than one producer can send messages to a queue. Producers can share a connection or use different connections, but they can all access the same queue.
More than one receiver can consume messages from a queue, but each message can only be consumed by one receiver. Thus Msg1, Msg2, and Msg3 are consumed by different receivers. (This is a Message Queue extension.)
Receivers can share a connection or use different connections, but they can all access the same queue. (This is a Message Queue extension.)
Senders and receivers have no timing dependencies: the receiver can fetch a message whether or not it was running when the client sent the message.
Senders and receivers can be added and deleted dynamically at runtime, thus allowing the messaging system to expand or contract as needed.
Messages are placed on the queue in the order sent, but the order in which they are consumed depends on factors such as message expiration date, message priority, and whether a selector is used in consuming messages.
The point-to-point model offers a number of advantages:
The fact that multiple receivers can consume messages from the same queue allows you to load-balance message consumption if the order in which messages are received is not important. (This is a Message Queue extension.)
Messages destined for a queue are always retained, even if there are no receivers.
Java clients can use a queue browser object to inspect the contents of a queue. They can then consume messages based on the information gained from this inspection. That is, although the consumption model is normally FIFO (first in, first out), consumers can consume messages that are not at the head of the queue if they know what messages they want by using message selectors. Administrative clients can also use the queue browser to monitor the contents of a queue.
In the publish/subscribe domain, message producers are called publishers and message consumers are called subscribers. They exchange messages by means of a destination called a topic: publishers produce messages to a topic; subscribers subscribe to a topic and consume messages from a topic.
Figure 2–3 shows a simple messaging operation in the publish/subscribe domain. MyTopicPublisher publishes Msg1 to the destination MyTopic. Then, MyTopicSubscriber1 and MyTopicSubscriber2 each receive a copy of Msg1 from MyTopic.
While the publish/subscribe model does not require that there be more than one subscriber, two subscribers are shown in the figure to emphasize the fact that this domain allows you to broadcast messages. All subscribers to a topic get a copy of any message published to that topic.
Subscribers can be non-durable or durable. The broker retains messages for all active subscribers, but it only retains messages for inactive subscribers if these subscribers are durable.
Figure 2–4 shows a more complex picture of publish/subscribe messaging to illustrate the possibilities offered by this pattern. Several producers publish messages to the Topic1 destination. Several subscribers consume messages from the Topic1 destination. Unless, a subscriber is using a selector to filter messages, each subscriber gets all the messages published to the topic of choice. In Figure 2–4, MyTSubscriber2 has filtered out Msg2.
This more complex picture illustrates a number of additional points about publish/subscribe messaging.
More than one producer can publish messages to a topic. Producers can share a connection or use different connections, but they can all access the same topic.
More than one subscriber can consume messages from a topic. Subscribers retrieve all messages published to a topic unless they use selectors to filter out messages or the messages expire before they are consumed.
Subscribers can share a connection or use different connections, but they can all access the same topic.
Durable subscribers can be active or inactive. The broker retains messages for them while they are inactive.
Publishers and subscribers can be added and deleted dynamically at runtime, thus allowing the messaging system to expand or contract as needed.
Messages are published to a topic in the order sent, but the order in which they are consumed depends on factors such as message expiration date, message priority, and whether a selector is used in consuming messages.
Publishers and subscribers have a timing dependency: a topic subscriber can consume only messages published after it has created the subscription.
The main advantage of the publish/subscribe model is that it allows messages to be broadcast to subscribers.
The JMS API defines interfaces and classes that you can use to implement either of the point-to-point or the publish/subscribe domains. These are the domain-specific API’s shown in columns 2 and 3 of Table 2–1. The JMS API defines an additional unified domain, which allows you to program a generic messaging client. The behavior of such a client is determined by the type of the destination to which it produces messages and from which it consumes messages. If the destination is a queue, messaging will behave according to the point-to-point pattern; if the destination is a topic, messaging will behave according to the publish/subscribe pattern.
Table 2–1 JMS Programming Domains and Objects
Base Type(Unified Domain) |
Point-to-Point Domain |
Publish/Subscribe Domain |
---|---|---|
Destination (Queue or Topic) |
Queue |
Topic |
ConnectionFactory |
QueueConnectionFactory |
TopicConnectionFactory |
Connection |
QueueConnection |
TopicConnection |
Session |
QueueSession |
TopicSession |
MessageProducer |
QueueSender |
TopicPublisher |
MessageConsumer |
QueueReceiver |
TopicSubscriber |
The unified domain was introduced with JMS version 1.1. If you need to conform to the earlier 1.02b specification, you can use the domain-specific API. Using the domain-specific API also provides a clean programming interface that prevents certain types of programming errors: for example, creating a durable subscriber for a queue destination. However, the domain-specific APIs have the disadvantage that you cannot combine point-to-point and publish/subscribe operations in the same transaction or in the same session. If you need to do that, you should choose the unified domain API. See The Request-Reply Pattern for an example of combining the two domains.