JMS Pre-Acknowledge Example

Standard JMS supports three acknowledgement modes: AUTO_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE, and DUPS_OK_ACKNOWLEDGE. For a full description on these modes please consult the JMS specification, or any JMS tutorial.

All of these standard modes involve sending acknowledgements from the client to the server. However in some cases, you really don't mind losing messages in event of failure, so it would make sense to acknowledge the message on the server before delivering it to the client.

By acknowledging the message before sending to the client, you can avoid extra network traffic and CPU work done in sending acknowledgements from client to server.

The down-side of acknowledging on the server before delivery, is that if the system crashes after acknowledging the message, but before the message has been received by the client, then, on recovery, that message will be lost. This makes pre-acknowledgement not appropriate for all use cases, but it is very useful for some use-cases when you can cope with such loss of messages

An example of a use-case where it might be a good idea to use pre-acknowledge, is for stock price update messages. With these messages it might be ok to lose a message in event of crash, since the next price update message will arrive soon, overriding the previous price.

In order to use pre-acknowledge functionality with ActiveMQ the session has to be created with a special, ActiveMQ specific acknowledgement mode, given by the value of ActiveMQJMSConstants.PRE_ACKNOWLEDGE.

Example step-by-step

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 the look-ups
  4.            
         Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");
    
         ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");                      
               
            
  5. Create a the JMS objects.
  6.            
         connection = cf.createConnection();
    
         Session session = connection.createSession(false, ActiveMQSession.PRE_ACKNOWLEDGE);
    
         MessageProducer producer = session.createProducer(queue);
             
         MessageConsumer messageConsumer = session.createConsumer(queue);           
               
            
  7. Create and send a message.
  8.            
         TextMessage message1 = session.createTextMessage("This is a text message 1");
    
         producer.send(message1);
    
         System.out.println("Sent message: " + message1.getText());           
               
            
  9. Print out the message count of the queue. The queue contains one message as expected delivery has not yet started on the queue.
  10.            
         int count = getMessageCount(connection);
           
         System.out.println("Queue message count is " + count);           
               
            
  11. Start the Connection, delivery will now start. Give a little time for delivery to occur.
  12.           
         connection.start();
    
         Thread.sleep(1000);          
              
           
  13. Print out the message count of the queue. It should now be zero, since the message has already been acknowledged even before the consumer has received it.
  14.            
         count = getMessageCount(connection);         
         
         System.out.println("Queue message count is now " + count);
               
            
  15. Finally, receive the message.
  16.            
         TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
    
         System.out.println("Received message: " + messageReceived.getText());           
               
            
  17. Be sure to close our resources!
  18.            
         if (initialContext != null)
         {
            initialContext.close();
         }
         if (connection != null)
         {
            connection.close();
         }           
               
            

More information