context.createProducer() .setDeliveryMode(DeliveryMode.NON_PERSISTENT).send(dest, msg);
Using Advanced JMS Features
This section explains how to use features of the JMS API to achieve the level of reliability and performance your application requires. Many people use JMS in their applications because they cannot tolerate dropped or duplicate messages and because they require that every message be received once and only once. The JMS API provides this functionality.
The most reliable way to produce a message is to send a
JMS messages are
Transactions allow multiple messages to be sent or received in an atomic operation. In the Java EE platform they also allow message sends and receives to be combined with database reads and writes in an atomic transaction. A transaction is a unit of work into which you can group a series of operations, such as message sends and receives, so that the operations either all succeed or all fail. For details, see Using JMS Local Transactions.
The most reliable way to consume a message is to do so within a transaction, either from a queue or from a durable subscription to a topic. For details, see Creating Durable Subscriptions, Creating Temporary Destinations, and Using JMS Local Transactions.
Some features primarily allow an application to improve performance. For example, you can set messages to expire after a certain length of time (see Allowing Messages to Expire), so that consumers do not receive unnecessary outdated information. You can send messages asynchronously; see Sending Messages Asynchronously.
You can also specify various levels of control over message acknowledgment; see Controlling Message Acknowledgment.
Other features can provide useful capabilities unrelated to reliability. For example, you can create temporary destinations that last only for the duration of the connection in which they are created. See Creating Temporary Destinations for details.
The following sections describe these features as they apply to application clients or Java SE clients. Some of the features work differently in the Java EE web or EJB container; in these cases, the differences are noted here and are explained in detail in Using the JMS API in Java EE Applications.
Controlling Message Acknowledgment
Until a JMS message has been acknowledged, it is not considered to be successfully consumed. The successful consumption of a message ordinarily takes place in three stages.
In locally transacted sessions (see Using JMS Local Transactions), a message is acknowledged when the session is committed. If a transaction is rolled back, all consumed messages are redelivered.
In a JTA transaction (in the Java EE web or EJB container) a message is acknowledged when the transaction is committed.
In nontransacted sessions, when and how a message is acknowledged depend
on a value that may be specified as an argument of the
If messages have been received from a queue but not acknowledged when a
If you use a queue or a durable subscription, you can use the
The sample program in Acknowledging Messages demonstrates two ways to ensure that a message will not be acknowledged until processing of the message is complete.
Specifying Options for Sending Messages
You can set a number of options when you send a message. These options enable you to perform the tasks described in the following topics:
Specifying Message Persistence
The JMS API supports two delivery modes specifying whether messages are
lost if the JMS provider fails. These delivery modes are fields of the
To specify the delivery mode, use the
You can use method chaining to set the delivery mode when you create a
producer and send a message. The following call creates a producer with
If you do not specify a delivery mode, the default is
Setting Message Priority Levels
You can use message priority levels to instruct the JMS provider to
deliver urgent messages first. Use the
You can use method chaining to set the priority level when you create a producer and send a message. For example, the following call sets a priority level of 7 for a producer and then sends a message:
The ten levels of priority range from 0 (lowest) to 9 (highest). If you do not specify a priority level, the default level is 4. A JMS provider tries to deliver higher-priority messages before lower-priority ones, but does not have to deliver messages in exact order of priority.
Allowing Messages to Expire
By default, a message never expires. If a message will become obsolete
after a certain period, however, you may want to set an expiration time.
For example, a message that contains rapidly changing data such as a stock price will become obsolete after a few minutes, so you might configure messages to expire after that time.
You can use method chaining to set the time to live when you create a producer and send a message. For example, the following call sets a time to live of five minutes for a producer and then sends a message:
If the specified
When the message is sent, the specified
Specifying a Delivery Delay
You can specify a length of time that must elapse after a message is
sent before the JMS provider delivers the message. Use the
You can use method chaining to set the delivery delay when you create a producer and send a message. For example, the following call sets a delivery delay of 3 seconds for a producer and then sends a message:
Using JMSProducer Method Chaining
The setter methods on the
You can also call the
Creating Temporary Destinations
Normally, you create JMS destinations (queues and topics) administratively rather than programmatically. Your JMS provider includes a tool to create and remove destinations, and it is common for destinations to be long-lasting.
The JMS API also enables you to create destinations (
The only message consumers that can consume from a temporary destination are those created by the same connection that created the destination. Any message producer can send to the temporary destination. If you close the connection to which a temporary destination belongs, the destination is closed and its contents are lost.
You can use temporary destinations to implement a simple request/reply
mechanism. If you create a temporary destination and specify it as the
value of the
For an example, see Using an Entity to Join Messages from Two MDBs.
Using JMS Local Transactions
A transaction groups a series of operations into an atomic unit of work. If any one of the operations fails, the transaction can be rolled back, and the operations can be attempted again from the beginning. If all the operations succeed, the transaction can be committed.
In an application client or a Java SE client, you can use local
transactions to group message sends and receives. You use the
You can use the
A transacted session is always involved in a transaction. To create a
transacted session, call the
As soon as the
In an application running in the Java EE web or EJB container, you cannot use local transactions. Instead, you use JTA transactions, described in Using the JMS API in Java EE Applications.
You can combine several sends and receives in a single JMS local
transaction, so long as they are all performed using the same
Do not use a single transaction if you use a request/reply mechanism, in which you send a message and then receive a reply to that message. If you try to use a single transaction, the program will hang, because the send cannot take place until the transaction is committed. The following code fragment illustrates the problem:
Because a message sent during a transaction is not actually sent until the transaction is committed, the transaction cannot contain any receives that depend on that message’s having been sent.
The production and the consumption of a message cannot both be part of the same transaction. The reason is that the transactions take place between the clients and the JMS provider, which intervenes between the production and the consumption of the message. Figure 48-8 illustrates this interaction.
Figure 48-8 Using JMS Local Transactions
The sending of one or more messages to one or more destinations by
Client 1 can form a single transaction, because it forms a single set of
interactions with the JMS provider using a single
Another way of putting this is that a transaction is a contract between a client and a JMS provider that defines whether a message is sent to a destination or whether a message is received from the destination. It is not a contract between the sending client and the receiving client.
This is the fundamental difference between messaging and synchronized processing. Instead of tightly coupling the sender and the receiver of a message, JMS couples the sender of a message with the destination, and it separately couples the destination with the receiver of the message. Therefore, while the sends and receives each have a tight coupling with the JMS provider, they do not have any coupling with each other.
When you create a
The example in Using Local Transactions shows how to use JMS local transactions.
Sending Messages Asynchronously
Normally, when you send a persistent message, the
This feature is currently available only in application clients and Java SE clients.
Sending a message asynchronously involves supplying a callback object.
You specify a