@Resource(lookup = "java:comp/DefaultJMSConnectionFactory") private static ConnectionFactory connectionFactory;
The JMS API Programming Model
The basic building blocks of a JMS application are
Figure 48-5 shows how all these objects fit together in a JMS client application.
Figure 48-5 The JMS API Programming Model
JMS also provides queue browsers, objects that allow an application to browse messages on a queue.
This section describes all these objects briefly and provides sample commands and code snippets that show how to create and use the objects. The last subsection briefly describes JMS API exception handling.
Examples that show how to combine all these objects in applications appear in Chapter 49, "Java Message Service Examples," beginning with Writing Simple JMS Applications. For more detail, see the JMS API documentation, part of the Java EE API documentation.
JMS Administered Objects
Two parts of a JMS application, destinations and connection factories, are commonly maintained administratively rather than programmatically. The technology underlying these objects is likely to be very different from one implementation of the JMS API to another. Therefore, the management of these objects belongs with other administrative tasks that vary from provider to provider.
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.
With GlassFish Server, you can use the
NetBeans IDE provides a wizard that allows you to create JMS resources for GlassFish Server. See Creating JMS Administered Objects for details.
The Java EE platform specification allows a developer to create administered objects using annotations or deployment descriptor elements. Objects created in this way are specific to the application for which they are created. See Creating Resources for Java EE Applications for details. Definitions in a deployment descriptor override those specified by annotations.
JMS Connection Factories
A connection factory is the object a client uses to create a connection
to a provider. A connection factory encapsulates a set of connection
configuration parameters that has been defined by an administrator. Each
connection factory is an instance of the
At the beginning of a JMS client program, you usually inject a
connection factory resource into a
For example, the following code fragment looks up the default JMS
connection factory and assigns it to a
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 JMS application can use multiple queues or topics (or both). To learn how to create destination resources, see Creating JMS Administered Objects.
To create a destination using GlassFish Server, you create a JMS destination resource that specifies a JNDI name for the destination.
In the GlassFish Server implementation of JMS, each destination resource refers to a physical destination. You can create a physical destination explicitly, but if you do not, the Application Server creates it when it is needed and deletes it when you delete the destination resource.
In addition to injecting a connection factory resource into a client
program, you usually inject a destination resource. Unlike connection
factories, destinations are specific to either the PTP or pub/sub
messaging style. To create an application that allows you to use the
same code for both topics and queues, you assign the destination to a
The following code specifies two resources, a queue and a topic. The resource names are mapped to destination resources created in the JNDI namespace:
In a Java EE application, JMS administered objects are normally placed
With the common interfaces, you can mix or match connection factories
and destinations. That is, in addition to using the
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.
You normally create a connection by creating a
A session is a single-threaded context for producing and consuming messages.
You normally create a session (as well as a connection) by creating a
Sessions serialize the execution of message listeners; for details, see JMS Message Listeners.
A session provides a transactional context with which to group a set of sends and receives into an atomic unit of work. For details, see Using JMS Local Transactions.
You use the
You can create a
To create a
When called with no arguments from an application client or a Java SE
client, or from the Java EE web or EJB container when there is no active
JTA transaction in progress, the
From an application client or a Java SE client, you can also call the
The session uses local transactions; see Using JMS Local Transactions for details.
Alternatively, you can specify a non-default acknowledgment mode; see Controlling Message Acknowledgment for more information.
When you use a
If you create a
JMS Message Producers
A message producer is an object that is created by a
You can create the message in a variable before sending it, as shown
here, or you can create it within the
JMS Message Consumers
A message consumer is an object that is created by a
A message consumer allows a JMS client to register interest in a destination with a JMS provider. The JMS provider manages the delivery of messages from a destination to the registered consumers of the destination.
When you use a
You use the
If you specify no arguments or an argument of
For a simple client, this may not matter. But if it is possible that a
message might not be available, use a synchronous receive with a
timeout: Call the
To enable asynchronous message delivery from an application client or a Java SE client, you use a message listener, as described in the next section.
You can use the
JMS Message Listeners
A message listener is an object that acts as an asynchronous event
handler for messages. This object implements the
From an application client or a Java SE client, you register the message
listener with a specific message consumer by using the
When message delivery begins, the JMS provider automatically calls the
In the Java EE web or EJB container, you use message-driven beans for
asynchronous message delivery. A message-driven bean also implements the
For a simple example of the use of a message listener, see Using a Message Listener for Asynchronous Message Delivery. Chapter 49, "Java Message Service Examples," contains several more examples of message listeners and message-driven beans.
JMS Message Selectors
If your messaging application needs to filter the messages it receives, you can use a JMS message selector, which allows a message consumer for a destination to specify the messages that interest it. Message selectors assign the work of filtering messages to the JMS provider rather than to the application. For an example of an application that uses a message selector, see Sending Messages from a Session Bean to an MDB.
A message selector is a
Consuming Messages from Topics
The semantics of consuming messages from topics are more complex than the semantics of consuming messages from queues.
An application consumes messages from a topic by creating a subscription on that topic and creating a consumer on that subscription. Subscriptions may be durable or nondurable, and they may be shared or unshared.
A subscription may be thought of as an entity within the JMS provider itself, whereas a consumer is a JMS object within the application.
A subscription will receive a copy of every message that is sent to the topic after the subscription is created, unless a message selector is specified. If a message selector is specified, only those messages whose properties match the message selector will be added to the subscription.
Unshared subscriptions are restricted to a single consumer. In this case, all the messages in the subscription are delivered to that consumer. Shared subscriptions allow multiple consumers. In this case, each message in the subscription is delivered to only one consumer. JMS does not define how messages are distributed between multiple consumers on the same subscription.
Subscriptions may be durable or nondurable.
A nondurable subscription exists only as long as there is an active consumer on the subscription. This means that any messages sent to the topic will be added to the subscription only while a consumer exists and is not closed.
A nondurable subscription may be either unshared or shared.
At the cost of higher overhead, a subscription may be durable. A durable subscription is persisted and continues to accumulate messages until explicitly deleted, even if there are no consumer objects consuming messages from it. See Creating Durable Subscriptions for details.
Creating Durable Subscriptions
To ensure that a pub/sub application receives all sent messages, use durable subscriptions for the consumers on the topic.
Like a nondurable subscription, a durable subscription may be either unshared or shared.
A durable subscription that exists but that does not currently have a non-closed consumer object associated with it is described as being inactive.
You can use the
A consumer identifies the durable subscription from which it consumes messages by specifying a unique identity that is retained by the JMS provider. Subsequent consumer objects that have the same identity resume the subscription in the state in which it was left by the preceding consumer. If a durable subscription has no active consumer, the JMS provider retains the subscription’s messages until they are received by the subscription or until they expire.
You establish the unique identity of an unshared durable subscription by setting the following:
You can set the client ID administratively for a client-specific
connection factory using either the command line or the Administration
Console. (In an application client or a Java SE client, you can instead
After using this connection factory to create the
The subscription becomes active after you create the consumer. Later, you might close the consumer:
The JMS provider stores the messages sent to the topic, as it would
store messages sent to a queue. If the program or another application
To delete a durable subscription, first close the consumer, then call
Figure 48-6 and Figure 48-7 show the
difference between a nondurable and a durable subscription. With an
ordinary, nondurable subscription, the consumer and the subscription
begin and end at the same point and are, in effect, identical. When the
consumer is closed, the subscription also ends. Here,
Figure 48-6 Nondurable Subscriptions and Consumers
With a durable subscription, the consumer can be closed and re-created,
but the subscription continues to exist and to hold messages until the
application calls the
Figure 48-7 Consumers on a Durable Subscription
A shared durable subscription allows you to use multiple consumers to
receive messages from a durable subscription. If you use a shared
durable subscription, the connection factory you use does not need to
have a client identifier. To create a shared durable subscription, call
Creating Shared Subscriptions
A topic subscription created by the
It is, however, possible to create a nondurable shared subscription to a
topic by using the
With a shared subscription, messages will be distributed among multiple clients that use the same topic and subscription name. Each message sent to the topic will be added to every subscription (subject to any message selectors), but each message added to a subscription will be delivered to only one of the consumers on that subscription, so it will be received by only one of the clients. A shared subscription can be useful if you want to share the message load among several consumers on the subscription rather than having just one consumer on the subscription receive each message. This feature can improve the scalability of Java EE application client applications and Java SE applications. (Message-driven beans share the work of processing messages from a topic among multiple threads.)
See Using Shared Nondurable Subscriptions for a simple example of using shared nondurable consumers.
You can also create shared durable subscriptions by using the
The ultimate purpose of a JMS application is to produce and consume messages that can then be used by other software applications. JMS messages have a basic format that is simple but highly flexible, allowing you to create messages that match formats used by non-JMS applications on heterogeneous platforms.
A JMS message can have three parts: a header, properties, and a body. Only the header is required. The following sections describe these parts.
For complete documentation of message headers, properties, and bodies,
see the documentation of the
The following topics are addressed here:
A JMS message header contains a number of predefined fields that contain
values used by both clients and providers to identify and route
messages. Table 48-1 lists and describes the JMS message
header fields and indicates how their values are set. For example, every
message has a unique identifier, which is represented in the header
Each header field has associated setter and getter methods, which are
documented in the description of the
Table 48-1 How JMS Message Header Field Values Are Set
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 (see JMS Message Selectors). For an example of setting a property to be used as a message selector, see Sending Messages from a Session Bean to an MDB.
The JMS API provides some predefined property names that begin with
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. Table 48-2 describes these message types.
Table 48-2 JMS Message Types
The JMS API provides methods for creating messages of each type and for
filling in their contents. For example, to create and send a
At the consuming end, a message arrives as a generic
Instead of casting the message to a message type, you can call the
The JMS API provides shortcuts for creating and receiving a
You can receive the message by using the
You can use the
The consumer code can then interpret a non-text message as a signal that all the messages sent have now been received.
The examples in Chapter 49, "Java Message
Service Examples," use messages of type
JMS Queue Browsers
Messages sent to a queue remain in the queue until the message consumer
for that queue consumes them. The JMS API provides a
See Browsing Messages on a Queue for an
example of using a
The JMS API provides no mechanism for browsing a topic. Messages usually disappear from a topic as soon as they appear: If there are no message consumers to consume them, the JMS provider removes them. Although durable subscriptions allow messages to remain on a topic while the message consumer is not active, JMS does not define any facility for examining them.
JMS Exception Handling
The root class for all checked exceptions in the JMS API is
All the examples in the tutorial catch and handle