WSO2TORIAL: A primer on Dead Letter Queues in the WSO2 ESB

Posted by Rob Blaauboer on 10 Aug, 2017
Rob Blaauboer

The WSO2 ESB supports all Enterprise Integration Patterns. For those of you who do not know what that is: enterprise integration patterns are generic solutions to common IT or business problems. One of the best known is the dead letter queues in the WSO2 ESB where a message that can’t be delivered to a backend server is saved on a queue or in a database to be retried for delivery a little bit later on.

EIP

The patterns, or EIP for short, are described among other things in a book, the EIP website and the documentation of WSO2 on this topic.

Dead Letters Queues in the WSO2 ESB- Dead letter channel

In order to make this pattern more clear, we are going to set up a dead letter channel using an out of the box ESB. Why this solution and not a more enterprise like solution with a standalone message queue and real backend service?

The answer is that the principle is the same but the low complexity of the setup makes it easier to understand for novice users.

Getting started

We will use, as said a regular ESB (5.0.0) and ESB Tooling/Developer Studio.

We will use the following artifacts:

  1. Proxy to send the message;
  2. Echo Service (AAR service, default functionality of the ESB)
  3. EchoEndpoint (so we can switch off and on)
  4. Message Store for undeliverable messages
  5. Fault-sequence to give errors and store the message in a messagestore
  6. Message Processor to pickup message and send to an endpoint
  7. Reply Message sequence to catch the reply message from the echo service when it is delivered
  8. 2nd Message Store to store the reply message from the endpoint.

Dead Letters Queues in the WSO2 ESB-MyFirst ESB CAR

 

Looking at the artifacts

Let’s look at the proxy first.

Proxy - Dead Letters Queues in the WSO2 ESB

 

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="MyFirstProxy" startOnLoad="true" transports="https http" xmlns="http://ws.apache.org/ns/synapse">
   <target>
      <inSequence>
          <sequence key="SendSeq"/>
      </inSequence>
      <outSequence>
          <send/>
      </outSequence>
      <faultSequence>
          <sequence key="MyFaultSequence"/>
      </faultSequence>
  </target>
</proxy>

Since I use named Sequences there is little to see. So let’s look at the Send Sequence. Here is little to see apart from a custom log indicating the sequence and a send mediator to the EchoEndpoint.

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="SendSeq" onError="MyFaultSequence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
   <log description="" level="custom">
       <property name="STATUS" value="SendSequence"/>
   </log>
   <send>
       <endpoint key="EchoEndpoint"/>
   </send>
</sequence>

But the proxy also mentions a Fault sequence. Let us look at that.

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="MyFaultSequence" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
   <log level="custom">
       <property name="MSG" value="MyFaultSequence"/>
       <property expression="get-property('ERROR_CODE')" name="EC"/>
       <property expression="get-property('ERROR_MESSAGE')" name="EM"/>
       <property expression="get-property('ERROR_DETAIL')" name="ED"/>
       <property expression="get-property('ERROR_EXCEPTION')" name="EE"/>
   </log>
   <property name="target.endpoint" scope="default" type="STRING" value="EchoEndpoint"/>
   <store messageStore="DLMessageStore"/>
</sequence>

Here we see a custom log that retrieves error_code, error_message, error_detail and error_exception. We set the target endpoint property to EchoEndpoint and store the value to the DLMessageStore.

The Message Store in this case is an in memory message queue that requires no configuration in axis2.xml and is ideal for this purpose.

The endpoint is simply pointing to the localhost address of the ESB (we assume a port offset of zero).

<?xml version="1.0" encoding="UTF-8"?>
<endpoint name="EchoEndpoint" xmlns="http://ws.apache.org/ns/synapse">
   <address uri="http://localhost:8280/services/echo"/>
</endpoint>

The Message Processor is a bit more complex but we define what store we use, the reply sequence to capture the reply message of the backend, a fault sequence (in this case we called it Fault2 to separate the flow). The rest of the parameters is out of the box and govern retry interval, maximum delivery attemps and so on.

<?xml version="1.0" encoding="UTF-8"?>
<messageProcessor class="org.apache.synapse.message.processor.impl.forwarder.ScheduledMessageForwardingProcessor" messageStore="DLMessageStore" name="DLMessageProcessor" targetEndpoint="EchoEndpoint" xmlns="http://ws.apache.org/ns/synapse">
   <parameter name="client.retry.interval">1000</parameter>
   <parameter name="max.delivery.attempts">4</parameter>
   <parameter name="member.count">1</parameter>
   <parameter name="message.processor.reply.sequence">ReplySequence</parameter>
   <parameter name="message.processor.fault.sequence">Fault2</parameter>
   <parameter name="max.delivery.drop">Disabled</parameter>
   <parameter name="interval">1000</parameter>
   <parameter name="is.active">false</parameter>
</messageProcessor>

The flow

It is important to understand that we switched off the Message Processor in this example since we want to simulate an endpoint that is not available.

We see that a normal call goes through to the backend service since we get a message back. We use SoapUI for this.

SOAPUI - Dead Letters Queues in the WSO2 ESB

Now we will switch off the ECHO endpoint.

ECHO Endpoint  - Dead Letters Queues in the WSO2 ESB

The message will not be delivered, we simply do not get a response. But the console shows the log mediators of the fault sequence.

[2017-07-29 21:44:43,126]  INFO - LogMediator STATUS = SendSequence
[2017-07-29 21:44:43,135]  INFO - LogMediator MSG = MyFaultSequence, EC = 303001, EM = Currently , Address endpoint : [ Name : EchoEndpoint ] [ State : MAINTNENCE ], ED = Currently , Address endpoint : [ Name : EchoEndpoint ] [ State : MAINTNENCE ], EE = Currently , Address endpoint : [ Name : EchoEndpoint ] [ State : MAINTNENCE ]

The Message Store however shows one message, exactly the one we sent.

Message Store - Dead Letters Queues in the WSO2 ESB

Now we turn on the Endpoint again and after that the Message Processor.

WSO2 Carbon - Dead Letters Queues in the WSO2 ESB

Now it is the other way around.

DL Message store - Dead Letters Queues in the WSO2 ESB

The message is gone and has been delivered to the endpoint. Since we store the reply in the second Message Store we can see it.

Message Content - Dead Letters Queues in the WSO2 ESB

It looks similar to the first, but it is a response message as you can see by the echoStringResponse.

Dead letter channel

This is a very simple setup of a dead letter channel. I tricked it a bit because the message processor even sends the message if the endpoint is still switched off. This is an error and we have made a Jira WSO2 public ticket for this.

In real life you will have a standalone JMS as the message queue / message store rather than an in memory version but the principle is still the same. You want to play with the number of retries and perhaps store the message in a database for guaranteed delivery or make sure that the message is moved to other queues when delivery fails for a number of times.

In any case, you know the principle and you can elaborate on this to fit your own use case.

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.

ESB Selection Guide

 

Topics: WSO2 ESB

Rob Blaauboer

Written by Rob Blaauboer

Rob is a Senior Business Consultant and Solution Architect with more than twenty years experience. In addition to his work he is an active blogger working on a number of articles on the ‘Internet of Things’ and a WSO2 ‘Getting Started with …’ series (WSO2 tutorial) in which he talks about WSO2 components and their purpose especially aimed at non technical readers. Rob is a WSO2 expert and official WSO2 trainer.