Mule Architecture

Understanding the Mule Architecture

This section describes the different parts of the Mule architecture and how they handle messages and their data. For the sake of illustration, it uses the example of a company that needs to generate invoices for customer orders, perform some processing on those invoices, and then send them to the shipping department for order fulfillment.

Understanding the Messaging Framework

The advantage of networking your applications is that one application can send data to another application. However, many applications don't have the ability to read or process data coming from another application. Mule solves this problem by providing a messaging framework that reads, transforms, and sends data as messages between applications. A message is simply a packet of data that can be handled and sent between applications on a specific channel (also called a queue).

At the simplest level, when you connect applications to Mule, it reads data from one application, transforms it as needed so it can be read by the target application, and sends it to that application. This allows you to integrate all types of applications, even those that were not built to be integrated.

Mule is a messaging framework based on ideas from Enterprise Service Bus (ESB) architectures. The key advantage of an ESB is that it allows different applications to communicate with each other by acting as a transit system for carrying data between applications within your intranet or across the Internet. The heart of the system is the message bus, which routes messages between applications.

One difference between Mule and a traditional ESB is that Mule only converts data as needed. With a typical ESB, you have to create an adapter for every application you connect to the bus and convert the application's data into a single common messaging format. The development of these adapters and the time required to process every message requires a lot of time and effort. Mule eliminates the need for a single message format. The information is sent on any communication channel, such as HTTP or JMS, and is translated only as needed along the way. Therefore, Mule increases performance and reduces development time over a traditional ESB.

About SOA

Mule is based on the concept of a service-oriented architecture (SOA). The SOA approach to development allows IT organizations to create applications by bringing together components of application functionality, or services. Services are discrete sets of functionality that are completely separate from each other but can work together on the same objects. For example, if you need to process invoices, you might have one service that merges customer data from a database into the invoice and another service that checks the inventory database to see if the items on the invoice are in stock.

Because each service stands alone, services can be used as building blocks for multiple processes and do not have to be recreated for each type of process or message. For example, the service that merges customer data onto the invoice could also be used to merge customer data onto statements, letters, or other documents. This modular approach allows you to create functionality once and re-use it as many times as needed, streamlining development.

Using SOA, businesses can realize dramatic savings on development costs and can rapidly adapt to changing business conditions by reusing and reconfiguring existing services in developing new applications. SOA also enables better integration of enterprise IT resources, including previously isolated application silos and legacy systems. Mule fully supports the SOA approach and orchestrates communication among the services, allowing you to easily tie all these applications together.]

Processing the Data

When a message is sent from an application (such as the invoice from an order entry system), Mule picks up the message, sends it to a service that processes it using some specific business logic (such as checking the customer and inventory databases), and then routes it to the correct application (such as the order fulfillment system). Mule contains many individual parts that handle the processing and routing of the message. The key part of the service is the service component. The service component executes business logic on messages, such as reading the invoice object, adding information to it from the customer database, and then forwarding it to the order fulfillment application.

An important feature of the service component is that it doesn't have to have any Mule-specific code; it can simply be a POJO, Spring bean, Java bean, or web service containing the business logic for processing data in a specific way. Mule manages the service component, bundles it with configuration settings and exposes it as a service, and ensures that the right information is passed to and from it based on the settings you specified for the service in the Mule configuration file.

You can have many different service components that perform different business logic, such as one that verifies whether the items on the invoice are in stock and one that updates a separate customer database with the order history. The invoice, which is encapsulated in a message, can flow from one service component to the next until all the required processing is complete.

Routing Messages Between Service Components

As stated previously, the service component contains business logic for processing the data in the message. It does not contain any information about how to receive or send messages themselves. To ensure that the service component receives the right messages and routes them properly after processing, you specify an inbound router and an outbound router for the component's wrapping service when you are configuring Mule.

Inbound routers specify which messages the service component will process. They can filter incoming messages, aggregate them, and resequence them before routing them to a service component. For example, if a service component subscribes to an RSS feed, the inbound router could filter which messages it receives from that feed.

