Create mule common libraries

Image from https://en.wikipedia.org/wiki/Biblioburro A nice story
Mule libraries

Today we will explore how to build our own “batteries” for mule and include it in our applications just like a normal java project.

I found, by working with several customers, that they tend to ignore this capability of Mule ESB and end up in copying around mule xml fragment in all their application forgetting that you can use all the power of Maven and modules even with Mule.

If you are and experienced java developer working since long time with maven this post will probably don’t teach you anything new but I often saw that, due to the easy to use GUI of Anypoint Studio, Mule is often used by several different type of profiles that don’t actually already have an huge experience with maven and/or java and this post targets mainly this audience.

But let’s move to the interesting part; the subject of this tutorial will be based on a common use case that came up in quite often in my career.

The use case: Send exceptions via mail

This is something that customer will always ask you: “If something goes wrong I want a mail”.

Off course it’s clear that there also another way to monitor and log exception that are equally informative and immediate but in my experience if such system are not already used will be and additional work that customer will probably not accept and this is a point I can completely understand.

Therefore you will end up in mail exception from all your mule application, and off course you will standardize the way you mail them. A simple solution is tu use a special log category and take advantage of log4j smtp appender but in most of the cases customer will need some more information and often a customized subject especially when the exception is a business one.

For this reason you will end up implementing an asynchronous mule flow that create an html mail and sent it via the SMTP connector (If you did it synchronously you probably didn’t had enough caffeine in your body).

It’s obvious that this is something you could potentially reuse in every application so why copying and pasting around when you can create a library and use it

Build your common library

The only thing you need to do is to create a standard mule project and call it as you like it.commons app project

My common sample application will have the following mule config file:

com_toforge_mule_commons_exception_mailer.xml

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
	xmlns:spring="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/smtp http://www.mulesoft.org/schema/mule/smtp/current/mule-smtp.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
    <smtp:connector name="com_toforge_mule_commons_exceptionMailer_smtp" contentType="text/html" validateConnections="true" doc:name="SMTP"/>
    <flow name="com_toforge_mule_commons_exception_mailer_flow" >
        <vm:inbound-endpoint exchange-pattern="one-way" path="com.toforge.mule.commons.exceptionMailer.queue" doc:name="VM"/>
        <parse-template location="com/toforge/mule/commons/templates/exception/mail.html" doc:name="Parse Template"/>
        <set-property propertyName="#['subject']" value="Exception on  mule app #[app.name]" doc:name="Set subject"/>
        <smtp:outbound-endpoint host="${com.toforge.mule.commons.exceptionMailer.smtp.host}" port="${com.toforge.mule.commons.exceptionMailer.smtp.port}" to="${com.toforge.mule.commons.exceptionMailer.mail.to}" from="${com.toforge.mule.commons.exceptionMailer.mail.from}" responseTimeout="10000" encoding="UTF-8" mimeType="text/html" doc:name="Mail sending" doc:description="Send mail containing the exception to specified mail address" connector-ref="com_toforge_mule_commons_exceptionMailer_smtp"/>
    </flow>
</mule>

As you probally noticed the flow name is quite long and looks like a package name, same goes for the vm inbound queue and properties.
This must be done for avoid accidental clash of names when using different libraries and got unexpected behaviors in your applications and furthermore helps developer to understand in which package referenced properties and/or config files can be found.
As you can see in the following image the flow is quite simple, it will parse a template that contains an html mail put it in the payload set the subject by adding the app name in it and send the mail via the SMTP connector.

Exception mailer

For let you reproduce the app this is the content of the template file: com/toforge/mule/commons/templates/exception/mail.html

<html>
  <body>
    <b>Flow:</b> #[exception.event.flowConstruct] <br/>
    <b>Cause</b>: #[exception.getMessage()] <br/>
    <b>Payload:</b><br />#[org.apache.commons.lang.StringEscapeUtils.escapeHtml(payload)]<br />
  </body>
</html>

We can now declare our library completed and for use it it’s enough to build it but please note that the maven build packaging type must be jar and not mule, this because it will be used inside another user application and must be build as a mule zip deployable package but as a normal java library.
So please go in the generated pom.xml file and modify the field packaging by setting it to jar, it should look like this:

