Overview

Messages are redelivered to a client when any of the following occurs:

  1. A transacted session is used and rollback() is called.
  2. A transacted session is closed before commit is called.
  3. A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called.

Behavior in the 3.x brokers

Acks/Nacks would be sent to the broker for each message that need to be redelivered. The broker would then redeliver the messages to a consumer. The broker could implement broker side redelivery process as he was aware of when messages were being redelivered to the client. He could send the message to a DLQ after a specified number of failed deliveries.

Behavior in the 4.x brokers

Acks are not sent to the broker until the last possible moment. In the transacted case, that's before the transaction commits. A single ranged ack is sent to the broker instead of multiple acks for each message consumed. On rollback, since nothing has been acked yet, and all messages are still available in an internal consumer queue, the messages are re-dispatched from the internal consumer queue. This reduces redelivery dispatch overhead, at the cost of the broker not being aware that redeliveries are occurring. Therefore the way redeliveries and DLQ handling is done needs to be rearchitected in the 4.x brokers.

Another bonus of this approach is that re-tried messages can preserve order very easily (which is really hard to do in the 3.x version)

The broker transmits the default delivery policy that he prefers to a client connection in his BrokerInfo command packet. But the client can override the policy settings by using the ActiveMQConnection.getRedeliveryPolicy() method:

RedeliveryPolicy policy = connection.getRedeliveryPolicy();
policy.setInitialRedeliveryDelay(500);
policy.setBackOffMultiplier(2);
policy.setUseExponentialBackOff(true);
policy.setMaximumRedeliveries(2);

Once a message's redelivery attempts exceeds the maximumRedeliveries configured for the Redelivery Policy, a "Poison ack" is sent back to the broker letting him know that the message was considered a poison pill. The Broker then takes the message and sends it to a Dead Letter Queue so that it can be analyzed later on.

The default Dead Letter Queue in ActiveMQ is called ActiveMQ.DLQ; all undeliverable messages will get sent to this queue and this can be difficult to manage. So, you can set an "individualDeadLetterStrategy" in the destination policy map of the activemq.xml configuration file, which allows you to specify a specific dead letter queue prefix for a given queue or topic. You can apply this strategy using wild card if you like so that all queues get their own dead-letter queue, as is shown in the example below.

        <destinationPolicy>
            <policyMap>
                <policyEntries>
                        <!-- Set the following policy on all queues using the '>' wildcard -->
                	<policyEntry queue=">">  
                		<deadLetterStrategy>  
                                        <!-- Use the prefix 'DLQ.' for the destination name, and make the DLQ a queue rather than a topic -->
                			<individualDeadLetterStrategy queuePrefix="DLQ." 
                			useQueueForQueueMessages="true" />  
                		</deadLetterStrategy>  
                	</policyEntry> 

                </policyEntries>
            </policyMap>
        </destinationPolicy>

See the Redelivery Policy section for some more detail on the policy options.

Graphic Design By Hiram