http://www.developer.com/

Back to article

The Fundamentals of Mule Configuration


June 10, 2009

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).



Click here for larger image

Figure 1: Mule Support for Various Protocols

Mule does not dictate a single standard message format. It allows transformations to be specified only when they are required to interoperate with different services. The Mule Enterprise Edition supports multiple commercial messaging systems as well, including TIBCO Rendezvous and IBM WebSphere MQ.

Leveraging the three layers of its architecture: application, integration, and transport, Mule implements an enterprise service bus (ESB) and provides a platform for a service oriented architecture (SOA). The layered approach promotes reusability (see Figure 2).



Click here for larger image

Figure 2: Layered Approach to Promote Reusability

Installing Mule

Mulesource.org provides two releases of Mule:
  • Enterprise (licensed and supported as a commercial product – trial available here)
  • Community (a less-featured, open-source version)

For Mule 2.x, install Java Developer Kit (JDK) 1.5 with Ant 1.7.1 or Maven 2.0.9.

A "Getting Started Guide" for Mule is available here. For Eclipse development, the easiest way to begin is to set the classpath to include all .jar files in the ./lib/mule and ./lib/opt directories of the distribution.

Running Mule

Mule can be embedded in a Java application, application server, or as a web application. To run Mule, you must specify a configuration file, which describes Mule settings. You can start a Mule Server in various ways:
  • At the command prompt:
    mule [-config ] 
  • From a script:
    org.mule.MuleServer -config mule-config.xml
    //create a new server and configure it with two configuration files
    MuleServer server = new MuleServer("mule-config1.xml,mule-config2.xml");
    //Start the server. The boolean argument determines if the server should start
    //in a new thread or use the current thread
    server.start(true);
  • By specifying a fully qualified class name of the configuration builder (If this is not specified, Mule uses the default org.mule.config.builders.AutoConfigurationBuilder.):
    org.mule.MuleServer -builder  -config appContext.xml
  • By assigning a specific server ID and interacting with the Mule environment:
    AutoConfigurationBuilder configbuilder = new AutoConfigurationBuilder("C:/MuleConfDir/mule-config.xml");
    DefaultMuleConfiguration muleConfig = new DefaultMuleConfiguration();
    muleConfig.setId("MY_SERVER_ID_1");
    MuleContextBuilder contextBuilder = new DefaultMuleContextBuilder();
    contextBuilder.setMuleConfiguration(muleConfig);
    MuleContext muleContext = new DefaultMuleContextFactory().createMuleContext(configbuilder, contextBuilder);
    muleContext.start();

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).



Click here for larger image

Figure 3: Service Component

Mule provides pluggable connectivity for any service component by wrapping it with Mule-specific configuration settings that define service-specific behavior and translating external messages into an invocation of a service component's method and controlling its lifecycle. The configuration for this translation is in an XML file (mule-config.xml by default) that specifies the message flow, which should be directed to the service component.

Mule Messages

A message in Mule is simply a packet of data that can be handled and sent between applications on a specific channel or an endpoint. A message is also the equivalent of an event that is triggered by an external occurrence such as a data being received on a queue or a file being copied to a directory. You can generate MuleMessage programmatically with the Mule client.

Service Endpoints

An endpoint functions as a gateway or channel that connects the service component to external messages, which can be either local or over a network (see Figure 4). Mule can be configured to intercept messages on endpoints and transform them if needed before passing the messages onto the service components.



Click here for larger image

Figure 4: Inbound and Outbound Endpoints

A service can use different transports to receive and send messages. For each type of transport that a service will use, you could use a separate endpoint.

Message Routers

Message routers control how messages are received by components and where they are sent after they are processed. Inbound routers control how a service handles incoming messages (e.g., selectively allowing only those messages that meet specific criteria). Outbound routers control how a message is dispatched after the service has processed it (e.g., sending it to a list of recipients or splitting up the message and sending the parts to different endpoints). See Figure 5.



Click here for larger image

Figure 5: Inbound and Outbound Routers

Routers work in conjunction with filters, which specify conditions that must be met for a message to be routed to a service, and expressions to extract information from the current message.

Transports and Connectors

A transport is a data carrier that carries messages between applications using a specific protocol (see Figure 6). Mule provides support for various standard transports (JMS, HTTP, etc.) along with a facility to create custom transports by extending org.mule.transport.AbstractConnector.



Click here for larger image

Figure 6: Mule-Provided Transports

A connector represents the configuration of a specific transport. For example, a JMS connector uses a queue or topic to receive and send data; a HTTP connector uses a port to exchange data. The specific queue, topic, or port is specified within the connector. Connectors can be specified globally (for the entire Mule application) or locally at the service level.

Transformers

Data transformation is a technique that enables disparate components to understand each other's messages. A message undergoes a translation process to bridge any gap between the data representations of the two components. Mule translators (which Mule calls transformers) are Java classes, which are the data equivalent of the Adapter pattern (GOF) for messages (see Figure 7).



Click here for larger image

Figure 7: Transformer Translate Messages

Examples of translations include the transformation of an XML message to another XML format or an XML message into a Java object. Transport-specific transformers are used to convert data received and sent on a specific protocol (e.g., ObjectToJMSMessage transformer for the JMS transport).

Mule comes with a variety of transformers and allows you to create specialized ones by extending the AbstractTransformer.