Pom commons

Now before be able to use it on another application we must install it in our local maven repository (Bonus tip:in a well organized team you will probably be able to build it on a continuous integration system (Jenkis) and deploy it to a snapshot nexus repository so that all the team can immediately use it).

So just open a shell and move in the directory of the project and run the command mvn clean install.

Once the build completes with success we can now create a sample application for try out our library.

Use your library

Once created a new application the first thing you need to do is open the POM and adding the dependency to your common library installed in your local maven repository, in my case is:

<dependency>
    <groupId>com.toforge.mule</groupId>
    <artifactId>commons</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

Now we can create a sample flow that uses this application. In my case I create a flow that you can call via http that will use a message filter to generate an exception and than in the catch strategy I just put an async VM outbound message processor that sends the message to the queue “com.toforge.mule.commons.exceptionMailer.queue”.
Off course our mule configuration file must load the flow from our library and for doing so we just take advantage of spring import capability using the spring:import tag.
Here the full xml of my sample flow:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:context="http://www.springframework.org/schema/context" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
	xmlns:spring="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="exception" doc:name="HTTP Listener Configuration"/>
    <context:property-placeholder location="sample-app.properties"/>
    <spring:beans>
    	<spring:import resource="classpath:com_toforge_mule_commons_exception_mailer.xml"/>
    </spring:beans>
    <flow name="sample-appFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
        <message-filter throwOnUnaccepted="true" doc:name="Message">
            <expression-filter expression="#[null]"/>
        </message-filter>
        <catch-exception-strategy doc:name="Catch Exception Strategy">
            <logger message="Exception raised, sending mail now" level="INFO" doc:name="Logger"/>
            <vm:outbound-endpoint exchange-pattern="one-way" path="com.toforge.mule.commons.exceptionMailer.queue" doc:name="VM"/>
        </catch-exception-strategy>
    </flow>
</mule>

sample flow common

Off course don’t forget to add to your src/main/resources the property file referenced in this example that should contain this variables:

com.toforge.mule.commons.exceptionMailer.smtp.host=localhost
com.toforge.mule.commons.exceptionMailer.smtp.port=25
com.toforge.mule.commons.exceptionMailer.mail.to= yourmail@yourdomain.com
com.toforge.mule.commons.exceptionMailer.mail.from= esb@localhost

On my mac I use a local postfix to send the mail but you could modify the common application for use external smtp server.

If you followed all the steps you should be able to run your test application and trigger an exception by calling the url http://localhost:8081/exception and get the mail.

You can now have fun and extend your common package by also adding common java classes like common transformers or specific custom message processor that you can reuse in all your apps.

Conclusions

It is clear that this approach will increase your team productivity by maximize code and mule configuration reusage bringing you the same advantage that you normally have in standard java apps however keep in mind that you must put something in a common library when you really use it in most of your apps.

Like always I do love when people point out that something in my post is not clear and if I did english language (ho|e)rrors so don’t hesitate to leave me feedbacks down here, I will appreciate it.

Mule documentation reference

https://docs.mulesoft.com/mule-user-guide/v/3.7/sharing-custom-configuration-fragments

https://docs.mulesoft.com/mule-user-guide/v/3.7/sharing-custom-code

https://docs.mulesoft.com/mule-user-guide/v/3.7/sustainable-software-development-practices-with-mule

  • Eduardo Ponzoni

    Very cool!!! In my company, we have created sort of a way of handling those exactly like you did, however we have created a shared catch exception strategy to use across the flows. Your idea of reusing by building it as library rather than another Mule application is the missing piece for us! Great work! I’m starting up a Blog around our journey into Mule as we all are pretty old BizTalk and Java guys moving into Mule for a while now. Again, thanks for sharing this great post! Keep it up!

  • http://www.toforge.com/ Mauro Rocco

    You are welcome. Thanks for the nice words.

  • Spyzou

    Thanks for the article! I’m exactly the audience intended for your post.

    I couldn’t get your example to completely work because of missing mail.html in commons JAR file build, but I got the gist of it and will try to adapt it to my need.