Guaranteed message deliveries part 2: when delivery is not possible

Posted by Luuk Abels on 14 Sep, 2017
DHL - We've missed you-905379-edited.jpg

In my previous blog I explained how to configure the WSO2ESB and ActiveMQ for guaranteed delivery using JMS transactions. The reason of course being that you do not want messages lost in cyberspace. In this blog about guaranteed message deliveries I want to focus on how to deal with messages that cannot be delivered.

In the previous part (1) blog I showed an example configuration that would retry indefinitely. But this can be a waste of resources when, for example, the client will not be available for some time.

A solution for this problem is to send the messages that cannot be delivered to another queue, a so called deadletterqueue. To do this you will need to configure a deadLetterStrategy.
This is a so called Enterprise Integration Pattern. These patterns are common for all organizations and the WSO2ESB supports all these patterns. To be more precise, there is a special piece of documentation about it on the WSO2 site.

In this blog I will explain how to configure such a deadLetterStrategy using the WSO2ESB and ActiveMQ.
To set up this configuration we are going to continue with the configuration from my previous blog.

The first step is to add a number of parameters to the following section in the Axis2.xml <ESB_HOME/repository/conf/axis2> configuration file:

 <!--Uncomment this and configure as appropriate for JMS transport support, after setting up your JMS environment (e.g. ActiveMQ) -->
<transportReceiver class="org.apache.axis2.transport.jms.JMSListener" name="jms">
<parameter name="myQueueConnectionFactory">
   <parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
   <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter>
   <parameter name="transport.jms.ConnectionFactoryJNDIName>QueueConnectionFactory</parameter>
   <parameter name="transport.jms.ConnectionFactoryType">queue</parameter>
   <parameter name="transport.jms.SessionTransacted">true</parameter>
   <parameter name="transport.jms.SessionAcknowledgement">CLIENT_ACKNOWLEDGE</parameter>
   <parameter name="redeliveryPolicy.redeliveryDelay">1000</parameter>
   <parameter name="redeliveryPolicy.maximumRedeliveries">-1</parameter>
   <parameter name="transport.jms.CacheLevel">consumer</parameter>
</parameter>

Add the following parameters to this section:

<parameter name="redeliveryPolicy.initialRedeliveryDelay">1000</parameter>
<parameter name="redeliveryPolicy.backOffMultiplier">3</parameter>
<parameter name="redeliveryPolicy.useExponentialBackOff">true</parameter>

Explanation

  • redeliveryPolicy.initialRedeliveryDelay: the time (in milliseconds) between the first delivery and the first redelivery attempt.
  • redeliveryPolicy.backOffMultiplier: multiplies the redelivery delay between each redeliver attempt.
  • redeliveryPolicy.useExponentialBackOff: enables or disables the exponential back off using the value set in the redeliveryPolicy.backOffMultiplier parameter.

Change the value of the following parameter:

<parameter name="redeliveryPolicy.maximumRedeliveries">3</parameter>

Note: do not forget to restart the ESB since these are only loaded at startup.

We now have configured a redelivery policy that will work the following way:

  • After the first delivery attempt there will be a delay of 1 second before the second attempt.
  • Between the second and the third attempt there will be a delay of 3 seconds.
  • Between the third and the fourth attempt there will be delay of 9 seconds.
  • After 4 delivery attempts the message will be send to the deadletterqueue.

By default ActiveMQ uses one deadletterqueue that is called ActiveMQ.DLQ. All the messages that cannot be delivered will be send to this queue.
But as you can imagine this can difficult to manage if different messages all end up in the same queue.

Individual Dead Letter Strategy

This can be solved by configuring a individualDeadLetterStrategy. This is done in the activemq.xml configuration.
Find the following section of parameters in the activemq.xml configuration file:

<destinationPolicy>
    <policyMap>
      <policyEntries>
        <policyEntry topic=">" >
            <!-- The constantPendingMessageLimitStrategy is used to prevent
                 slow topic consumers to block producers and affect other consumers
                 by limiting the number of messages that are retained
                 For more information, see:
                 http://activemq.apache.org/slow-consumer-handling.html
            -->
          <pendingMessageLimitStrategy>
            <constantPendingMessageLimitStrategy limit="1000"/>
          </pendingMessageLimitStrategy>
        </policyEntry>
      </policyEntries>
    </policyMap>
</destinationPolicy>

Replace it with the following configuration:

  <destinationPolicy>
    <policyMap>
      <policyEntries>
        <policyEntry queue=">">
          <deadLetterStrategy>
            <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>
          </deadLetterStrategy>
        </policyEntry>
      </policyEntries>
    </policyMap>
  </destinationPolicy>

Explanation

This configuration will create a deadletterqueue with the prefix “DLQ.” for every queue that has a message that cannot be delivered.
This will allow you to keep tabs on the messages while making it easier to get messages of the DLQ since we still need to deliver them.

If you have any questions about this blogpost contact us via the comments section of this blog. View also our WSO2 Tutorials, webinars or white papers for more technical information. Need support? We do deliver WSO2 Product SupportWSO2 Development SupportWSO2 Operational Support and WSO2 Training Programs.

Are you ready for WSO2 Support? 

Topics: WSO2 ESB, ESB, ActiveMQ

Written by Luuk Abels

Luuk Abels
Luuk Abels is working as an Integration Consultant at Yenlo. He studied Business IT & Management and is an expert in Middleware Architecture. He usually works on-site, where he helps clients solve, monitor and update their WSO2 environment. Besides his technical skills, Luuk is passionate about enterprise architecture. In his free time, Luuk enjoys playing field hockey.