type=page
status=published
title=The JMS API Programming Model
next=jms-concepts004.html
prev=jms-concepts002.html
~~~~~~
= The JMS API Programming Model


[[BNCEH]]

[[the-jms-api-programming-model]]
The JMS API Programming Model
-----------------------------

The basic building blocks of a JMS application are

* Administered objects: connection factories and destinations
* Connections
* Sessions
* `JMSContext` objects, which combine a connection and a session in one
object
* Message producers
* Message consumers
* Messages

link:#BNCEI[Figure 48-5] shows how all these objects fit together in a
JMS client application.

[[BNCEI]]

.*Figure 48-5 The JMS API Programming Model*
image:img/javaeett_dt_030.png[
"Diagram of the JMS API programming model: connection factory,
JMSContext, connection, session, message producer, message consumer,
messages, and destinations"]

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 link:jms-examples.html#BNCGV[Chapter 49, "Java Message Service
Examples,"] beginning with link:jms-examples003.html#BNCFA[Writing Simple
JMS Applications]. For more detail, see the JMS API documentation, part
of the Java EE API documentation.

[[BNCEJ]]

[[jms-administered-objects]]
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 `asadmin create-jms-resource`
command or the Administration Console to create JMS administered objects
in the form of connector resources. You can also specify the resources
in a file named `glassfish-resources.xml` that you can bundle with an
application.

NetBeans IDE provides a wizard that allows you to create JMS resources
for GlassFish Server. See link:jms-examples003.html#GKTJS[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
link:jms-concepts005.html#BABHFBDH[Creating Resources for Java EE
Applications] for details. Definitions in a deployment descriptor
override those specified by annotations.

[[BNCEK]]

[[jms-connection-factories]]
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 `ConnectionFactory`,
`QueueConnectionFactory`, or `TopicConnectionFactory` interface. To
learn how to create connection factories, see
link:jms-examples003.html#GKTJS[Creating JMS Administered Objects].

At the beginning of a JMS client program, you usually inject a
connection factory resource into a `ConnectionFactory` object. A Java EE
server must provide a JMS connection factory with the logical JNDI name
`java:comp/DefaultJMSConnectionFactory`. The actual JNDI name will be
implementation-specific.

For example, the following code fragment looks up the default JMS
connection factory and assigns it to a `ConnectionFactory` object:

[source,oac_no_warn]
----
@Resource(lookup = "java:comp/DefaultJMSConnectionFactory")
private static ConnectionFactory connectionFactory;
----

[[BNCEL]]

[[jms-destinations]]
JMS Destinations
^^^^^^^^^^^^^^^^

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 link:jms-examples003.html#GKTJS[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
`Destination` object.

The following code specifies two resources, a queue and a topic. The
resource names are mapped to destination resources created in the JNDI
namespace:

[source,oac_no_warn]
----
@Resource(lookup = "jms/MyQueue")
private static Queue queue;

@Resource(lookup = "jms/MyTopic")
private static Topic topic;
----

In a Java EE application, JMS administered objects are normally placed
in the `jms` naming subcontext.

With the common interfaces, you can mix or match connection factories
and destinations. That is, in addition to using the `ConnectionFactory`
interface, you can inject a `QueueConnectionFactory` resource and use it
with a `Topic`, and you can inject a `TopicConnectionFactory` resource
and use it with a `Queue`. The behavior of the application will depend
on the kind of destination you use and not on the kind of connection
factory you use.

[[BNCEM]]

[[connections]]
Connections
~~~~~~~~~~~

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.


[width="100%",cols="100%",]
|=======================================================================
a|
*Note*:

In the Java EE platform, the ability to create multiple sessions from a
single connection is limited to application clients. In web and
enterprise bean components, a connection can create no more than one
session.

|=======================================================================


You normally create a connection by creating a `JMSContext` object. See
link:#BABGDFEA[JMSContext Objects] for details.

[[BNCEN]]

[[sessions]]
Sessions
~~~~~~~~

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
`JMSContext` object. See link:#BABGDFEA[JMSContext Objects] for details.
You use sessions to create message producers, message consumers,
messages, queue browsers, and temporary destinations.

