Chapter 1. Fundamental Mule

This chapter covers the fundamental concepts within Mule, from the definition of an Enterprise Service Bus (ESB) to how you can configure fundamental elements inside Mule to produce a working application.

The Enterprise Service Bus

An Enterprise Service Bus (ESB), sometimes referred to as "messaging middleware," is nothing more than a platform that can carry data between different, disparate applications. Data is carried to and from a series of stops, known as "endpoints," which must be defined for each application. The internals of an ESB contain routing mechanisms that know how to direct specific data from point A to point B.

As you can see from the diagram in Figure 1-1, the ESB is a logical channel that spans your enterprise and each endpoint, and allows data to be sent or received from numerous applications via the bus. Data is transferred to or from each endpoint using a particular protocol—across a TCP connection or perhaps over HTTP, for instance. However, the ESB is more than just the protocols or communication channels; it is the messaging framework.

Mule 2.0 provides this messaging framework rather than the actual middleware required to transfer messages from one endpoint to another. Typically, you could use the Java Message Service (JMS) to transfer data, or perhaps web services, and just use Mule to manage all of this. In fact, Mule does not limit you to using one messaging middleware over another, and it supports 25 different protocols out of the box in the current release. Many more are also available on the community-based MuleForge web site that MuleSource hosts and runs at http://www.MuleForge.org.

The ESB

Figure 1.1. The ESB

Apart from this messaging, Mule has an object broker that can manage Java objects at runtime. The object broker uses a nonintrusive container that allows you to reuse existing Java objects without the need for additional coding. As well as transferring data to and from other applications, data can also be passed to and from these hosted objects. All this is performed at runtime using the staged event-driven architecture (SEDA) threading model, which was developed by Dr. Matt Walsh.

All thread handling is performed internally within Mule and shielded from the developer. While a lot of items are hidden from view, this is not to suggest that they are inaccessible; you can easily tweak or change anything within Mule by taking advantage of its fully extensible development model. Practically any class within Mule can be replaced or extended to suit your needs.

One subtle advantage of Mule is that it can be used to represent any type of topology merely by reconfiguring it. As illustrated in Figure 1-2, apart from the standard ESB topology you can also set up a peer-to-peer network, client/server, hub-and-spoke, or pipeline model, or you can combine one or more topologies depending on your particular circumstances. Such a combination is then referred to as an Enterprise Service Network (ESN).

SOA Topologies

Figure 1.2. SOA Topologies

Since Mule provides all of this and even adds numerous other features such as security, it is fair to say that it is more than merely an ESB. In fact, the term ESN is frequently used to describe Mule.

Note

This is an important point: Mule does not impose a topology on you or your applications but rather lets you choose the topology that best fits your architecture. This point will be highlighted several times throughout this book. Mule does not impose certain choices on you but instead lets you choose what makes the most architectural sense for your application.

Mule Features

Mule 2.0 provides pluggable connectivity along with a wealth of options out of the box. Common transports such as JMS, HTTP, SMTP, FTP, POP3, and XMPP are all supported natively, as are web services. In some cases, these transports support streaming of large files, but this is dependent on the protocol.[1] Messages transferred through Mule along one of these protocols can behave in any of the following ways:

  • Synchronously, meaning a message that is sent needs to generate a reply before the next message can be handled.

  • Asynchronously, meaning that multiple messages can be handled before any replies are generated. This is also known as a "fire and forget" pattern.

  • In a "request-response" pattern, which is similar to synchronous processing but also allows you to handle the response directly.

While data is being transferred through Mule, it can be transformed from one format to another before reaching its destination based on its content, the transports used, or on a series of rules. These routing options can be declared in configuration by the Mule developer or they can be dynamically formed at runtime.

Transactions are supported on specific transports,[2] but both single- and multiple- resource transactions can be used within a Mule application to preserve the state of your data. You can also handle any exceptional situations using Mule's exception strategies, which allow you to catch, route, and handle different errors in different ways.

Remote management of your Mule instances is possible using Java Management Extensions (JMX) technology or by using Mule's internal system notification mechanism. A number of external JMX tools are available that you can use to take full advantage of this, including the MuleHQ product that MuleSource bundles with the Enterprise Edition of Mule.

