Delayed Redelivery Example

This example demonstrates how ActiveMQ can be configured to provide a delayed redelivery in the case where a message needs to be redelivered.

Delaying redelivery can often be useful in the case that clients regularly fail or roll-back. Without a delayed redelivery, the system can get into a "thrashing" state, with delivery being attempted, the client rolling back, and delivery being re-attempted ad infinitum in quick succession, using up valuable CPU and network resources.

Re-delivery occurs when the session is closed with unacknowledged messages. The unacknowledged messages will be redelivered.

By providing a redelivery delay, it can be specified that a delay of, say, 10 seconds is implemented between rollback and redelivery. The specific delay is configurable on both a global and per destination level, by using wild-card matching on the address settings.

Example setup

Redelivery delay is specified in the configuration file activemq-configuration.xml:

In this example we set the redelivery delay to 5 seconds for the specific example queue. We could set redelivery delay on on multiple queues by specifying a wild-card in the match, e.g. match="jms.#" would apply the settings to all JMS queues and topics.

We then consume a message in a transacted session, and rollback, and note that the message is not redelivered until after 5 seconds.

         <address-setting match="jms.queue.exampleQueue">           
            <redelivery-delay>5000</redelivery-delay>
         </address-setting>
         
     

To run the example, simply type mvn verify -Pexample from this directory

  1. Create an initial context to perform the JNDI lookup.
  2.            initialContext = getContext(0);
            
  3. Perform a lookup on the queue
  4.            Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
            
  5. Perform a lookup on the Connection Factory
  6.            ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
            
  7. Create a JMS Connection
  8.            connection = cf.createConnection();
            
  9. Create a transacted JMS Session
               Session session = connection.createSession(true, 0);
            
  10. Create a JMS Message Producer
  11.           MessageProducer producer = session.createProducer(queue);
           
  12. Create a Text Message
  13.             TextMessage message = session.createTextMessage("this is a text message");
            
  14. Send the Message
  15.             producer.send(message);
            
  16. We commit the session to effectively send the message to the queue
  17.             session.commit();
            
  18. We create a JMS message consumer on the queue
  19.             MessageConsumer messageConsumer = session.createConsumer(queue);
            
  20. We start the connection. In order for delivery to occur on any consumers or subscribers on a connection, the connection must be started
  21.            connection.start();
            
  22. We receive the message...
  23.             TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
                System.out.println("1st delivery from " + queue.getQueueName() + ": " + messageReceived.getText());            
            
  24. ...but we roll back the session. the message returns to the queue, but only after a 5 second delay
  25.             session.rollback();
            
  26. We try to receive the message but it's being delayed
  27.             
             messageReceived = (TextMessage)messageConsumer.receive(3000);
             
             if (messageReceived != null)
             {
                return false;
             }
             
             System.out.println("Redelivery has been delayed so received message is " + messageReceived);
                
                
            
  28. We try and receive the message again, this time we should get it
  29.                         
             messageReceived = (TextMessage)messageConsumer.receive(3000);
             
             System.out.println("2nd delivery from " + queue.getQueueName() + ": " + messageReceived.getText());
               
           
  30. We rollback the session again to cause another redelivery, and we time how long this one takes
               
             long start = System.currentTimeMillis();
             
             session.rollback();
                             
             messageReceived = (TextMessage)messageConsumer.receive(8000);
             
             long end = System.currentTimeMillis();
             
             System.out.println("3nd delivery from " + queue.getQueueName() + ": " + messageReceived.getText() +
                                " after " + (end - start) + " milliseconds.");           
               
            
  31. And finally, always remember to close your JMS connections and resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
  32.            finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }
            

More information