Sessions serialize the execution of message listeners; for details, see
link:#BNCEQ[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
link:jms-concepts004.html#BNCGH[Using JMS Local Transactions].

[[BABGDFEA]]

[[jmscontext-objects]]
JMSContext Objects
~~~~~~~~~~~~~~~~~~

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.

You use the `JMSContext` to create the following objects:

* Message producers
* Message consumers
* Messages
* Queue browsers
* Temporary queues and topics (see
link:jms-concepts004.html#BNCGB[Creating Temporary Destinations])

You can create a `JMSContext` in a `try`-with-resources block.

To create a `JMSContext`, call the `createContext` method on the
connection factory:

[source,oac_no_warn]
----
JMSContext context = connectionFactory.createContext();
----

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 `createContext` method creates a
non-transacted session with an acknowledgment mode of
`JMSContext.AUTO_ACKNOWLEDGE`. When called with no arguments from the
web or EJB container when there is an active JTA transaction in
progress, the `createContext` method creates a transacted session. For
information about the way JMS transactions work in Java EE applications,
see link:jms-concepts005.html#BNCGL[Using the JMS API in Java EE
Applications].

From an application client or a Java SE client, you can also call the
`createContext` method with the argument `JMSContext.SESSION_TRANSACTED`
to create a transacted session:

[source,oac_no_warn]
----
JMSContext context =
        connectionFactory.createContext(JMSContext.SESSION_TRANSACTED);
----

The session uses local transactions; see
link:jms-concepts004.html#BNCGH[Using JMS Local Transactions] for
details.

Alternatively, you can specify a non-default acknowledgment mode; see
link:jms-concepts004.html#BNCFW[Controlling Message Acknowledgment] for
more information.

When you use a `JMSContext`, message delivery normally begins as soon as
you create a consumer. See link:#BNCEP[JMS Message Consumers] for more
information.

If you create a `JMSContext` in a `try`-with-resources block, you do not
need to close it explicitly. It will be closed when the `try` block
comes to an end. Make sure that your application completes all its JMS
activity within the `try`-with-resources block. If you do not use a
`try`-with-resources block, you must call the `close` method on the
`JMSContext` to close the connection when the application has finished
its work.

[[BNCEO]]

[[jms-message-producers]]
JMS Message Producers
~~~~~~~~~~~~~~~~~~~~~

A message producer is an object that is created by a `JMSContext` or a
session and used for sending messages to a destination. A message
producer created by a `JMSContext` implements the `JMSProducer`
interface. You could create it this way:

[source,oac_no_warn]
----
try (JMSContext context = connectionFactory.createContext();) {
    JMSProducer producer = context.createProducer();
    ...
----

However, a `JMSProducer` is a lightweight object that does not consume
significant resources. For this reason, you do not need to save the
`JMSProducer` in a variable; you can create a new one each time you send
a message. You send messages to a specific destination by using the
`send` method. For example:

[source,oac_no_warn]
----
context.createProducer().send(dest, message);
----

You can create the message in a variable before sending it, as shown
here, or you can create it within the `send` call. See link:#BNCES[JMS
Messages] for more information.

[[BNCEP]]

[[jms-message-consumers]]
JMS Message Consumers
~~~~~~~~~~~~~~~~~~~~~

A message consumer is an object that is created by a `JMSContext` or a
session and used for receiving messages sent to a destination. A message
producer created by a `JMSContext` implements the `JMSConsumer`
interface. The simplest way to create a message consumer is to use the
`JMSContext.createConsumer` method:

