Over a million developers have joined DZone.

Zen and the Art of Mule ESB Implementation

· Cloud Zone

Build fast, scale big with MongoDB Atlas, a hosted service for the leading NoSQL database on AWS. Try it now! Brought to you in partnership with MongoDB.

[This article was originally written by Adrian Hsieh.]

Well it worked for Motorcycle Maintenance and Archery…

After the deal had been signed, requirements were drawn up, everybody went through training, and all the software had been download, the developers and architects new to Mule ESB often puzzle themselves with this question, “Ok, what do I do now?” With all the tools and options provided by our products, taking that proverbial first step toward go-live Nirvana can indeed come across as a daunting task for Mule implementation virgins. As the pseudo-scholar of Eastern Religions, a doctor of philosophy, as well as the most monkish employee at MuleSoft, I hope to illustrate how meditating on Zen principles can help get implementations started and bring good karma to successful project completions.

Garden of Stones
The stone gardens are the ultimate crystallization of Zen philosophies. In a stone garden, there are no sculptures, no statues, and no flowers. At the same time, the garden can represent different sceneries to different people. The most famous example is the karesansui (枯山水) garden at the Ryōan-ji (龍安寺) in Kyoto, Japan, where many visitors have claimed that the stones there depict tiger cubs swimming across a river.

Similarly, the choices presented by the palettes in Mule Studio are just like the stones in the garden. It is unlikely a standard message processor would be exactly the same as one of the steps required in your algorithm. What Studio provides out of the box though, are just like the stones in the garden. It is entirely up to you how you want to utilize them to suit your purpose. For example, Mule Studio will never have a “filter out zero amount order line” transformer when mapping an archetypal sales order with header and lines. However, using the tools already provided, e.g. DataMapper, the requirement can be easily implemented. In our example here, we are mapping a sales order from Handshake, a popular mobile order taking app, to QuickBooks Windows. The business use case calls for lines with zero amount not to be mapped. Using the DataMapper, this can easily be done by first mapping all the fields normally in the visual editor:

Then by switching to the Script Editor to enclose all the mapping for the line level into an “if” block, the desired filtering is archived.

//#CTL2
 
// Transforms input record into output record.
function integer transform() {
	if ($in.0.unitPrice != 0.0 && $in.0.qty != 0.0) {
		$out.0.itemType = lookup(QBRefLookup).get($in.0.sku,dictionary.realmid,'ITEM').type;
		$out.0.discountRatePercent = isnull($in.0.percentageDiscount) ? null : str2decimal($in.0.percentageDiscount);
		$out.0.itemName = $in.0.sku;
		$out.0.discountAmount = isnull($in.0.discount) ? null : str2decimal($in.0.discount);
		$out.0.desc = $in.0.description + (isnull($in.0.notes) ? null : ' ' + $in.0.notes);
		$out.0.value11 = num2str(lookup(QBRefLookup).get($in.0.sku,dictionary.realmid,'ITEM').qbid);
		$out.0.idDomain11 = lookup(QBRefLookup).get($in.0.sku,dictionary.realmid,'ITEM').qbdomain;
		$out.0.qty= $in.0.qty;
		$out.0.unitPrice= $in.0.unitPrice;
	}
//START -> DO NOT REMOVE
$out.0.__id = $in.0.__id;
$out.0.__parent_id = $in.0.__parent_id;
//END -> DO NOT REMOVE
		return ALL;
}

