Designing Reliable Messaging Clients

JMS applications are loosely coupled components and modules that work together in a flexible manner. There are some design considerations that can enhance the reliability and the integrity of your JMS applications. The following sections discuss some of these:

  • Message persistence to guarantee message delivery

  • Acknowledgment, priority, and time-to-live

  • Transaction support

  • Temporary destination

Specifying Message Persistence

JMS supports two delivery modes for messages: persistent and non-persistent. The persistent delivery mode, which is the default, is based on guaranteed delivery. The JMS provider will take extra care to ensure that a message is not lost in case of a JMS provider failure. A message sent with this delivery mode is logged to stable storage before it is sent.

On the other hand, the non-persistent delivery mode does not require the JMS provider to store the message to guarantee its delivery in case the provider fails.

You can specify the delivery mode in either of two ways:

  • Using the setDeliveryMode() method of the QueueSender or the TopicPublisher object to set a delivery mode for all messages sent by that producer:

    sender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    
  • Using an argument to the send() or publish() method to set the delivery mode for a specific message. Here's an example that sets the delivery mode for published messages to NON_PERSISTENT:

    publisher.publish(msg, DeliveryMode.NON_PERSISTENT);
    

Caution

Using the NON_PERSISTENT delivery mode might improve performance and reduce storage overhead by the provider, but it provides no guarantee of delivering the messages.


Figure 13.5 illustrates persistent and non-persistent messages.

Figure 13.5. Persistent and non-persistent messaging.


Message Acknowledgment, Priority, and Expiration

Another factor in designing a reliable JMS application is to control the acknowledgment, priority, and expiration date of messages.

Acknowledgment is initiated either by the JMS provider or by the JMS client, depending on the session acknowledgment mode. Establishing message acknowledgments enhances application reliability. When a JMS client receives a message, it processes the message and then acknowledges receiving it.

In transacted sessions, acknowledgment occurs automatically when a transaction is committed. In non-transacted sessions, message acknowledgment depends on the value specified as the second argument of the createQueueSession() or createTopicConnection() method. Here's an example of a non-transacted PTP session:

QueueSession qSession = qConn.createQueueSession(false,
              Session.AUTO_ACKNOWLEDGE, 3, 5000);

In the preceding example, the first parameter specifies a non-transacted session, and the second parameter specifies Session.AUTO_ACKNOWLEDGE to indicate the consumer's receipt of a message when the client has successfully returned from either the receive() or onMessage() method.

The other possible settings are

  • Session.CLIENT_ACKNOWLEDGE: When a client acknowledges a consumed message, it automatically acknowledges the receipt of all messages that have been consumed by its session.

  • Session.DUPS_OK_ACKNOWLEDGE: This type is known as lazy acknowledgment, and is performed by consumers that use duplicate messages. If the JMS provider redelivers a message, it must set the value of the JMSRedelivered message header to true.

Message priority level is specified by the third parameter of the same method. You also can set priority by using the setPriority() method of QueueSender or TopicPublisher. Message priority levels values are 0–9 (where 0 is the lowest priority). The default priority level for JMS is 4. A JMS provider tries to deliver higher-priority messages first, but does not have to deliver messages in the exact order of priority.

Message expiration time (also called time to live or TTL) is specified by the fourth parameter, and is set to five seconds. By default, a message never expires. You also can set the expiration time by using the setTimeToLive() method of QueueSender or TopicPublisher. A JMS provider will delete undelivered messages after its expiration time. This helps in optimizing storage and computing resources.

Using Local Transactions

As you learned in Day 9, a local transaction belongs only to the current process, and deals with only a single resource manager. JMS handles both local and distributed transactions. Today we'll cover local transactions, but we defer JMS distributed transactions to Day 16, “Understanding Transactions,” when you'll study the concepts of Java Transaction API (JTA).

JMS local transactions are managed by the Session object, and not by the EJB container. To change this implicit behavior, JMS provides the concept of the transacted session. A transacted session is created by setting the flag to true for the method createQueueSession(true) in PTP or createTopicSession(true) in Pub/Sub. The commit() and rollback() methods also are used by the Session object to control the transaction's behavior. An example of a local transaction in PTP is as follows:

QueueSession qSession = qConn.createQueueSession(true);
QueueSender sender = qSession.createSender(q);
TextMessage msg1 = qSession.createTextMessage();
msg.setText("Enrollment is successful.");
TextMessage msg2 = qSession.createTextMessage();
msg.setText("Regsiteration is approved.");
try{
   sender.send(msg1);
   sender.send(msg2);
   qSession.commit();
}catch (JMSException e){
     qSession.rollback();
}

Here both messages are sent to the JMS provider, but they will be delivered as a unit of work to the queue only when the commit() method is issued. Also, acknowledgment happens automatically when a transaction is committed.

Caution

JMS local transactions have no explicit begin() method to start a transaction. Therefore, transactions are chained and depend upon commit() or rollback() method calls. Transactional messages are accumulated at the JMS server until the transaction is committed or rolled back, which has negative impact on the JMS server's performance.


Working with Temporary Destinations

As you learned, JMS destinations are normally created as administered objects. JMS also enables you to create a temporary destination (TemporaryQueue and TemporaryTopic), which becomes active only during the session's connection. The JMS provider guarantees that the temporary destination is unique across all connections. You create these destinations dynamically using the createTemporaryQueue() and createTemporaryTopic() methods of the corresponding session object. The following is an example of creating a TemporaryQueue:

TemporaryQueue tempQ = qSession.createTemporaryQueue("myTempQueue");

Temporary destinations work in the same fashion as administered destinations.

Caution

If you close the connection that the temporary destination belongs to, the destination is closed and its contents are lost.


When a producer and consumer agree to use a temporary destination, the producer first creates it, and then passes its reference to the consumer. This is accomplished by setting the JMSReplyTo message header field. At the other end, the consumer needs to extract the reference from the message header before using this destination.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.216.175