[source,oac_no_warn]
----
try (JMSContext context = connectionFactory.createContext();) {
    JMSConsumer consumer = context.createConsumer(dest);
    ...
----

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 `JMSContext` to create a message consumer, message
delivery begins as soon as you have created the consumer. You can
disable this behavior by calling `setAutoStart(false)` when you create
the `JMSContext` and then calling the `start` method explicitly to start
message delivery. If you want to stop message delivery temporarily
without closing the connection, you can call the `stop` method; to
restart message delivery, call `start`.

You use the `receive` method to consume a message synchronously. You can
use this method at any time after you create the consumer.

If you specify no arguments or an argument of `0`, the method blocks
indefinitely until a message arrives:

[source,oac_no_warn]
----
Message m = consumer.receive();
Message m = consumer.receive(0);
----

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 `receive` method with a timeout argument greater than
`0`. One second is a recommended timeout value:

[source,oac_no_warn]
----
Message m = consumer.receive(1000); // time out after a second
----

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 `JMSContext.createDurableConsumer` method to create a
durable topic subscription. This method is valid only if you are using a
topic. For details, see link:#BNCGD[Creating Durable Subscriptions]. For
topics, you can also create shared consumers; see
link:#BABJCIGJ[Creating Shared Subscriptions].

[[BNCEQ]]

[[jms-message-listeners]]
JMS Message Listeners
^^^^^^^^^^^^^^^^^^^^^

A message listener is an object that acts as an asynchronous event
handler for messages. This object implements the `MessageListener`
interface, which contains one method, `onMessage`. In the `onMessage`
method, you define the actions to be taken when a message arrives.

From an application client or a Java SE client, you register the message
listener with a specific message consumer by using the
`setMessageListener` method. For example, if you define a class named
`Listener` that implements the `MessageListener` interface, you can
register the message listener as follows:

[source,oac_no_warn]
----
Listener myListener = new Listener();
consumer.setMessageListener(myListener);
----

When message delivery begins, the JMS provider automatically calls the
message listener's `onMessage` method whenever a message is delivered.
The `onMessage` method takes one argument of type `Message`, which your
implementation of the method can cast to another message subtype as
needed (see link:#BNCEW[Message Bodies]).

In the Java EE web or EJB container, you use message-driven beans for
asynchronous message delivery. A message-driven bean also implements the
`MessageListener` interface and contains an `onMessage` method. For
details, see link:jms-concepts005.html#BNCGQ[Using Message-Driven Beans
to Receive Messages Asynchronously].

Your `onMessage` method should handle all exceptions. Throwing a
`RuntimeException` is considered a programming error.

For a simple example of the use of a message listener, see
link:jms-examples003.html#BNCFH[Using a Message Listener for Asynchronous
Message Delivery]. link:jms-examples.html#BNCGV[Chapter 49, "Java Message
Service Examples,"] contains several more examples of message listeners
and message-driven beans.

[[BNCER]]

[[jms-message-selectors]]
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 link:jms-examples008.html#BNCGW[Sending
Messages from a Session Bean to an MDB].

A message selector is a `String` that contains an expression. The syntax
of the expression is based on a subset of the SQL92 conditional
expression syntax. The message selector in the example selects any
message that has a `NewsType` property that is set to the value
`'Sports'` or `'Opinion'`:

[source,oac_no_warn]
----
NewsType = 'Sports' OR NewsType = 'Opinion'
----

The `createConsumer` and `createDurableConsumer` methods, as well as the
methods for creating shared consumers, allow you to specify a message
selector as an argument when you create a message consumer.

The message consumer then receives only messages whose headers and
properties match the selector. (See link:#BNCET[Message Headers] and
link:#BNCEV[Message Properties].) A message selector cannot select
messages on the basis of the content of the message body.

[[BABEEJJJ]]

[[consuming-messages-from-topics]]
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.

* An unshared nondurable subscription does not have a name and may have
only a single consumer object associated with it. It is created
automatically when the consumer object is created. It is not persisted
and is deleted automatically when the consumer object is closed.
+
The `JMSContext.createConsumer` method creates a consumer on an unshared
nondurable subscription if a topic is specified as the destination.
* A shared nondurable subscription is identified by name and an optional
client identifier, and may have several consumer objects consuming
messages from it. It is created automatically when the first consumer
object is created. It is not persisted and is deleted automatically when
the last consumer object is closed. See link:#BABJCIGJ[Creating Shared
Subscriptions] for more information.

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 link:#BNCGD[Creating Durable Subscriptions] for
details.