A service itself may be confined to the local network or may use a native or proprietary transport that is not supported by external applications. By providing a messaging framework that is capable of translations via transformers and providing access to the service component via endpoints, Mule exposes a component service to general intranet/Internet message exchange.

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();
client.dispatch("serviceEndpoint", dataObject, null);
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:
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:
  1. A client initiates the process by invoking a URL (such as http://mycompany/order:8081).
  2. 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.
  3. If transformation is needed, a transformer such as HttpRequestToNameString is applied to the message.
  4. The message is dispatched to the service component for business processing.
  5. The Customer Data Service component retrieves customer information from a database.
  6. 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.
  7. 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.



Click here for larger image

Figure 8: Data Flow in Mule

Working with mule-config.xml

A Mule configuration file is organized as a tree of XML elements with the following basic tags:
  • <model> – Defines the services within an application
  • <service> – Configures a service
  • <description> – Describes a service for human viewing
  • <inbound> – Configures the inbound routers, their endpoints, and inbound transformers
  • <outbound> – Configures one or more outbound routers, their endpoints, and outbound transformers
  • <async-reply> – Configures an asynchronous reply router, which is used for asynchronous request/response messaging
  • <exception-strategy> – Configures the error-handling strategy on the connector or model or a service
The following is a sample model with service configurations showing some of these elements:
<mule>
  <model>
    <service name="GreeterUMO">
       <inbound....>
         <filtering-router>
       ....
       </filtering-router>
       </inbound>
       <component..../>
       <outbound....>
       .......
       </outbound>
       <default-service-exception-strategy>
       .....
       </default-service-exception-strategy>
    </service>
    <service name="GreeterUMO2" initialState="stopped">
      ...
    </service>
  </model>
</mule>

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> – A Mule component is configured by specifying the implementation class name. Mule creates a new instance of the class for each message the component receives. Note that it is the Java class that is specified, not a specific method.
    <component class="org.my.ServiceComponentImpl"/>
  • <pooled-component> – A Mule pooled component configures Mule to create a pool of that component. The object factory that creates a single instance of the object can also be specified.
    <pooled-component class="org.my.ServiceComponentImpl"/>
    <component>
         <singleton-object class="org.my.ServiceComponentImpl"/>
    </component>
  • <entry-point-resolver-set/> – Mule can be configured with an entry point resolver to dynamically choose the component method to invoke based on the payload of the message.
    <component class="org.my.PrototypeObjectWithMyLifecycle">
        <entry-point-resolver-set>
            <array-entry-point-resolver/>
            <callable-entry-point-resolver/>
        </entry-point-resolver-set>
    </component>
  • <callable-entry-point-resolver> – This entry point resolver is for components that implement the org.mule.api.lifecycle.Callable interface. A component can implement the Callable interface to override any dynamic resolution and call the interface method implementation instead.
  • <custom-entry-point-resolver-set> – This custom entry point resolver can be implemented with a class that implements the org.mule.api.model.EntryPointResolverSet interface. To specify the method explicitly on your endpoint, you can use the method argument on the endpoint, such as:
    <ejb:endpoint host="localhost" port="1099" object="SomeService" method="remoteMethod"/>
  • Mule provides several simple components that are useful for testing and initial prototyping, such as <log-component/>, which outputs all received messages as strings to the console.

    Configuring Endpoints

  • <endpoint> – Use this to declare an endpoint having a global scope throughout the entire Mule application. Within a service, ref= is used to reference the global endpoint.
    <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> – This channel is where a service component receives events. It can include the transport to use, the address, the path, or the resource (any valid URI).
    <inbound-endpoint address="udp://localhost:65432"/>
    <inbound-endpoint address="jms://test.queue"/>
  • <outbound-endpoint> – This channel is where data returned by the component is sent.
    <outbound-endpoint address="smtp://user:secret@smtp.host"/>
    <outbound-endpoint address="smtp://user:secret@smtp.host"/>

    Configuring Inbound Routers

  • <selective-consumer-router> – This router applies one or more filters to the incoming message. If the filters match, the message is forwarded to the component.
    <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>
  • <idempotent-receiver-router> – This router ensures that only unique messages are received by a service by checking the unique message ID of the incoming message. The ID can be generated from the message using an expression defined in the idExpression attribute.
    <inbound>
        <secure-hash-idempotent-receiver-router messageDigestAlgorithm="SHA26">
            <simple-text-file-store directory="./idempotent"/>
        </secure-hash-idempotent-receiver-router>
    </inbound>
  • <secure-hash-idempotent-receiver> – This router ensures that only unique messages are received by a service by calculating a hash code of the message contents.
    <inbound>
        <secure-hash-idempotent-receiver-router messageDigestAlgorithm="SHA26">
            <simple-text-file-store directory="./idempotent"/>
        </secure-hash-idempotent-receiver-router>
    </inbound>
    For an exhaustive list, refer to this link.

    Configuring Outbound Routers

  • <filtering-router> – This router uses filters to determine whether the message matches particular criteria.
    <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>
  • <pass-through-router> – This router matches all messages and simply sends or dispatches messages via the one endpoint that is configured.
    <outbound>
      <pass-through-router>
        <smtp:outbound-endpoint to="ross@muleumo.org"/>
      </pass-through-router>
    </outbound>
  • <static-recipient-list-router> – This router can be used to send the same message to multiple endpoints over a single endpoint, or to implement routing-slip behavior where the next destination for the message is determined from message properties or the payload.
    <outbound>
      <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>
    For an exhaustive list, refer to this link.

    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"/>
    <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"/>
    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.
    <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>
    For exhaustive list, refer to this link.

    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.

    About the Author

    Thribhuvan Thakur is a senior software engineer/Architect at Southwest Airlines with 14 years of experience in design and development. He has been working with Java since its inception, and with JMS since 1999. Thakur is a Sun Certified Java Programmer, Sun Certified Java Developer and Sun Certified J2EE Architect. He holds a Masters in Computer Science from the University of North Texas.

  • Sitemap | Contact Us

    Thanks for your registration, follow us on our social networks to keep up-to-date