Mule, the open source messaging framework for enterprise integration, requires significant configuration using XML files. This article provides an introduction to Mule configuration. First, it covers the basics of Mule you will need to understand.
Author’s Note: Many of the links to further Mule documentation require a mulesource.org account.
What Is Mule?
Mule is a transport-agnostic, Java-based messaging framework that allows disparate applications to connect without having to call each other directly. Mule supports multiple threading/messaging models (staged event-driven architecture, or SEDA, is the default), input and output to various transports (email, files, databases, etc.), and web services through protocols such as SOAP (see Figure 1).
Mule Components
This section defines various components that make up the Mule messaging framework and explains how to configure them using XML. The discussion refers to Mule version 2.x.
Service Component
Services are the primary Mule artifact used to implement integration solutions. A service component is a piece of code that implements some business functionality (see Figure 3). One of the primary advantages of Mule is that service components can be simple POJOs with no pre-existing external interface other than the invocation of its methods. In early versions of Mule (1.x), service components were called universal message objects (UMO).
Using the Mule Client
The Mule client is a simple interface for Java clients to send and receive messages programmatically from a Mule server and other applications. In general, messages are triggered by an external occurrence such as a message being received on a queue or a file being copied to a directory.The Mule client helps test the message flow by injecting messages for unit or load testing. If you use the Mule client in the same classloader (e.g., a web app or Mule standalone), the client will have access to the server configuration. For example, if you had this endpoint defined in your server configuration file:
<http:endpoint host=”192.168.0.1″ port=”80″ path=”/services” name=”serviceEndpoint”/>Then this endpoint would be accessible by the Mule client:
MuleClient client = new MuleClient();If you are running the Mule client in standalone mode, you configure it with its own Mule XML configuration file and pass in these files when the client is created:
client.dispatch(“serviceEndpoint”, dataObject, null);
MuleClient client = new MuleClient(“http-client-config.xml, shared-client-config.xml”);
client.getMuleContext().start();
Putting It All Together
Mule uses the configuration file to determine the data flow, as well as which components, routers, transports, and transformers to use (see Figure 8). An endpoint defines the transport to use. Below is the flow of an event through a Mule application:- A client initiates the process by invoking a URL (such as http://mycompany/order:8081).
- A declared HTTP Inbound transport picks up the message and checks if any transformation of the input (the URL in this case) is specified in the inbound router.
- If transformation is needed, a transformer such as HttpRequestToNameString is applied to the message.
- The message is dispatched to the service component for business processing.
- The Customer Data Service component retrieves customer information from a database.
- The outbound router routes the result of the service component to determine where the message should be dispatched. For example, an outbound router may specify a JMS endpoint so that the message is put on a queue or a topic.
- The outbound transport picks up the message and checks if any transformation is needed. The inbound router of the receiving service receives the message, and processing continues with the message as in step 2.
Configuration Settings
The knitting of service components into an application is done in a Mule configuration file. Mule configuration settings are the responsibility of the developer. They include:- The declaration of service components
- The endpoint(s) on which the service will receive messages
- Any transformers to use before presenting messages to a service component
- The outbound endpoint(s) where messages will go next
- Routing information for the message to dispatch it to the next service component
Declaring Service Components
<component class=”org.my.ServiceComponentImpl”/>
<pooled-component class=”org.my.ServiceComponentImpl”/>
<component>
<singleton-object class=”org.my.ServiceComponentImpl”/>
</component>
<component class=”org.my.PrototypeObjectWithMyLifecycle”>
<entry-point-resolver-set>
<array-entry-point-resolver/>
<callable-entry-point-resolver/>
</entry-point-resolver-set>
</component>
<ejb:endpoint host=”localhost” port=”1099″ object=”SomeService” method=”remoteMethod”/>
Configuring Endpoints
<file:endpoint name=”fileReader” reverseOrder=”true”
comparator=”org.mule.transport.file.comparator.OlderFirstComparator”/>
……
<model>
<service name=”Priority1″>
<file:inbound-endpoint ref=”fileReader” path=”/var/prio1″/>
……
</service>
<service name=”Priority2″>
<file:inbound-endpoint ref=”fileReader” path=”/var/prio2″/>
……
</service>
</model>
<inbound-endpoint address=”udp://localhost:65432″/>
<inbound-endpoint address=”jms://test.queue”/>
<outbound-endpoint address=”smtp://user:secret@smtp.host”/>
<outbound-endpoint address=”smtp://user:secret@smtp.host”/>
Configuring Inbound Routers
<inbound>
<selective-consumer-router>
<mulexml:jxpath-filter expression=”msg/header/resultcode = ‘success'”/>
</selective-consumer-router>
<forwarding-catch-all-strategy>
<jms:endpoint topic=”error.topic”/>
</forwarding-catch-all-strategy>
</inbound>
<inbound>
<secure-hash-idempotent-receiver-router messageDigestAlgorithm=”SHA26″>
<simple-text-file-store directory=”./idempotent”/>
</secure-hash-idempotent-receiver-router>
</inbound>
<inbound>For an exhaustive list, refer to this link.
<secure-hash-idempotent-receiver-router messageDigestAlgorithm=”SHA26″>
<simple-text-file-store directory=”./idempotent”/>
</secure-hash-idempotent-receiver-router>
</inbound>
Configuring Outbound Routers
<outbound matchAll=”true”>
<filtering-router>
<endpoint address=”jms://deposit.queue”/>
</filtering-router>
<filtering-router>
<jms:outbound-endpoint queue=”large.deposit.queue”/>
<mulexml:jxpath-filter expression=”deposit/amount >= 100000″/>
</filtering-router>
</outbound>
<outbound>
<pass-through-router>
<smtp:outbound-endpoint to=”ross@muleumo.org”/>
</pass-through-router>
</outbound>
<outbound>For an exhaustive list, refer to this link.
<static-recipient-list-router>
<payload-type-filter expectedType=”javax.jms.Message”/>
<recipients>
<spring:value>jms://orders.queue</spring:value>
<spring:value>jms://tracking.queue</spring:value>
</recipients>
</static-recipient-list-router>
</outbound>
Configuring a Transport/Connector
You can declare values equivalent to an endpoint URI to describe the connection information for the transport.<rmi:endpoint name=”BadType” host=”localhost” port=”1099″ object=”MatchingUMO” method=”reverseString”/>Alternatively, you can define a connector configuration using the <connector> element. Mule uses standard components such as Work Manager for efficient pooling of thread resources and for more control over thread usage. For errors, you declare an exception strategy as well as transactional behavior.
<jms:inbound-endpoint queue=”test.queue”/>
<ssl:endpoint name=”clientEndpoint” host=”localhost” port=”60198″ synchronous=”true”/>
<quartz:endpoint name=”qEP6″ repeatCount=”10″ repeatInterval=”1000″ jobName=”job”/>
<vm:connector name=”VMConnector”>
…
<default-connector-exception-strategy>
<vm:outbound-endpoint path=”systemErrorHandler”/>
</default-connector-exception-strategy>
</vm:connector>
Configuring Transformers
You can configure a transformer locally or globally. A local transformer is defined on the endpoint where it is applied, while a global transformer is referenced when needed. The following code defines two global transformers (see definitions below).<xm:xml-to-object-transformer name=”XMLToExceptionBean”
returnClass=”org.mule.example.errorhandler.ExceptionBean”/>
<custom-transformer name=”ExceptionBeanToErrorMessage”
class=”org.mule.example.errorhandler.ExceptionBeanToErrorMessage”
returnClass=”org.mule.example.errorhandler.ErrorMessage”/>
- <append-string-transformer> appends a string to an existing string.
<append-string-transformer name=”myAppender” message=” … that’s good to know!”/>
- <xslt-transformer> processes a XML payload through XSLT.
<mulexml:xslt-transformer name=”xslt” xslFile=”./conf/xsl/cd-listing.xsl”>
<mulexml:context-property key=”title” value=”#[header:ListTitle]”/>
<mulexml:context-property key=”rating” value=”#[header:ListRating]”/>
</mulexml:xslt-transformer>
Conclusion
This article has covered the basics of Mule and how to configure Mule components using XML. As well as being a platform for SOA, Mule also offers a SOA governance (registry/repository) facility called Mule Galaxy. It also supports administering and managing Mule deployments within an enterprise via Mule HQ.Acknowledgements
Thanks to Ron Gates for proofreading this article.