[[BNCGD]]

[[creating-durable-subscriptions]]
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.

* An unshared durable subscription is identified by name and client
identifier (which must be set) and may have only a single consumer
object associated with it.
* A shared durable subscription is identified by name and an optional
client identifier, and may have several consumer objects consuming
messages from it.

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 `JMSContext.createDurableConsumer` method to create a
consumer on an unshared durable subscription. An unshared durable
subscription can have only one active consumer at a time.

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:

* A client ID for the connection
* A topic and a subscription name for the subscription

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
call `JMSContext.setClientID`.)

After using this connection factory to create the `JMSContext`, you call
the `createDurableConsumer` method with two arguments: the topic and a
string that specifies the name of the subscription:

[source,oac_no_warn]
----
String subName = "MySub";
JMSConsumer consumer = context.createDurableConsumer(myTopic, subName);
----

The subscription becomes active after you create the consumer. Later,
you might close the consumer:

[source,oac_no_warn]
----
consumer.close();
----

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
calls `createDurableConsumer` using the same connection factory and its
client ID, the same topic, and the same subscription name, then the
subscription is reactivated and the JMS provider delivers the messages
that were sent while the subscription was inactive.

To delete a durable subscription, first close the consumer, then call
the `unsubscribe` method with the subscription name as the argument:

[source,oac_no_warn]
----
consumer.close();
context.unsubscribe(subName);
----

The `unsubscribe` method deletes the state the provider maintains for
the subscription.

link:#BNCGE[Figure 48-6] and link:#BNCGF[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, `create` stands
for a call to `JMSContext.createConsumer` with a `Topic` argument, and
`close` stands for a call to `JMSConsumer.close`. Any messages sent to
the topic between the time of the first `close` and the time of the
second `create` are not added to either subscription. In
link:#BNCGE[Figure 48-6], the consumers receive messages M1, M2, M5, and
M6, but they do not receive messages M3 and M4.

[[BNCGE]]

.*Figure 48-6 Nondurable Subscriptions and Consumers*
image:img/javaeett_dt_031.png[
"Diagram showing messages being lost when nondurable subscriptions are
used"]

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 `unsubscribe` method. In link:#BNCGF[Figure 48-7],
`create` stands for a call to `JMSContext.createDurableConsumer`,
`close` stands for a call to `JMSConsumer.close`, and `unsubscribe`
stands for a call to `JMSContext.unsubscribe`. Messages sent after the
first consumer is closed are received when the second consumer is
created (on the same durable subscription), so even though messages M2,
M4, and M5 arrive while there is no consumer, they are not lost.

[[BNCGF]]

.*Figure 48-7 Consumers on a Durable Subscription*
image:img/javaeett_dt_032.png[
"Diagram showing messages being preserved when durable subscriptions are
used"]

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
the `JMSContext.createSharedDurableConsumer` method, specifying the
topic and subscription name:

[source,oac_no_warn]
----
JMSConsumer consumer =
        context.createSharedDurableConsumer(topic, "MakeItLast");
----

See link:jms-examples003.html#BNCFX[Acknowledging Messages],
link:jms-examples004.html#BNCGG[Using Durable Subscriptions],
link:jms-examples005.html#BABEJBHA[Using Shared Durable Subscriptions],
and link:jms-examples008.html#BNCGW[Sending Messages from a Session Bean
to an MDB] for examples of Java EE applications that use durable
subscriptions.

[[BABJCIGJ]]

[[creating-shared-subscriptions]]
Creating Shared Subscriptions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A topic subscription created by the `createConsumer` or
`createDurableConsumer` method can have only one consumer (although a
topic can have many). Multiple clients consuming from the same topic
have, by definition, multiple subscriptions to the topic, and all the
clients receive all the messages sent to the topic (unless they filter
them with message selectors).

It is, however, possible to create a nondurable shared subscription to a
topic by using the `createSharedConsumer` method and specifying not only
a destination but a subscription name:

[source,oac_no_warn]
----
consumer = context.createSharedConsumer(topicName, "SubName");
----

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 link:jms-examples005.html#BABIBEAC[Using Shared Nondurable
Subscriptions] for a simple example of using shared nondurable
consumers.

