JMS specification provides many features towards reliable message delivery some of which are discussed briefly in the next few sections.
A message is supposed to be consumed successfully if it has been acknowledged. Acknowledgment may be initiated either by the client or by the JMS provider. When and how a message is acknowledged depends on if the session is transacted or not.
For a transacted session, acknowledgments are sent automatically by the provider when a transaction is committed. If a transaction is rolled back, all consumed messages are resent to the destination the messages consumed from.
2. Message Persistence
By default, messages sent by producers and to be delivered to consumers are stored in stable persistent storage before delivery. The send() method does not return successfully until a message is stored. So, if the provider fails later during message delivery due to some reason, or if it is restarted, the messages still sustain. This is known as persistent delivery mode. JMS also provides non_ persistent delivery mode where messages before delivery are not stored in persistent storage. So, messaging may be missing. However, it reduces storage and performance is expected to be better.
A JMS client can instruct the provider to use a specific kind of delivery mode. One way to do this
is to use the setDeiiveryMode() method of the MessageProducer interface as follows:
This sets the delivery mode for all messages sent by that producer to non_persistent mode. We can also use the overloaded send () method to set the delivery mode for a specific message as follows:
mp.send(message, DeliveryMode.NON_PERSISTENT, 3, 10000);
The second argument sets the delivery mode to non_persistent. The third and fourth arguments set the priority level and expiration time, which are described in the next sections.
3. Message Priority
JMS specifies ten levels of priority range from 0 (lowest) to 9 (highest) that indicate how urgently messages should be delivered. One way to do this is to use the setPriority() method of the MessageProducer interface as follows:
This sets the priority level for all messages sent by that producer to 6. We can also use the send() method of the MessageProducer interface to set the priority for a specific message as follows:
mp.send(message, DeliveryMode.NON_PERSISTENT, 6, 10000);
The third argument sets the priority level.
4. Message Expiration
By default, JMS provider retains all the messages in the memory indefinitely. In addition, they are key in persistent storage if persitent delivery mode is used. A message may be given an expiry time after which the message is no longer retained in the JMS system. Note that the messages are not deleted as soon as they expire. The JMS provider looks for all expired messages after a certain time interval and deletes such messages from the memory. If an expired message is a persistent one, it is deleted from the persistent message as well.
One way to do this is to use the setTimeToLive() method of the MessageProducer interface as follows:
This sets the expiry time for all messages sent by that producer to 10000 milliseconds (10 seconds). We can also use the send() method of the MessageProducer interface to set the expiry time for a specific message as follows:
mp.send(message, DeliveryMode.NON_PERSISTENT, 5, 10000);
The fourth argument sets expiry time.
5. Temporary Destinations
The destinations (queues and topics), we have created so far lasts even after a provider restarts. JMS API also allows to create TemporaryQueue and TemporaryTopic objects that only last till the connection, in which they are created survives. We create these temporary queues and topic using the createTemporaryQueue() and the createTemporaryTopic() methods on Session interface. The temporary destinations are typically used to implement a simple request/reply mechanism.
Source: Uttam Kumar Roy (2015), Advanced Java programming, Oxford University Press.