Reliability Mechanisms
Start course
1h 24m

This course covers the Java Message Service (JMS) API and its main concepts. Finally, we will look through example questions.

Learning Objectives

  • Understand the fundamentals of the JMS API and messaging
  • Learn about writing message producers and consumers
  • Learn about reliability mechanisms
  • Learn how to write message-driven beans

Intended Audience

This course is intended for anyone who already has basic knowledge of Java and now wants to learn about Java Enterprise Edition.


Basic knowledge of Java programming.


Hello there. In this lesson, we will talk about reliability mechanisms. So, let's start. You've seen how to connect to a provider, create different types of messages, send them to queues or topics and receive them. But what if you rely heavily on JMS, and need to ensure reliability or other advanced features?

JMS defines several levels of reliability to ensure your message is delivered even if the provider crashes or is under load or if destinations are filled with messages that should have expired. The mechanisms for achieving reliable message delivery are like this; filtering messages. Using selectors you can filter messages you want to receive. Setting message time-to-live. Send an expiration time on messages, so they are not delivered if they are obsolete. Specifying message persistence. Specify that messages are persistent in the event of a provider failure. Controlling acknowledgement. Specify various levels of message acknowledgement. Creating durable subscribers. Ensure messages are delivered to an unavailable subscriber in a pub sub model. Setting priorities. Set the priority for delivering a message.

Some messaging applications need to filter the messages they receive. When a message is broadcast to many clients, it becomes useful to set criteria, so that it's only consumed by certain receivers. This eliminates both the time and bandwidth the provider would waste transporting messages to clients that don't need them. You've seen that messages are composed of three parts; header, properties and body. The header contains a fixed number of fields, the message metadata. And the properties are set of custom name value pairs that the application can use to set any values. Selection can be done on those two areas. Producers set one or several property values or header fields and the consumer specifies message selection criteria using selector expressions. Only messages that match the selector are delivered. Message selectors assign the work of filtering messages to the JMS provider rather than to the application. A message selector is a string that contains an expression.

The syntax of the expression is based on a subset of the SQL 92 conditional expression syntax and looks like this, context. createConsumer{queue, "JMSPriority<6"). receive{}; context.createConsumer{queue, "JMSPriority AND orderAmount<200"). to receive{}; context. createConsumer{queue, "orderAmount BETWEEN 1000 AND 2000"). receive{};. In the proceeding code, a consumer is created with the JMS context. create consumer method, passing a selector string. This string can use header fields, JMS priority six or custom properties order amount 200. The producer sets these properties into the message like this; context.createTextMessage() .setIntProperty("orderAmount",1530); context.createTextMessage() .set JMSPriority(5);. Selector expressions can use logical operators; not and/ or, comparison operators, arithmetic operators, expressions, not between, not in, not like, is not null and so on. Under heavy load, a time to live can be set on messages to ensure that the provider will remove them from the destination when they become obsolete, by either using the JMS producer API or setting the JMS expiration header field.

The JMS producer has a setTimeToLive method that takes a number of milliseconds, context.createProducer{} .setTimeToLive{1000) .send(queue. message); JMS supports two modes of message delivery, persistent and non persistent. Persistent delivery ensures that the message is delivered only once to a consumer, whereas non persistent delivery requires a message be delivered once at most. Persistent delivery which is the default is more reliable, but at a performance cost, as it prevents losing a message if a provider failure occurs. The delivery method can be specified using the set delivery mode method of the JMS producer interface, context.createProducer{} .setDeliveryMode(DeliveryMode.NON_PERSISTENT) .send(queue, message);. So far, the scenarios we've explored have assumed that a message is sent and received without any acknowledgement, but sometimes you will want a receiver to acknowledge the message has been received. An acknowledgement phase can be initiated either by the JMS provider or by the client depending on the acknowledgement mode. In transactional sessions, acknowledgement happens automatically when a transaction is committed.

If a transaction is rolled back, all consumed messages are redelivered, but in non transactional sessions an acknowledgement mode must be specified. Auto_acknowledge, this session automatically acknowledges the receipt of a message. Client_acknowledge, a client acknowledges the message by explicitly calling the message.acknowledge method. DUPS_Ok_acknowledge, this option instructs the session to lazily acknowledge the delivery of messages. This is likely to result in the delivery of some duplicate messages if the JMS provider fails. So, it should be used only by consumers that can tolerate duplicate messages. If the message is redelivered, the provider sets the value of the JMS redelivered header field to true. This code uses the at JMS session mode annotation to set the acknowledgement mode to the JMS context on the producer. The consumer explicitly acknowledges the message by calling the acknowledged method. The disadvantage of using the pub sub model is that a message consumer must be running when the messages are sent to the topic, otherwise it will not receive them. By using durable consumers, the JMS API provides a way to keep messages in the topic until all subscribed consumers receive them. With durable subscription, the consumer can be offline for some time, but when it reconnects it receives the messages that arrive during its disconnection.

To achieve this, the client creates a durable consumer using the JMS context. At this point, the client program starts the connection and receives the messages. The name, Java EE seven durable subscription is used as an identifier of the durable subscription. Each durable consumer must have a unique ID, resulting in the declaration of a unique connection factory for each potential durable consumer. You can use message priority levels to instruct the JMS provider to deliver urgent messages first. JMS defines 10 priority values, with zero as the lowest and nine as the highest. You can specify the priority value by using the set priority method of the JMS producer. Most of these methods return the JMS producer to allow method calls to be chained together, allowing a fluid programming style. For example, context.createProducer() .setPriority(2). Set time to live 1000, set delivery mode, delivery mode non persistent, send(queue, message);. So, that's it. Hope to see you in our next lesson. Have a nice day.


About the Author
Learning Paths

OAK Academy is made up of tech experts who have been in the sector for years and years and are deeply rooted in the tech world. They specialize in critical areas like cybersecurity, coding, IT, game development, app monetization, and mobile development.

Covered Topics