Enterprise vs. Community Edition

The standard Mule edition that you can freely download (and the version we're referring to in this book) is the Community Edition (CE) originally created by Ross Mason and now still thriving as a popular open source project. Ross has since founded MuleSource, based in San Francisco, which now offers a closed-source Enterprise Edition (EE) of Mule. This is basically the Community Edition with additional QA tools (Galaxy EE, MuleHQ, and Saturn) and subscription support thrown in. However, the release of Mule EE available at the time of writing this book builds on the Mule 1.x line. Ricston offers training and services supporting all versions of Mule.

Here's what the tools that ship with Mule EE offer:

  • Saturn is a business-level transaction monitoring tool that allows you to see the state of your business processes while data flows through Mule.

  • Galaxy provides a registry and repository for better SOA governance.

  • MuleHQ is a web-based interface that allows you to interact with Mule and monitor it remotely using JMX.

Anatomy of a Mule

The configuration format for Mule 2.0 is Spring based, which makes it much more extensible than it was in previous versions. However it is not dependent on Spring; you do not need to install or use Spring if you want to use Mule. The XML namespaces and schemas are provided on the MuleSource site, and because each module is now responsible for its own configuration, there is a separate namespace and schema for each Mule module: one for the core Mule module, one for each of the transports, and so forth.

When launched, Mule looks for a configuration file called mule-config.xml, but you can include a file name (and path) to load Mule with a different file of your own.

"%MULE_HOME%inmule.bat" -config bin/mule-config.xml

Mule can be loaded by running it and using any one of its command-line arguments. The main parameter to use is -config, which allows you to specify a fully-qualified or relative path and file name for the configuration file to use, as shown in the preceding code snippet. Assuming that you have the JDK installed on your computer and that it is configured properly, the single command shown previously will work from within a script. This will launch the wrapper that will, in turn, host Mule. This is the most common method used to launch Mule as a stand-alone application.

Mule can be launched programmatically by using the org.mule.MuleServer class. This class needs to be created; its constructor accepts a comma-separated list of configuration files that you want to use, as shown here:

MuleServer server = new MuleServer ("myConfig.xml,
    myOtherConfig.xml");
server.start (true);

Installing Mule as a Service (or Daemon)

Apart from being run in a stand-alone fashion, Mule can also be installed as a service on Windows or as a daemon on Unix.

On Windows, use the install parameter shown here:

mule install -config myConfig.xml

This can be reversed by using the remove command:

mule remove

Once installed, Mule can be started, stopped, or restarted. In each case, the config parameter will accept a comma-separated list of configuration files to use:

mule start | restart | stop -config myConfig.xml

Additionally, you can use the following Windows net command to start and stop Mule:

net start | stop mule

On Unix you can use the service command to start, stop, and restart Mule, but this is only applicable if your operating system supports a SysV-style startup system.

The Design-Time Container

When run, Mule will load its configuration file and host all service components that are declared within it. However, it could just as easily load this information from a third-party container, Spring being the most popular one. You can declare components, classes, and connectors inside a Spring configuration file and load them into Mule by telling Mule which container to use. In fact, you can mix the two; this allows you to add an existing Spring container to your Mule application without having to redeclare all the items.

Tip

Other design-time containers are supported too, such as the Pico container and the Hivemind container. These are all available on the MuleForge site.

Mule 2 Configuration File Structure

A typical Mule 2.0 configuration file will contain the following items:

  • Connectors need to be declared up front. Having said that, if you are prepared to use a connector with all its default values, you do not need to declare it. Mule will automatically create a connector if one is not explicitly configured.

  • Your custom transformers, if any, can be declared and given a name so that you can refer to them by name.

  • Global endpoints are also declared beforehand and then referred to by name.

  • Lastly, but not least, you should have at least one Mule model available in your application. A Mule model will contain at least one service component that is configured together with its routers, transformers (if any), and endpoints.

The configuration file illustrated here is a perfectly valid Mule configuration file that does absolutely nothing:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns=
   "http://www.mulesource.org/schema/mule/core/2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring=
   "http://www.springframework.org/schema/beans"
xsi:schemaLocation=
  "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/
      spring-beans-2.0.xsd
   http://www.mulesource.org/schema/mule/core/2.0
   http://www.mulesource.org/schema/mule/core/2.0/
      mule.xsd">

   <model name="example"/>

</mule>

Note the following items:

  • The XML version and encoding are in the first line.

  • The opening <mule> XML tags contain the references to the XML namespaces and schemas. In this case, the schemas are being loaded from the Web.

  • No connectors, transformers, or global endpoints are declared.

  • There is a single Mule model called "example," which is empty.

Due to the nature of XML namespaces and their use, Spring items can be declared explicitly inside a Mule configuration file provided that the Spring namespace has been included. Spring beans, or any Spring element, can then be inserted into a Mule configuration file. All Spring XML tags are then prefixed by <spring...> and Mule will hand over processing of these items to Spring.

Warning

Usage of Spring and Spring elements has changed considerably from previous versions of Mule. Up until Mule 1.4.3, a Spring configuration file could be loaded and parsed by Mule, and all beans defined within it could be used by Mule at runtime by specifying which configuration file to use within <container-context> XML tags.

The configuration shown here displays the namespaces required to use Spring inside your Mule configuration. Note that you can also specify Spring beans individually or have a collection of Spring beans included.

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns=
   "http://www.mulesource.org/schema/mule/core/2.0"
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:beans=
   "http://www.springframework.org/schema/beans"
xsi:schemaLocation=
   "http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/
       springbeans-2.0.xsd
    http://www.mulesource.org/schema/mule/core/
       2.0 METAINF/mule.xsd">

   <!-- Mule config here -->

   <spring:bean>  <!-- ... you can embed Spring
   bean definitions directly ... -->
   </spring:bean>

   <spring:beans> <!-- and you can have nested
   spring defintions -->
   </spring:beans>
</mule>

Mule is made up of a large number of different classes and interfaces, but we need to examine these key elements first:

  • Service components

  • Endpoints

  • Connectors

  • Routers

  • Transformers

Service Components

A service component, historically called a Universal Message Object, is nothing more than a Java object (or a Spring bean) that is hosted and contained by Mule. These components become services within the Mule instance.

Note

The term "Universal Message Object" used to be quite common in Mule 1.x, and you can find it in the online documentation and the source code for Mule 1.x. Starting with Mule 2, this name (and the corresponding acronym UMO) has been removed.

Each component contains some amount of business logic—some code related to the business task that Mule supports. This code does not need to be Mule-specific, as Mule can host components without the need for further coding of your own.

Tip

You can include Mule-specific code should you want to, but this is not obligatory.

Service components will therefore represent key integration logic within your Mule application.

Configuring Service Components

Service components must refer to some kind of Java object, either one of your own or one of the inbuilt objects, which could include the following:

  • The Bridge component, which bridges the inbound endpoint with the outbound endpoint. This is provided for backward compatibility and is no longer necessary.

  • The Echo component, which returns whatever it receives.

  • The Log component, which logs the message (or the message length) in the log files.

Each service is configured using an inbound router collection, a component, and an outbound router collection. If a component is not declared, events are automatically bridged from the inbound endpoints to the outbound endpoints.

The following attributes would be used:

  • name is a name for this service. This is an attribute for the <service> tags.

  • class is the fully-qualified class name representing this service and is an attribute for the <component> tags.

    <service name="GreeterService">
       <inbound>
          <inbound-endpoint address="http://localhost:8888"
             transformer-refs="HttpRequestToNameString"
             synchronous="true"/>
          <vm:inbound-endpoint path="greeter"
             transformer-refs="StringToNameString"
             synchronous="true"/>
       </inbound>
    Break and indent as:
          <component class=
             "org.mule.samples...
       <outbound>
          <filtering-router>
             <vm:outbound-endpoint path="chitchatter"/>
             <payload-type-filter expectedType=
                "org.mule.samples.hello.NameString"/>
          </filtering-router>
       </outbound>
    </service>

In this example we have a service called GreeterService that contains the previously used inbound and outbound router collections. The component in use is a custom one so its class name is specified between the router collections.

Endpoints

The Message Endpoint pattern[3] is used in integration projects to answer a simple question: how do you connect an object to a messaging channel? This pattern allows you to connect different applications or objects to a messaging channel. Each protocol (as a messaging channel) is transparently implemented; which means that the component will not know or need to know which protocol is going to be used to send or receive data.

Inside Mule, an endpoint can connect service components to local resources (such as files) or to network resources (for example HTTP connections or third-party applications). They also serve as the location where a number of other Mule features can be configured, such as filters, transformers, and transactions.

A simple Mule instance is shown in Figure 1-3. Every Mule instance consists of one or more service components that each have one or more endpoints. These endpoints allow data to be received or sent by the service components. Endpoints may be used to connect components together or to connect them to an external application or data source.

A Mule Instance

Figure 1.3. A Mule Instance

Each Mule application can be made up of one or more Mule instances, so it is possible that service components in separate Mule instances are connected together along an endpoint.

Endpoints can be configured on various Mule elements:

  • On the inbound section of a service component. Here the endpoint would be an inbound endpoint and data would be read from it.

  • On a router within an outbound section of a service component. Here the endpoint would be an outbound endpoint and data would be written to it.

  • In exception strategies, which are used to manage exceptions.

  • In catch-all strategies, which are used to manage routing possibilities.

Transports define customized endpoints, which allow for a simpler mechanism to set the address as well as property values. However, the simplest endpoint configuration will only need an address and nothing more. The following attributes are available to all endpoints:

  • synchronous allows you to specify whether messages read from or written to this endpoint should be read or written synchronously or asynchronously. It defaults to false so that all message flows will be asynchronous.

  • connector-ref lets you specify which connector to use with this transport. You can set up multiple connectors with the same protocol (to connect to multiple JDBC databases, for instance), which lets you tie an endpoint to a specific connector.

  • transformer-ref lets you specify a comma separated list of transformer names to apply to any messages being written to or read from this endpoint.

    <inbound-endpoint address="stdio://in"
       transformer-refs="StringToNameString"/>
    <outbound-endpoint address="smtp://[email protected]"/>

In the preceding example we can see a single inbound endpoint configured to read from the standard I/O transport's in channel (which is the standard input device). It is also configured to use a transformer, StringToNameString. In this case, any items read off the console will be converted to Name objects before being passed on to the component.

We also have a single outbound endpoint configured to write to an SMTP address.

<jms:inbound-endpoint queue="my.queue"/>
<stdio:outbound-endpoint system="OUT"/>

In this example we're using transport-specific endpoints rather than the standard ones. We can see that the JMS inbound endpoint has a queue attribute that refers to the name of a JMS queue. The outbound endpoint, on the other hand, has an attribute called system, which matches the type of endpoint for the standard I/O transport. The attributes for transport-specific endpoints will vary from one transport to another.

Configuring Global Endpoints

A global endpoint is a named endpoint template that can be declared in the Mule configuration before the Mule model(s). These endpoints can be configured once and then referred to by name from any location that would use endpoints, such as the inbound section of a service or perhaps an exception strategy. You do not need to specify any further transport-specific attributes or properties as everything has already been clearly defined.

Whenever a global endpoint is referenced, a new one will be created for you. You can override the definition of the endpoint at a local level; these changes will not affect any other use of this endpoint and will be specific to this local instance only.

<mule>
   <endpoint name="BookingQueue"
      address="vm://my.queue"/>
</mule>
<service>
   <inbound>
      <inbound-endpoint ref="BookingQueue"/>
   </inbound>
        ...
</service>

The preceding example shows a global endpoint called BookingQueue that refers to a VM queue called my.queue. The inbound endpoint section from the previous example has been changed to refer to this endpoint by using the ref attribute rather than the address attribute. If any different properties were set in the inbound endpoint section, they would not affect any other use of this endpoint. However, any changes in the global endpoint definition would affect all uses of this endpoint.

Connectors

A connector, also known as a provider or a transport, allows a component to send or receive data across a specific protocol. Each protocol is represented inside Mule using a different connector. The connector is a reference to a collection of classes that are responsible for communication, as listed here:

  • A Message Receiver is a class that knows how to receive raw data using the protocol and convert it into a format that Mule can use.

  • A Message Dispatcher is a class that knows how to convert Mule data for transmission using the protocol specified.

  • A series of optional transport-specific transformers allow you to transform the data when being sent or received.

The connector configuration element allows you to specify how a particular protocol is going to behave. For example, you can specify the host name for the SMTP transport or the data source for the JDBC transport. If the default values are sufficient for your needs, you can avoid explicitly declaring a connector, as Mule will construct one on the fly if one is needed but not explicitly declared. Endpoints that use this protocol will automatically be linked to the correct connector.

Each connector element is prefixed with the name of the technology that it describes. Each protocol defines a series of attributes for the connector too; these vary from one protocol to another but one attribute is always available: name allows you to assign a name to the connector. You can then refer to this connector by name should you need to. The connector for the standard I/O transport is shown here:

<stdio:connector name="SystemStreamConnector"
   promptMessage="Please enter something":
   messageDelayTime="1000"/>

The name attribute is set to SystemStreamConnector, and the following additional attributes are specific to this connector:

  • promptMessage will be displayed to the user.

  • messageDelayTime controls how long to wait before displaying the promptMessage to the user.

Routers

Based on the Message Router pattern,[4] routers exist to be able to decouple individual processing steps when messages are received from, or are dispatched to, endpoints.

In Mule, inbound routers exist to control messages that are received by an endpoint before the message is passed on to the service component. A message may be filtered or a set of messages may be aggregated before the component is supposed to handle them, for instance. On the outbound side, messages published by the service component are handled by routers before being passed on to the endpoints. These messages may need to be broadcast to multiple endpoints or be split according to specific criteria. A number of routing patterns are available in Mule, and we shall investigate some of the more popular ones.

The advantage of using routers is that you can have components that focus on the business processing and leave all logic related to routing and routing patterns to these Mule elements.

Note

The service components do not need to do anything else other than perform some specific task, for example validation, without worrying about where the data is coming from or which protocol is used to receive it. The services are therefore loosely coupled from the transports that carry data.

The diagram shown in Figure 1-4 illustrates a single service hosted by Mule. Data read from an endpoint on the left passes through the inbound router(s) configured for the service. The routers hand this message over to the component for processing. Once the component has a return value, it is passed to the outbound routers who, in turn, pass it on to the outbound endpoint, or endpoints.

A Single Service in Mule

Figure 1.4. A Single Service in Mule

Configuring Routers

Every service component will have both an inbound and outbound router collection so that messages can be read from at least one endpoint and replies can be sent along at least one endpoint.

An inbound router collection will normally have one or more endpoints configured within it. Any messages read from these endpoints will then pass through the default pass-through router that merely hands the message over to the component. Other inbound routing patterns can be used by defining the routers to use after the endpoint(s).

Outbound router collections must be configured using outbound routers, as there is no default router to use. You can define one or more routers and each router would contain the endpoint, or endpoints, required for its operation.

In both cases, if you have more than one router configured in a router collection, you can take advantage of the collection's matchAll attribute. This allows you to determine whether a message should be passed through all the routers, or whether it should be passed through them until one of them handles it.

Implications of matchAll

It is important that you understand how the matchAll router works. For example, assume two Filtering routers are set up such that the first router only accepts items with a value greater than 3, while the second router only accepts items with the name property set to "special:"

  • If matchAll is set to false (the default value) as shown on the left-hand side of Figure 1-5, then a message with a value greater than 3 will be accepted, a message whose name property is set to "special" will be accepted, and a message that meets both criteria will also be accepted.

  • If matchAll is set to true, as shown in Figure 1-5 on the right-hand side, then messages that match one of these conditions will be accepted as before, but a message that meets both filters will be accepted twice and processed twice.

matchAll = true vs. false

Figure 1.5. matchAll = true vs. false

Tip

The matchAll attribute is much more suitable for outbound router collections with multiple selection criteria so you can send the same message to multiple destinations based on different criteria.

Inbound Router Collection Example

The following configuration sample defines an inbound router collection with no routers configured on it:

<inbound>
      <!-- Incoming HTTP requests -->
      <inbound-endpoint address="http://localhost:8888"
       transformer-refs="HttpRequestToNameString"/>
<!-- Incoming VM requests -->
      <vm:inbound-endpoint path="greeter"
       transformer-refs="StringToNameString"
       synchronous="true"/>
</inbound>

There are two inbound endpoints:

  • An HTTP endpoint will listen on port 8888 on the localhost for HTTP requests synchronously. The HttpRequestToNameString transformer will be used to convert HTTP requests to NameString objects before the message is passed to the service component.

  • A VM endpoint will listen along the path called "greeter". Any string messages read from this endpoint will be converted to NameString objects before being passed to the service component.

Outbound Router Collection Example

The following outbound router collection has three outbound routers configured on it.

<outbound>
      <filtering-router>
      <vm:outbound-endpoint path="chitchatter"/>
      <payload-type-filter expectedType=
         "org.mule.samples.hello.NameString"/>
      </filtering-router>
      <filtering-router>
      <vm:outbound-endpoint path="userErrorHandler"/>
      <payload-type-filter expectedType=
        "java.lang.Exception"/>
      </filtering-router>
      <outbound-pass-through-router>
      <stdio:outbound-endpoint system="OUT"/>
      </outbound-pass-through-router>
</outbound>

In the first two cases, we're using the filtering outbound router. The first router will pass messages on to the VM channel called "chitchatter," provided that the payload of the message is a NameString. If this is not the case, the second router will be invoked, which will pass the message to the userErrorHandler VM channel if the payload is a Java exception.

If neither of these conditions is met, the message is handled by the pass-through router, which will output the item to the console's standard output device. If the matchAll attribute had been set, then all messages would be passed to the console.

Transformers

The Message Translator pattern[5] allows components to communicate with one another when each component uses different data formats. Mule does not impose a specific message format on you so you can take advantage of whatever format or formats make the most sense for your application.

Three different types of transformers can be used:

  • Type transformation involves converting the type of the message, for example converting a byte stream to a string or converting a JMS message to a Java object. The message is untouched but the type will change. Typically, these transformations are transport-specific and are available out of the box.

  • Message transformation involves converting the message itself; for example converting a single BookingRequest object into a corresponding AirlineTicket object. These transformations are very application-specific and would need to be coded intentionally. Mule provides a simple yet powerful framework to chain transformers together for multiple transformations.

  • Transformations involving the properties on a message where the message may contain properties, usually related to the transport used. For example, a message sent to an SMTP server would have "To," "From," and "CC" properties.

Transformers must be declared in a Mule configuration before they can be used. They will then be referred to by name, usually from within endpoints.

Each transformer can set the following attributes:

  • name is a name for the transformer and must be set. The best practice for naming transformers is to be descriptive enough to understand exactly what the transformer does, for example a transformer that converts a byte stream to a string should be named ByteStreamToString. When debugging or browsing the configuration it will be immediately obvious what this transformer is supposed to do.

  • returnClass allows you to specify a different return type to the one that the transformer returns. This is useful for typecasting, for example if your transformer returns a plain java.lang object class but you know that it would be a com.ricstonAirways.AirlineTicket class, you can specify that the transformer should return AirlineTicket objects rather than plain Java objects. Do note that if the data cannot be typecast, this will cause exceptions to be raised. This property is not required.

  • ignoreBadInput is a flag that allows you to control how a transformer is supposed to react when it receives some sort of data that it was not expecting. If it is set to true, any incorrect inbound data will be ignored and passed on to the next transformer (or service). If it is set to false, which is the default, any incorrect inbound data will cause an exception to be raised.

Additionally, custom transformers have a class attribute that lets you specify the fully-qualified class name for this transformer.

The examples here show two transformers. The first one is for a custom transformer. The second transformer has the ignoreBadInput attribute set to true and is one of the built-in transformers, ByteArrayToObject.

<custom-transformer name="StringToNameString"
   class="org.mule.samples.hello.StringToNameString"/>

<byte-array-to-object-transformer
   name="ByteArrayToObject" ignoreBadInput="true"/>

Complete Mule 2.0 Configuration File

We can put everything that we've covered so far together to make a usable Mule configuration, as shown here:

<mule xmlns=
   "http://www.mulesource.org/schema/mule/core/2.0"
xmlns:xsi=
   "http://www.w3.org/2001/XMLSchema-instance"
xmlns:spring=
   "http://www.springframework.org/schema/beans"
xmlns:http=
   "http://www.mulesource.org/schema/mule/http/2.0"
xmlns:vm=
   "http://www.mulesource.org/schema/mule/vm/2.0"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/
          springbeans-2.0.xsd
 http://www.mulesource.org/schema/mule/core/2.0
 http://www.mulesource.org/schema/mule/core/2.0/mule.xsd
 http://www.mulesource.org/schema/mule/vm/2.0
 http://www.mulesource.org/schema/mule/vm/2.0/
          mule-vm.xsd
 http://www.mulesource.org/schema/mule/http/2.0
 http://www.mulesource.org/schema/mule/http/2.0/
          mulehttp.xsd">
<custom-transformer name="StringToNameString"
     class="org.mule.samples.hello.StringToNameString"/>
   <custom-transformer name="HttpRequestToNameString"
     class=
      "org.mule.samples.hello.HttpRequestToNameString"/>

   <model name="helloSample">

      <service name="Greeter">

         <inbound>
            <inbound-endpoint
              address="http://localhost:8888"
              transformer-refs="HttpRequestToNameString"
              synchronous="true">
            </inbound-endpoint>
            <vm:inbound-endpoint path="greeter"
               transformer-refs="StringToNameString"
               synchronous="true"/>
         </inbound>

         <component
               class="org.mule.samples.hello.Greeter"/>

         <outbound>
            <filtering-router>
              <vm:outbound-endpoint path="chitchatter"/>
               <payload-type-filter expectedType=
                  "org.mule.samples.hello.NameString"/>
            </filtering-router>
            <filtering-router>
               <vm:outbound-endpoint
                  path="userErrorHandler"/>
               <payload-type-filter expectedType=
                  "java.lang.Exception"/>
            </filtering-router>
         </outbound>
</service>

   </model>

</mule>

Here's how it all comes together:

  1. First you see the initial namespace and schema declarations as well as the declaration of two transformers.

  2. This is followed by the declaration of the model and then a single service component that is called Greeter. The inbound HTTP and VM endpoints are included here.

  3. After the inbound router collection, we can see the declaration of the component itself. It points to one of the Mule samples.

  4. The outbound router collection follows the component declaration.

The service is complete, as is the model and the entire Mule configuration.

Summary

In summary, while the term ESB normally refers to messaging middleware, Mule extends this definition by adding many other features that it offers as a superset of the functionality offered by an ESB. Also, as you have started to see, Mule does not impose any specific platform or transport on you; it has been designed to work with your existing infrastructure. This is done by making everything pluggable and by having common services available within its central backbone (see Figure 1-6). For these reasons we prefer to think of Mule as an Enterprise Service Network. While Mule can be configured to use the traditional ESB topology, it can also be used for any other topology.

The Mule Services Backbone

Figure 1.6. The Mule Services Backbone

We also took a look at the various Mule elements and the standard integration patterns they are based on. They are all configured inside a Mule configuration file or inside a third-party design-time container, such as Spring. Following are the key elements that make up a Mule configuration file:

  • An XML namespace that determines the syntax of each XML tag

  • The connectors, transformers, and global endpoints that are predeclared and referred to by name from within the Mule model

  • Models that also contain the service components and their inbound and outbound router collections

  • Properties that are used to configure any obscure or generic items



[1] A full list of transports and the features they support is available on the MuleSource Wiki at http://mule.mulesource.org/x/CwKV.

[2] The transports that support transactions are documented at http://mule.mulesource.org/display/MULE2USER/Transaction+Management.

[3] Enterprise Integration Patterns: The Message Endpoint pattern (http://www.enterpriseintegrationpatterns.com/MessageEndpoint.html)

[4] Enterprise Integration Patterns: The Message Router pattern (http://www.enterpriseintegrationpatterns.com/MessageRouter.html)

[5] Enterprise Integration Patterns: The Message Translator pattern (http://www.enterpriseintegrationpatterns.com/MessageTranslator.html)

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset