Guaranteed message deliveries part 1: using the WSO2ESB and ActiveMQ

Posted by Luuk Abels on 7 Sep, 2017

How to configure a guaranteed delivery?

Whether you are a bank, a university or an SME, when you are using a ESB for communication between applications you probably also want to make sure that every message that passes through the ESB will be delivered and that no message gets lost in cyberspace.

There are a number of ways to configure a guaranteed delivery mechanism. In this blog, I want to focus on an a-synchronous solution using JMS.

I will explain how to set up a configuration where messages are being picked up from a queue in ActiveMQ and guaranteed delivered using the WSO2ESB. This blog consists of 3 parts: in part 1 I will explain how to configure a guaranteed delivery policy. Part 2 will be about what to do when the delivery of a message is not possible, and in part 3 I will tell all about monitoring the redelivery policy. First steps: configuring ActiveMQ and the WSO2ESB.

The first step is to configure the WSO2ESB and ActiveMQ, this can be done using the following link: Setting up WSO2 ESB and ActiveMQ.

After you have completed these steps, you need to add the following JMS parameters into your JMS transport listener configuration in the Axis2.xml <ESB_HOME/repository/conf/axis2> file. Please restart the ESB since these values are only read at startup. Also take a good look if you are changing the right JMS parameters, there is support for multiple JMS queues and you need the one for ActiveMQ. Keep in mind that there are a sender and receiver pair for JMS. We will now only use the receiver.

Find the following section of parameters:

<!-- 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>

    

Add the following parameters to this section:

<parameter name="transport.jms.SessionTransacted">true</parameter>
<parameter name="transport.jms.SessionAcknowledgement">CLIENT_ACKNOWLEDGE</parameter>
<parameter name="transport.Transactionality">local</parameter>
<parameter name="redeliveryPolicy.redeliveryDelay">1000</parameter>
<parameter name="redeliveryPolicy.maximumRedeliveries">-1</parameter>
<parameter name="transport.jms.CacheLevel">consumer</parameter>

    

Explanation

  • transport.jms.SessionTransacted: indicates whether the JMS session is transacted or not. The value of this parameter needs to be set to “true” because we want to know whether the message is successfully delivered or not.
  • transport.jms.SessionAcknowledgement: indicates which acknowledgment mode is to be used. The value needs to be set to “CLIENT_ACKNOWLEDGE”, this means that the client needs to acknowledge that the message is received.
  • transport.Transactionality: indicates whether the JMS sessions are transacted or not. The value needs to be set to “local”. This means local JMS session transactions are enabled.
  • redeliveryPolicy.redeliveryDelay: the time (in milliseconds) between delivery attempts.
  • redeliveryPolicy.maximumRedeliveries: the maximum number of attempts to redeliver the message (set this parameter to “-1” for unlimited retries).
  • transport.jms.CacheLevel: indicates the cachelevel. For maximum performance the value need to be set to “consumer”. Configuring a proxy service

WSO2ESB and ActiveMQ

 

Now that the configuration of the WSO2ESB and ActiveMQ is finished we can continue with the next step: configuring a proxy service. Since we have configured all of the parameters in the Axis2 configuration we only have to add the following parameters to the proxy service:

<parameter name="transport.jms.Destination">QueueName</parameter>
<parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>

    

Explanation

  • transport.jms.Destination: this is the name of the queue in ActiveMQ that you want to use. Unlike the name of the parameter suggets this is the source of the messages for the proxy service.
  • transport.jms.ConnectionFactory: this parameter specifies which JMS configuration from the Axis2 configuration is to be used.

Call mediator in blocking mode

Normally we would use the send mediator to send a message to a client. But since we need to have a acknowledgment from the client that the message is arrived we cannot use a send mediator because the ESB doesn’t wait for a response. When we use a call mediator in blocking mode the ESB will wait for a acknowledgment from the client before continuing. When the ESB does not receive a acknowledgment a time-out will occur and the faultSequence will be invoked.

  <call blocking="true">
    <endpoint name="DummyEndpoint"/>
  </call>
    

Note: if you are using a older version of the WSO2ESB than 4.9.0 you can use the callout mediator instead.

SET_ROLLBACK_ONLY

When the ESB has invoked the faultSequence we need to tell that a new delivery attempt is needed. This is done by adding the following property to the faultSequence:

<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
    

With the “SET_ROLLBACK_ONLY” property set in the faultSequence the ESB will rollback the transaction and it will initiate a retry as long as the maximum redeliveries is not reached.

Example

<proxy xmlns="http://ws.apache.org/ns/synapse" name="DummyService" transports="jms" statistics="disable" trace="disable" startOnLoad="true">
    <target>
        <inSequence>
            <call blocking="true">
                <endpoint name="DummyEndpoint"/>
            </call>
        </inSequence>
        <outSequence/>
        <faultSequence>

            <property name="SET_ROLLBACK_ONLY" scope="axis2" type="STRING" value="true" />

            <log level="full" category="ERROR">
                <property name="error_code" expression="$ctx:ERROR_CODE" />
                <property name="error_message" expression="$ctx:ERROR_MESSAGE" />
                <property name="error_detail" expression="$ctx:ERROR_DETAIL" />
            </log>
        </faultSequence>
    </target>
    <parameter name="transport.jms.Destination">QueueName</parameter>
    <parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>
</proxy>

    

So we now have a proxy that will send a message to an endpoint and a queue ready for when it fails. In the next blog, we will take a look at what we need to do when delivery is not possible.

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.

New Call-to-action

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.