After a service component has processed a message, the outbound router specifies where to dispatch the message. For example, it might route invoices for in-state addresses to one shipping department and route all other invoices to another shipping department. You can define multiple inbound and outbound routing constraints and even chain routers together so that a service component receives and routes messages exactly as required.

Separating Business Logic from Messaging

One of the many advantages of Mule is that it can handle messages that are sent via a variety of protocols. For example, an invoice might always be in XML format, but it might arrive over HTTP in one situation and as a JMS message in another depending on which application created the invoice. If the service component handles only business logic and works with the data, not the message itself, how does it know how to read the various formats in which the message might arrive?

The answer is that service components don't know how to read the messages, because by default, service components are completely shielded from the message format. Instead, a transport carries the message along, and transformers change the message's payload (such as the invoice) as needed to a format the service component can read before the router passes the message to the service component. For example, if an XML invoice is sent over HTTP, the HTTP transport carries the message along, routers direct the message to each service component that needs to process it, and transformers change the invoice along the way (such as from XML to a Java object) as required by each service component. All the transporting, transforming, and routing of the message are completely transparent to the service component.

Transformers are the key to exchanging data, as they allow Mule to convert the data to a format that another component or application can understand. Most importantly, data is transformed only as needed. Instead of converting every message to a single common messaging format, messages and their data are transformed only as needed for the target component or application where the message is being sent. Lastly, you can use multiple types of transports to handle different channels, such as sending the message over HTTP and then forwarding it as a JMS message after it has been processed by the Customer Data service component.

The separation of the business logic from the sending and transformation of messages allows for great flexibility in how you set up your architecture and makes it much simpler to customize the business logic without having to worry about the various formats in which a message might arrive. Your service component can work with the raw data of the message if desired, but it is not required.

Wiring Everything Together

Endpoints are configuration elements that are the key to wiring together all the services. You specify endpoints in the inbound and outbound routers to tell Mule which transport to use, where to send messages, and which messages a service component should receive. The primary part of an endpoint is the address, expressed as a uniform resource indicator (URI), which indicates the transport to use, the location (a transport-specific resource), and any additional parameters.

For example, if a service's inbound router specifies the endpoint, the HTTP transport will dispatch to that service any messages that have been sent to that URL. If the inbound router specifies file://myserver/files/, the File transport, which is watching that directory, dispatches any new files created in that directory to the service. The endpoint you specify on the outbound router indicates where the message will go next--it goes to the service with the same inbound endpoint as the previous component's outbound endpoint, as shown in the following illustration.

A service can receive messages using different transports. For each type of transport that a service will use, you must specify one or more separate endpoints. For example, if you want one of your services to handle messages coming in on both the HTTP and JMS channels, you would specify at least one HTTP endpoint and at least one JMS endpoint in the inbound router for that service. Mule registers these endpoints with the service, and the transport uses this registry information at runtime to configure itself and determine where to send and receive messages.

The router or endpoint can include filters that further specify which messages to send or receive. For example, you can specify that the service component only receives RSS messages by a specific author. Specifying routers and endpoints for your services simply requires editing an XML file. You do not have to write any Java code. As stated previously, your service components code remains completely separate from messaging and routing, which you handle through Mule configuration.

In summary, Mule provides a simple and lightweight way to write service components that do something to data without needing to worry about the sender or recipient of the data, the format of the data, or the technology being used to send/receive the data. Although many brokering and integration technologies offer the ability to connect to disparate data sources, they often require extra coding to get messages to behave the way you want and to deliver the data where you want it to go. Mule allows you to quickly develop service components and then change the way they behave through simple XML configuration instead of writing Java code.

Understanding the Logical Data Flow

The previous sections introduced each of the parts of the Mule instance from a conceptual view point. Now, using the invoice example again, let's take a look at how data flows logically through each part of a Mule instance. Throughout the process, Mule uses the Mule configuration file to determine which components, routers, transports, and transformers to use along the way. The diagram that follows illustrates these steps.