Reading Time: 5 minutes

Reuse is the catalyst that turns the vision of API-led connectivity into a reality. In the context of MuleSoft, reuse can come in many different forms:

  1. APIs
  2. Frameworks added as a jar/maven dependency
  3. Pre-packaged project templates within Exchange, which could then be imported into Anypoint Studio

The standard approach I always follow when engaging with my customers is identifying common reusable frameworks that can be used across use cases. For example, error-handling framework, logging framework, notification framework, etc. The goal is to standardize these frameworks, to make them reusable and easy for developers to incorporate into their use cases, without having to implement from scratch. One tool that helps me help my customers in building those frameworks is the XML SDK

latest report
Learn why we are the Leaders in API management and iPaaS

Advantages of the XML SDK:

  1. They are reusable by design.
  2. It is a powerful way of creating custom modules by packaging Mule components (that are used in Mule flows) together. 
  3. Easy to manage, maintain, and support, just like Mule applications.
  4. Easy to read/implement because the constructs are the same as Mule flows and developers don’t need to know any programming languages.

In this blog post, I show how to modify the error-handling logic that was demonstrated in one of my previous blog posts around Anypoint MQ, using the XML SDK. To understand the basics of XML SDK, please see this.

Quick recap on the error-handling logic

XML snippet of the error-handler logic:


<ee:transform doc:name="Transform Message" doc:id="8ea42bff-7129-465b-8a32-b3dce90aa8b1">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
"data": vars.originalPayload,
"errorDescription": error.description,
"errorCause": error.cause.summaryMessage,
"sourceQueueName": "source-queue"

}]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level="INFO" doc:name="Log redelivery_count" doc:id="ce986698-1e27-4323-8931-63adbacd2544" message="RedeliveryCount in QueueProcessor : #[vars.'redelivery_count' ]" />
<anypoint-mq:publish doc:name="Publish to error-queue" doc:id="d02eaff6-5cb5-4af6-a0e2-60eb2383dc74" config-ref="Anypoint_MQ_Config" destination="error-queue">
<anypoint-mq:properties><![CDATA[#[output application/java
---
{
count : vars.'redelivery_count'
}]]]></anypoint-mq:properties>
</anypoint-mq:publish>
<anypoint-mq:ack doc:name="Ack" doc:id="53edbd13-6dfc-4c8b-97c5-8229790be897" config-ref="Anypoint_MQ_Config" ackToken="#[vars.ackToken]"/>

As you can see, in the error handler block, there are several steps involved:

  1. Transform message with additional meta-data
  2. Logging
  3. Publishing to error-queue using Anypoint MQ Connector
  4. Acknowledging the message using Anypoint MQ Connector

The above set of steps is actually a simplistic implementation. In reality, it is common to have more orchestration and logic involved. If there are additional projects that implement a similar pattern, then there is significant value in externalizing the logic as a custom module using XML SDK.

For step-by-step instructions on how I implemented the module and the source code of the project itself, please see this.

XML Snippet of the ErrorHandler Module implementing the error-handler logic:


<?xml version="1.0" encoding="UTF-8"?>
<module name="ErrorHandler" category="SELECT"
        prefix="errorhandler"
        doc:description="This module relies entirely in runtime provided components (no other Plugin dependencies)"

        
        xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
        xmlns:mule="http://www.mulesoft.org/schema/mule/core"
        xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:anypoint-mq="http://www.mulesoft.org/schema/mule/anypoint-mq"
        xsi:schemaLocation="
           http://www.mulesoft.org/schema/mule/module http://www.mulesoft.org/schema/mule/module/current/mule-module.xsd
           http://www.mulesoft.org/schema/mule/anypoint-mq http://www.mulesoft.org/schema/mule/anypoint-mq/current/mule-anypoint-mq.xsd
           http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
           http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd">
<property name="anypointmq.url" defaultValue="https://mq-us-west-2.anypoint.mulesoft.com/api/v1" displayName="AnypointMQ-Url" type="string"/>
    <property name="anypointmq.clientId" type="string" displayName="AnypointMQ-ClientId"/>
    <property name="anypointmq.clientSecret" password="true" type="string" displayName="AnypointMQ-ClientSecret"/>
    <property name="anypointmq.sourceQueue" type="string" displayName="AnypointMQ-SourceQueueName"/>
    <property name="anypointmq.errorQueue" type="string" displayName="AnypointMQ-ErrorQueueName"/>
    <property name="originalPayload" type="string" displayName="originalPayload"/>
    <property name="ackToken" type="string" displayName="AnypointMQ-AckToken"/>
    <property name="redelivery_count" type="number" displayName="Redelivery-Count"/>
    <property name="error" type="any" defaultValue="#[error]" displayName="error"/>
<anypoint-mq:config name="Anypoint_MQ_Config" doc:name="Anypoint MQ Config" doc:id="7dabe09d-a2c8-494b-86a0-ac09ea4f5d73" >
<anypoint-mq:connection url="#[vars.'anypointmq.url']" clientId="#[vars.'anypointmq.clientId']" clientSecret="#[vars.'anypointmq.clientSecret']" />
</anypoint-mq:config>
    <operation name="on-error" displayName="Process Error">
        <body>
        <mule:logger level="INFO" doc:name="Log redelivery_count" doc:id="ce986698-1e27-4323-8931-63adbacd2544" message="RedeliveryCount in QueueProcessor : #[vars.'redelivery_count' ]" />
        <mule:logger level="INFO" doc:name="Log redelivery_count" doc:id="ce986698-1e27-4323-8931-63adbacd2544" message="ErrorCause in QueueProcessor : #[vars.error.cause.summaryMessage]" />
            <ee:transform doc:name="Transform Message" doc:id="8ea42bff-7129-465b-8a32-b3dce90aa8b1">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
"data": vars.originalPayload,
"errorDescription": vars.error.description,
"errorCause": vars.error.cause.summaryMessage,
"sourceQueueName": vars.'anypointMQ.sourceQueue'

}]]></ee:set-payload>
</ee:message>
</ee:transform>
<mule:logger level="INFO" doc:name="Log redelivery_count" doc:id="ce986698-1e27-4323-8931-63adbacd2544" message="RedeliveryCount in QueueProcessor : #[vars.'redelivery_count' ]" />
<anypoint-mq:publish doc:name="Publish to error-queue" doc:id="d02eaff6-5cb5-4af6-a0e2-60eb2383dc74" config-ref="Anypoint_MQ_Config" destination="#[vars.'anypointmq.errorQueue']">
<anypoint-mq:properties><![CDATA[#[output application/java
---
{
count : vars.'redelivery_count'
}]]]></anypoint-mq:properties>
</anypoint-mq:publish>
<anypoint-mq:ack doc:name="Ack" doc:id="53edbd13-6dfc-4c8b-97c5-8229790be897" config-ref="Anypoint_MQ_Config" ackToken="#[vars.ackToken]"/>
        </body>
    </operation>

   
 </module>

In closing, I would like to leave you with the following images, the one before and the one after implementing XML SDK module:

Before
After

The XML SDK module can just be reused by any other project by simply adding the connector as a dependency from Exchange without having to rewrite or copy/paste the logic.

For more information on how to use Anypoint Platform, visit our developer tutorials site.