You can also create shared durable subscriptions by using the
`JMSContext.createSharedDurableConsumer` method. For details, see
link:#BNCGD[Creating Durable Subscriptions].

[[BNCES]]

[[jms-messages]]
JMS Messages
~~~~~~~~~~~~

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 `Message` interface in the API
documentation. For a list of possible message types, see
link:#BNCEW[Message Bodies].

The following topics are addressed here:

* link:#BNCET[Message Headers]
* link:#BNCEV[Message Properties]
* link:#BNCEW[Message Bodies]

[[BNCET]]

[[message-headers]]
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. link:#BNCEU[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
field `JMSMessageID`. The value of another header field,
`JMSDestination`, represents the queue or the topic to which the message
is sent. Other fields include a timestamp and a priority level.

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.

[[sthref196]][[BNCEU]]

*Table 48-1 How JMS Message Header Field Values Are Set*

[width="99%",cols="20%,60%,20%"]
|=======================================================================
|*Header Field* |*Description* |*Set By*
|`JMSDestination` |Destination to which the message is being sent |JMS
provider `send` method

|`JMSDeliveryMode` |Delivery mode specified when the message was sent
(see link:jms-concepts004.html#BNCFY[Specifying Message Persistence])
|JMS provider `send` method

|`JMSDeliveryTime` |The time the message was sent plus the delivery
delay specified when the message was sent (see
link:jms-concepts004.html#BABGEADH[Specifying a Delivery Delay] |JMS
provider `send` method

|`JMSExpiration` |Expiration time of the message (see
link:jms-concepts004.html#BNCGA[Allowing Messages to Expire]) |JMS
provider `send` method

|`JMSPriority` |The priority of the message (see
link:jms-concepts004.html#BNCFZ[Setting Message Priority Levels]) |JMS
provider `send` method

|`JMSMessageID` |Value that uniquely identifies each message sent by a
provider |JMS provider `send` method

|`JMSTimestamp` |The time the message was handed off to a provider to be
sent |JMS provider `send` method

|`JMSCorrelationID` |Value that links one message to another; commonly
the `JMSMessageID` value is used |Client application

|`JMSReplyTo` |Destination where replies to the message should be sent
|Client application

|`JMSType` |Type identifier supplied by client application |Client
application

|`JMSRedelivered` |Whether the message is being redelivered |JMS
provider prior to delivery
|=======================================================================


[[BNCEV]]

[[message-properties]]
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 (see link:#BNCER[JMS Message
Selectors]). For an example of setting a property to be used as a
message selector, see link:jms-examples008.html#BNCGW[Sending Messages
from a Session Bean to an MDB].

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.

[[BNCEW]]

[[message-bodies]]
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. link:#BNCEX[Table
48-2] describes these message types.

[[sthref197]][[BNCEX]]

*Table 48-2 JMS Message Types*

[width="75%",cols="15%,60%"]
|=======================================================================
|*Message Type* |*Body Contains*
|`TextMessage` |A `java.lang.String` object (for example, the contents
of an XML file).

|`MapMessage` |A set of name-value pairs, with names as `String` objects
and values as primitive types in the Java programming language. The
entries can be accessed sequentially by enumerator or randomly by name.
The order of the entries is undefined.

|`BytesMessage` |A stream of uninterpreted bytes. This message type is
for literally encoding a body to match an existing message format.

|`StreamMessage` |A stream of primitive values in the Java programming
language, filled and read sequentially.

|`ObjectMessage` |A `Serializable` object in the Java programming
language.

|`Message` |Nothing. Composed of header fields and properties only. This
message type is useful when a message body is not required.
|=======================================================================


The JMS API provides methods for creating messages of each type and for
filling in their contents. For example, to create and send a
`TextMessage`, you might use the following statements:

[source,oac_no_warn]
----
TextMessage message = context.createTextMessage();
message.setText(msg_text);     // msg_text is a String
context.createProducer().send(message);
----

At the consuming end, a message arrives as a generic `Message` object.
You can then cast the object to the appropriate message type and use
more specific methods to access the body and extract the message
contents (and its headers and properties if needed). For example, you
might use the stream-oriented read methods of `BytesMessage`. You must
always cast to the appropriate message type to retrieve the body of a
`StreamMessage`.

Instead of casting the message to a message type, you can call the
`getBody` method on the `Message`, specifying the type of the message as
an argument. For example, you can retrieve a `TextMessage` as a
`String`. The following code fragment uses the `getBody` method:

[source,oac_no_warn]
----
Message m = consumer.receive();
if (m instanceof TextMessage) {
    String message = m.getBody(String.class);
    System.out.println("Reading message: " + message);
} else {
    // Handle error or process another message type
}
----

The JMS API provides shortcuts for creating and receiving a
`TextMessage`, `BytesMessage`, `MapMessage`, or `ObjectMessage`. For
example, you do not have to wrap a string in a `TextMessage`; instead,
you can send and receive the string directly. For example, you can send
a string as follows:

[source,oac_no_warn]
----
String message = "This is a message";
context.createProducer().send(dest, message);
----

You can receive the message by using the `receiveBody` method:

[source,oac_no_warn]
----
String message = receiver.receiveBody(String.class);
----

You can use the `receiveBody` method to receive any type of message
except `StreamMessage` and `Message`, as long as the body of the message
can be assigned to a particular type.

An empty `Message` can be useful if you want to send a message that is
simply a signal to the application. Some of the examples in
link:jms-examples.html#BNCGV[Chapter 49, "Java Message Service
Examples,"] send an empty message after sending a series of text
messages. For example:

[source,oac_no_warn]
----
context.createProducer().send(dest, context.createMessage());
----

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 link:jms-examples.html#BNCGV[Chapter 49, "Java Message
Service Examples,"] use messages of type `TextMessage`, `MapMessage`,
and `Message`.

[[BNCEY]]

[[jms-queue-browsers]]
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 `QueueBrowser`
object that allows you to browse the messages in the queue and display
the header values for each message. To create a `QueueBrowser` object,
use the `JMSContext.createBrowser` method. For example:

[source,oac_no_warn]
----
QueueBrowser browser = context.createBrowser(queue);
----

See link:jms-examples003.html#BNCFL[Browsing Messages on a Queue] for an
example of using a `QueueBrowser` object.

The `createBrowser` method allows you to specify a message selector as a
second argument when you create a `QueueBrowser`. For information on
message selectors, see link:#BNCER[JMS Message Selectors].

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.

[[BNCEZ]]

[[jms-exception-handling]]
JMS Exception Handling
~~~~~~~~~~~~~~~~~~~~~~

The root class for all checked exceptions in the JMS API is
`JMSException`. The root cause for all unchecked exceptions in the JMS
API is `JMSRuntimeException`.

Catching `JMSException` and `JMSRuntimeException` provides a generic way
of handling all exceptions related to the JMS API.

The `JMSException` and `JMSRuntimeException` classes include the
following subclasses, described in the API documentation:

* `IllegalStateException`, `IllegalStateRuntimeException`
* `InvalidClientIDException`, `InvalidClientIDRuntimeException`
* `InvalidDestinationException`, `InvalidDestinationRuntimeException`
* `InvalidSelectorException`, `InvalidSelectorRuntimeException`
* `JMSSecurityException`, `JMSSecurityRuntimeException`
* `MessageEOFException`
* `MessageFormatException`, `MessageFormatRuntimeException`
* `MessageNotReadableException`
* `MessageNotWriteableException`, `MessageNotWriteableRuntimeException`
* `ResourceAllocationException`, `ResourceAllocationRuntimeException`
* `TransactionInProgressException`,
`TransactionInProgressRuntimeException`
* `TransactionRolledBackException`,
`TransactionRolledBackRuntimeException`

All the examples in the tutorial catch and handle `JMSException` or
`JMSRuntimeException` when it is appropriate to do so.