The Logic of Reincarnation
Zen philosophy is a school of Buddhism, this it also accepts the concept of reincarnation. A good analogy for reincarnation in programming is recursive flow reference, which Mule fully supports but is not obvious from the Mule user interface. Many common use cases can be best solved with recursive flow reference. For example, many popular systems use name as unique record identifier, such asQuickBooks with customer name. When conflict occurs, the common business rule is to append an incremental number to the name to resolve duplication. Recursive flow offers the easiest option to find the right number.

    <flow name="qb-findname-flow" doc:name="qb-findname-flow" processingStrategy="synchronous">
        <vm:inbound-endpoint exchange-pattern="request-response" path="qb.findname" doc:name="qb.findname"/>
		<enricher source="#[payload.size()]" target="#[variable:matched]" doc:name="Message Enricher">
        	<quickbooks:find-objects config-ref="quickbooks" queryFilter="name :EQUALS: #[payload.workingname]" accessTokenId="#[map-payload:realmid]" type="#[map-payload:synctype]" doc:name="Quickbooks Online"/>
    	</enricher>
        <choice doc:name="Choice">
            <when expression="#[matched > 0]">
                <processor-chain>
                    <scripting:transformer doc:name="append-to-name">
                        <scripting:script engine="Groovy">
                            <scripting:text><![CDATA[def idx = payload.get('idx') + 1;
							def workingname = payload.get('orgname') + ' ' + idx;
							payload.put('idx', idx);
							payload.put('workingname', workingname);
							return payload;]]></scripting:text>
                        </scripting:script>
                    </scripting:transformer>
                    <logger message="QB Name conflict.  Try next: #[payload]" level="WARN" doc:name="qb-name-conflict"/>
                    <vm:outbound-endpoint exchange-pattern="request-response" path="qb.findname" doc:name="qb.findname"/>
                </processor-chain>
            </when>
            <otherwise>
                <processor-chain>
                	<logger message="Found QB Name to use: #[payload]" level="INFO" doc:name="qb-found-name"/>
                    <expression-transformer expression="#[map-payload:workingname]" doc:name="return-name"/>
                </processor-chain>
            </otherwise>
        </choice>
    </flow>

In the above example, vm-endpoint is used. Recursion can also be implemented via flow-ref. An excellent example by our Support Engineer Alberto Aresca can be found here.

Symmetry






Zen philosophy adores symmetry. The philosophy puts a heavy emphasis on striking the right balance. For every Kinkaku-ji (金閣寺),there is a Ginkaku-ji (銀閣寺). There is a thread that ties the two together in eternity.

A mule is an asymmetric animal by nature, with a horse mother and a donkey father. Mule ESB leans toward asymmetry as well, with default one-way exchange pattern and implicit queued-asynchronous process strategy. From time to time though, a synchronous behaviour may be desired, for example, often exception handling should be processed by the same thread as the flow that encountered error. In these cases, either specific processing strategy to be synchronous for a flow or simply use a sub-flow. An example of how sub-flow is used for exception handling is shown below. In this scenario, the thread that is processing the flow will also process the error response.

    <catch-exception-strategy doc:name="Catch Exception Strategy">
      <flow-ref name="set-errorresponse-subflow" doc:name="set-errorresponse-subflow"/>
    </catch-exception-strategy>
        
    <sub-flow name="set-errorresponse-subflow" doc:name="set-errorresponse-subflow">
      <set-variable variableName="jsonpmsg" value="#[exception.cause.message]" doc:name="jsonpmsgError"/>
      <scripting:transformer doc:name="json-map">
        <scripting:script engine="Groovy"><![CDATA[def jsonpmsg = message.getInvocationProperty('jsonpmsg');
          def estatus = 500;
            
          if (jsonpmsg.indexOf('token_rejected') > 0 || jsonpmsg.indexOf('OAuth') > 0)
            estatus = 401;
            
            def jsonmap=[status:estatus,message:jsonpmsg];
            return jsonmap;]]></scripting:script>
      </scripting:transformer>
      <json:object-to-json-transformer doc:name="Object to JSON"/>
      <flow-ref name="status-jsonp-subflow" doc:name="status-jsonp"/>
    </sub-flow>

In conclusion…
I hope you find this blog post helpful to your Mule endeavors and it boosts your the zenergy to kick start your implementation. Thank you for reading and Peace Out.

Download Mule ESB today!

Follow us on Twitter to get all the latest updates!

Related posts:

  1. On-Demand Webinar: Mule 101 – Getting to know Mule

Now it's easier than ever to get started with MongoDB, the database that allows startups and enterprises alike to rapidly build planet-scale apps. Introducing MongoDB Atlas, the official hosted service for the database on AWS. Try it now! Brought to you in partnership with MongoDB.

Topics:

Published at DZone with permission of Ross Mason, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}