Top Banner
20

.VMF &4# 5VUPSJBM

Jan 02, 2022

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: .VMF &4# 5VUPSJBM

Mule ESB 3 Tutorial

Page 2: .VMF &4# 5VUPSJBM

1. Home . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1 Creating an Application Using the Mule IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Creating an Application Using Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.3 Creating a Configuration File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.4 Testing Your Mule Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.5 Introducing Message Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.6 Understanding Advanced Message Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Page 3: .VMF &4# 5VUPSJBM

1.

Home

Mule ESB 3 TutorialThis book provides a tutorial on how to develop Mule ESB 3 applications. It covers the essentials, such as using the Mule IDE, writing aconfiguration file, routing messages, and testing your application. It also covers advanced topics such as developing Mule applications usingMaven and using advanced message routing.

Using the Mule IDE

If you're curious about how to use the Mule IDE, this topic will help you get started with this tool.

Working with Maven

Maven can help you develop Mule applications, so if you are ready to plunge into this new world, this topic is a must-read.

Creating Configuration Files

Creating configuration files is at the heart of Mule development. Read this topic to learn the basics of how to do this.

How to Test Your Application

Testing is part and parcel of application development. Learn the Mule approach to testing here.

Message Routing

If you are ready to start moving data around your Mule application, this topic will help you understand the basics.

Advanced Message Routing

Routing messages can get complicated. Read this topic to learn some of the deeper, lesser-known methods of message routing with Mule.

Creating an Application Using the Mule IDE

Creating an Application Using the Mule IDE[ ] [ ] [ ] [ ] [ Create the Application Run the Application Create a Configuration File for the New Application Use Eclipse Tools for Adding Elements

]Package and Deploy the JAR and Configuration File

The simplest way to create an application in Mule ESB is to use the with . The Mule IDE allows you to quickly start a new project,Mule IDE Eclipsewhich you can base on one of the existing examples, or just create a new configuration file by selecting the transports you want to use. Thislesson walks you through creating a new application called myHelloApp, which will be based on the , running the application,Hello World Exampleand creating a new configuration file for the project.

Mule IDE 2.1 is required to support Mule 3 but Mule 3's new Application Model and Hot Deployment capabilities are not yetnatively supported by the Mule IDE. If you would like to use the Mule IDE with these features, please see the documentation on

.Hot Deployment using the Mule IDE

Create the Application

Page 4: .VMF &4# 5VUPSJBM

1. 2. 3. 4.

1. 2.

1. 2.

1. 2. 3.

4.

In Eclipse Workbench, choose , expand the Mule folder and select , and then click .File > New > Project Mule Project NextEnter the name , ensuring that there is no space in the project name.myHelloAppEnsure that Mule 3 is your default Mule distribution or selected as the project specific one.Click and select the Hello example.Add sample project content

Click , and then click the Libraries tab and verify that the Java 5 or later library is installed and available on the build path.NextClick to have the Mule IDE generate your project.Finish

You will now see the myHelloApp project in the navigation pane on the left. You can expand its folders to see the source code, configuration files,and more. Let's run the application to see it in action.

Run the Application

In the Package Explorer, expand the directory, and right-click the configuration file.src/main/app mule-config.xmlChoose .Run As > Mule Server

A new run configuration is created automatically and the server is started. The application runs, initializing Mule. After the Mule splash screenappears in the console window, open a web browser with this url:

http://localhost:8888?name=Ross

The server should respond with "Hello Ross, how are you?" If you get any other response, check the log in the console window for any errors.

Create a Configuration File for the New Application

Now let's create a new configuration file for the myHelloApp. Instead of using the HTTP and Servlet transports and a browser to interact with theapplication, let's change the configuration to use the System I/O (also called ) and transports. For simplicity, we'll call the newSTDIO VMconfiguration file .my-hello-config.xml

Choose , expand the Mule folder and select , and then click .File > New > Other Mule Configuration NextClick , expand the myHelloApp project, select the directory, and then click .Browse... src/main/app OKChange the default name from to . You can use any name you like, as long as it is uniquemule-config.xml my-hello-config.xmlwithin the project and has an extension. If you use the name of an existing file, it will overwrite that file..xmlSelect the System I/O (also called STDIO) and VM transports, leave Spring Config selected, and then click .Finish

Page 5: .VMF &4# 5VUPSJBM

Mule IDE creates the configuration file in the directory of the myHelloApp project. It adds the namespaces for the STDIO and VMsrc/main/apptransports.

Use Eclipse Tools for Adding Elements

Now we'll use the Eclipse tools to add elements to the new configuration file.

Open the new configuration file in the Eclipse editor. You can add global elements anywhere below the namespace declarations, which are at thetop of the file. You can add services within a element, and then add local routers, filters, endpoints, and transformers to the services.<model>

Eclipse provides a fast and error-proof method for entering these elements. Simply click anywhere between the opening and closing tags of anelement, then press to see a list of the available elements. Double-click the element in the list that you want, and Eclipse enters theCtrl+spaceopening and closing tags for that element. You can also hover over a tag to see a description of the element and its supported attributes.

To add System I/O so that you can interact with the application from the console, copy the body (the content below the namespace declarations)of the default example configuration to your new configuration file. Then make the following changes.mule-config.xml

Add a connector configuration and declare another custom transformer for STDIN:

<stdio:connector name="SystemStreamConnector" promptMessageCode="3" resourceBundle="messages.hello-example-messages" messageDelayTime= />"1000"

<custom-transformer name= class= />"StdinToNameString" "org.mule.example.hello.StdinToNameString"

Append or replace the http and servlet inbound endpoints in the Hello World flow with a stdio one (if you append it, make sure you also declarethe applicable namespaces for http and servlet transports):

<stdio:inbound-endpoint system= exchange-pattern= >"IN" "one-way" <transformer ref = />"StdinToNameString"</stdio:inbound-endpoint>

Page 6: .VMF &4# 5VUPSJBM

Add a stdio outbound endpoint to the Hello World flow between the choice element and the default exception strategy:

<stdio:outbound-endpoint system= exchange-pattern= >"OUT" "one-way" <transformer ref= />"ChatStringToString"</stdio:outbound-endpoint>

Package and Deploy the JAR and Configuration File

After you have finished creating your Mule application, you can deploy it by packaging up the application in a JAR file and then copying the JARand configuration file to your Mule instance(s). Since the Mule IDE does not yet natively support the new deployment structure of Mule 3, you willneed to do the packaging manually to conform to the . Alternatively, you can follow the instructions for Mule application format Hot Deployment

.using the Mule IDE

Creating an Application Using Maven

Creating an Application Using Maven[ ] [ ]Create a New Project Build the Application

Mule's integrated support for the Maven project management tool means that you can quickly and easily create a new Mule project right from thecommand line. This lesson walks you through creating a new application called myHelloApp, which will be based on the ,Hello World Examplerunning the application, and creating a new configuration file for the project.

For information on downloading, installing and setting up Maven with Mule, see and .Setting Up the Development Environment Using Maven

Maven 3.0 (beta) is not currently supported with Mule. Maven 2.0.x and 2.2.x are the recommended versions to use with Mule.

Mule provides a Maven archetype (project wizard) for creating new Mule projects. Before you can use it, you must sdd the following to the file (usually in your Maven or directory) so that Maven will allow you to execute Mule plug-ins.settings.xml conf $HOME/.m2

settings.xml

<settings> <pluginGroups> org.mule.tools<pluginGroup> </pluginGroup> </pluginGroups> ...</settings>

Create a New Project

We are going to create a new project called 'myHelloApp'. Navigate to the parent directory where you want to create this new project. Next, youwill execute the archetype and generate the code. If this is your first time running this command, Maven will download the archetype for you.

> mvn mule-project-archetype:create -DartifactId=myHelloApp -DmuleVersion=3.0.0

The wizard will ask you a number of questions. For an explanation of these see the .project archetype documentation

Enter org/mule/example as the Java package path.

org/mule/example

When you get to the transports question, please specify the http and vm tranports.

http,vm

Page 7: .VMF &4# 5VUPSJBM

Next, it will ask you which modules to include. Please enter at least one module name (note this is a limitation of the archetype, you must specifyat least one item). Maven will now create a skeleton project structure for you.

You can now browse the myHelloApp project structure. It should look like this:

myHelloApp--assembly.xml--pom.xml--MULE-README.txt--src/main --resources/mule-config.xml --java/org/mule/example/myhelloapp--src/test --resources/myhelloapp-functiona-test-config.xml --java/org/mule/example/myhelloapp/MyHelloAppTestCase.java

Build the Application

mvn package

This will build your project, run the tests, and construct a mule application archive named myhelloapp-1.0-SNAPSHOT.zip. Now just copy thisarchive to you {$MULE_HOME/apps} directory and start mule - {$MULE_HOME/bin/mule}. Mule will detect your application archive andautomatically deploy it. If there are any errors in your configuration you will need to correct the, repackage and copy the archive over again.

To deploy your application to additional Mule instances, you can repeat the last two steps for each instance.

Creating a Configuration File

Creating a Configuration File[ ] [ ] [ ] [ ] [ Add the XML Declaration and Namespaces Add the Description Configure Global Connectors Configure Global Custom Transformers

] [ ] [ ] [ ] [ ]Configure Models and Services Configure Error Handling Configure the Final Service View the Full Example Run the Application

Creating a Mule ESB application is as simple as creating a configuration file and pointing to a Java class that performs any required custom logicon the messages that come through. Although the easiest way to create a Mule configuration file is to use the Mule IDE as described in Creating

, Lesson Three provides you with the information you need to create the file manually in any XML editor or IDEan Application Using the Mule IDEand helps you understand all the elements involved. You will walk through creating a configuration file for the Hello World application. You canthen run Mule using this file and the compiled Java classes.

To get started, create an empty Mule Project using the Mule IDE or Maven project archetype and open a new, empty mule-config.xml file in yourfavorite editor.

Add the XML Declaration and Namespaces

First, the XML declaration goes at the top of the file:

<?xml version= encoding= ?>"1.0" "UTF-8"

Next, in the element, you declare the namespace for the core Mule schema, XSI, Spring, and the transports and modules you want to<mule>use. In this example, we're using the HTTP and VM transports. You then use the XSI namespace to declare the locations of the schemas. Forexample:

Page 8: .VMF &4# 5VUPSJBM

<mule xmlns="http://www.mulesoft.org/schema/mule/core" =xmlns:xsi "http://www.w3.org/2001/XMLSchema-instance" =xmlns:spring "http://www.springframework.org/schema/beans" =xmlns:http "http://www.mulesoft.org/schema/mule/http" =xmlns:vm "http://www.mulesoft.org/schema/mule/vm" xsi:schemaLocation=" http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.0/mule.xsd http://www.mulesoft.org/schema/mule/httphttp://www.mulesoft.org/schema/mule/http/3.0/mule-http.xsd http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/3.0/mule-vm.xsd http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

The HTTP transport will allow a user to interact with the application using any http client, including a web browser.

Add the Description

Optionally, you can add the element with a description of this configuration file. If you are creating only one configuration file for<description>your entire application, the description could be about the entire application.

The Hello World sample application has two components:<description> 1. The Greeter component that adds a greeting to the message it receives 2. The ChitChatter component that adds some additional conversation to the message it receives A message is triggered by input through an http endpoint and the outbound message is also written out through the http response. This configuration also demonstrates user and system error handling. User error handling returns an error message to the end user. System error handling logs errors. </description>

Configure Global Connectors

While there are several ways in Mule to , the best practice is to use the element to define a global connectorconfigure a transport <connector>configuration, which you can then reference in multiple places. The element must be prefixed by the namespace of its transport.<connector>For example, the following connector will be available to endpoints that use the :STDIO transport

<stdio:connector name="SystemStreamConnector" promptMessageCode="3" resourceBundle="messages.hello-example-messages" messageDelayTime= />"1000"

The example does not use the STDIO transport, so you do not need to add the above connector to your configuration.

Because we have only one connector defined for the STDIO transport, this connector will be used by default whenever we create an STDIOtransport. If we defined multiple STDIO connectors, you would use the attribute on the endpoint to specify the one you want toconnector-refuse.

To see which attributes you can set for a connector, go to the transport's reference page by clicking its name on the page.Available Transports

Configure Global Custom Transformers

Similarly, if you want to configure that you can reference from multiple places, add them to the configuration now.custom transformers

Because we're going to send the string through HTTP, we need a transformer that will convert it from an HTTP request to a name string. TheHello World example includes a Java class that performs this transformation, which you configure as follows:

Page 9: .VMF &4# 5VUPSJBM

<custom-transformer name= class="HttpRequestToNameString"/>"org.mule.example.myhelloapp.HttpRequestToNameString"

It also uses several other transformers that format the message payload and convert it to the datatype expected by each component:

<custom-transformer name= class="StringToNameString"/>"org.mule.example.myhelloapp.StringToNameString"

<custom-transformer name= class="NameStringToChatString"/>"org.mule.example.myhelloapp.NameStringToChatString"

<custom-transformer name= class="ChatStringToString"/>"org.mule.example.myhelloapp.ChatStringToString"

<custom-transformer name= class="ExceptionToString" "org.mule.example.myhelloapp.ExceptionToString"/>

Go ahead and add all of the above transformer declarations to your mule configuration after the <description> element.

Configure Models and Services

You are now ready to add your , which is where you specify your that do the actual work. Services are contained within services components, so you add the tag first:models <model>

<model name= >"myHelloApp" ...services will go here

Now, start by adding tags with a attribute that contains a unique name for the service. The Helloconfiguring your services <service> nameWorld example has four services, each of which has an section, a , and an section in that order. For<inbound> <component> <outbound>details on the elements you can configure in a service, see the .Service Configuration Reference

Configure the Inbound Section

Let's add the inbound section for the GreeterUMO service first:

<service name= >"GreeterUMO" <inbound> <inbound-endpoint address= transformer-refs="http://localhost:8888" "HttpRequestToNameString"exchange-pattern= >"request-response" <not-filter> <wildcard-filter pattern= />"/favicon.ico" </not-filter> </inbound-endpoint> </inbound>

Notice that within the inbound section, we've specified the inbound endpoint. The inbound endpoint defines which messages this service willhandle by specifying the following:

The transport. In this case, it's HTTP.Where the message originates. In this case, it's can receive messages using standard HTTP GET request.http://localhost:8888The transformer to use. Here we reference one of the global transformers we defined earlier in the configuration. that will convert theHTTP request to a NameString object.No connector is referenced so the default HTTP connector will be used.The exchange pattern to follow. HTTP expects a synchronous response, so we specify the request-response pattern.

This inbound endpoint specifies that only messages that are received on will be received by this service, and they will behttp://localhost:8888transformed by the HttpRequestToNameString transformer before they are passed to the component. A filter is configured to explicitly excludeany request for the favicon.ico from being processed by the service. There is no specified, so all messages received on thisinbound routerendpoint will be processed by the service.

Configure the Component

Page 10: .VMF &4# 5VUPSJBM

The component is the next element to configure. The component can be a plain Java class, Spring Bean, JSR-223 script, web service, oranything that can perform logic on the messages.

In this example, our component is a POJO, so you specify the class in the tag:<component>

<component class= />"org.mule.example.myhelloapp.Greeter"

By default, Mule automatically discovers the correct method in the Java class to execute (the ) by matching the return type on theentry pointtransformer (in this case, NameString) to the methods in the component. For information on other ways of resolving the entry point, see Entry

.Point

The code for the Greeter component is below.

org.mule.example.myhelloapp;package

/** * <code>Greeter</code> expects a valid <code>NameString</code> object. If invalid, * an exception is created and returned. The outbound router will filter exceptions * as user errors and the messages to the original requester accordingly.return */

class Greeterpublic{ greeting = "";private String

Greeter()public { greeting = LocaleMessage.getGreetingPart1(); }

greet(NameString person)public Object { payload = person;Object (person.isValid())if { person.setGreeting(greeting); } else { payload = Exception(LocaleMessage.getInvalidUserNameError());new } payload;return }}

Configure the Outbound Section

Now we need to specify what the service will do after the component has finished with it. We specify this in the outbound section. In this case, wewant to use an to send the message to one service if the message was processed successfully and to a different service if theoutbound routermessage had errors. To do this, we use , each of which specifies a) the outbound endpoint where the message will go next, and b)filtering routersthe criteria the message must meet to be routed there. If a message does not meet the criteria of the first router, it's checked against the secondrouter's criteria, and so on until there's a match.

<outbound> <filtering-router> <vm:outbound-endpoint path= exchange-pattern= />"chitchatter" "request-response" <payload-type-filter expectedType= />"org.mule.example.myhelloapp.NameString" </filtering-router> <filtering-router> <vm:outbound-endpoint path= exchange-pattern= />"userErrorHandler" "request-response" <payload-type-filter expectedType= />"java.lang.Exception" </filtering-router></outbound>

Page 11: .VMF &4# 5VUPSJBM

In this case, if the message payload was transformed correctly into a NameString object, the first router sends it to the path usingchitchatterthe VM transport. VM is an internal messaging service that routes messages between services running inside the same JVM for fasterprocessing. If you deploy your services on separate Mule instances instead, you could easily replace this with a JMS provider. If the message wasnot transformed correctly and the payload contains an exception, the message is routed to the path using the VM transport.userErrorHandlerWhen you configure the services that will handle the message in each of these cases, you must ensure that they specify or chitchatter

as the path on their inbound endpoints.userErrorHandler

Configure Error Handling

Mule provides support for for unexpected errors. Exception strategies allow you to handle messages when there is a system error:error handling

<!-- Route unexpected errors to separate error handler --><default-service-exception-strategy> <vm:outbound-endpoint path= exchange-pattern= />"systemErrorHandler" "one-way"</default-service-exception-strategy></service>

In the Hello World example, user errors are routed back to the caller and system errors are routed to system.err. These error-handling servicesare defined below:

<!-- This error handler returns user error messages to caller. Errors could also be routed elsewhere, e.g. into an error file, send via email to a list, stored in a database, etc. --><service name= >"UserErrorHandler" <inbound> <vm:inbound-endpoint path= responseTransformer-refs="userErrorHandler" "ExceptionToString"exchange-pattern= />"request-response" </inbound></service>

The UserErrorHandler just transforms the message using the response transformer and returns it to the caller.

<!-- Handle any unexpected errors. Errors could also be routed elsewhere, e.g. into an error file, send via email to a list, stored in a database, etc. --><flow name= >"SystemErrorHandler" <vm:inbound-endpoint path= exchange-pattern= />"systemErrorHandler" "request-response" <outbound-endpoint address= exchange-pattern= />"stdio://ERR" "one-way"</flow>

The SystemErrorHandler uses a new construct in Mule 3 called <flow>. Flow-based configuration allows a more flexible model than service andcan be useful for processing messages where the service-based model is not required. In this case, there is no component or outbound router,just an inbound and outbound endpoint that re-routes all messages to STDERR.

Configure the Final Service

There is one last service in the example: the ChitChat service. This service transforms the message, adds text to it and returns it to the caller.Again, we use the simpler flow construct to specify the inbound endpoint and component. In this case there is no outbound. Instead of using anoutbound endpoint, we're simply going to configure a response transformer, which will transform the string after the component is done with it andsend it back to the caller, namely the HTTP endpoint. Therefore, you add the response transformer and declare the request-response exchangepattern.

<flow name= >"ChitChat" <vm:inbound-endpoint path= transformer-refs= "chitchatter" "NameStringToChatString" responseTransformer-refs= exchange-pattern= />"ChatStringToString" "request-response" <component class= />"org.mule.example.myhelloapp.ChitChatter"</flow>

The code for the ChitChatter component is below:

Page 12: .VMF &4# 5VUPSJBM

1.

org.mule.example.myhelloapp;package

class ChitChatterpublic{ chitchat = "";private String

ChitChatter()public { chitchat = LocaleMessage.getGreetingPart2(); }

void chat(ChatString string)public { string.append(chitchat); }

}

Lastly, end the file with the closing and tags:</model> </mule>

... </model></mule>

View the Full Example

To see the entire configuration file and source code for this example, navigate to the directory under your Mule homeexamples/hello/srcdirectory or create a new project from the Hello World example using the Mule IDE (See ). TheCreating an Application Using the Mule IDEconfiguration file is included in and the custom classes referenced in the configuration file are included withexamples/hello/src/main/appsthe example under the directory.examples/hello/src/main/java

Run the Application

To run the application, the custom classes must be compiled and the entire application packaged into a Mule application archive. Follow thedirections in (Mule IDE) or (Maven) to package and deploy yourCreating an Application Using the Mule IDE Creating an Application Using Mavenapplication to Mule.

Testing Your Mule Application

Testing Your Mule Application[ ] [ ] [ ] [ ]Test the Application Create an HTML Interface Unit Test Cases Functional Test Case

This lesson builds on and shows you how to test the Hello World example using a web page and Mule's functionalCreating a Configuration Filetest framework.

Test the Application

It's time to test the application. This assumes you previously packaged and deployed the application to Mule.

Open a web browser and enter the URL .http://localhost:8888/?name=Ross

This URL passed "Ross" to the endpoint , which was picked up and processed by the GreeterUMO service. It thenhttp://localhost:8888passed the message to the ChitChat service for processing, which sent it back to the calling endpoint, where it was displayed in the web browser.

Create an HTML Interface

Because it's unlikely that users would enter their names as part of a URL string, you could create an HTML page that prompts users for their

Page 13: .VMF &4# 5VUPSJBM

names and submits it via a form. For example, create a simple page with the following code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"

<html xmlns= xml:lang= lang= >"http://www.w3.org/1999/xhtml" "en" "en" <head> Get Name<title> </title> </head> <body> <form method= action= >"GET" "http://localhost:8888" <input type= name= />"text" "name" <input type= value= />"submit" "Submit Name" </form><br /> </body></html>

Now, with the Hello World application still running, launch this HTML page in a web browser. It should look like this:

Enter your name, and then click . It displays the greeting with yourSubmit Namename.

Unit Test Cases

Most custom objects in Mule are POJOs, so unit testing is easy. If you examine the test cases in the Hello World example, you'll see how thevarious components and transformers are easily tested with standard unit tests.

Functional Test Case

Because Mule ESB is light-weight and embeddable, it is easy to run an entire Mule Server inside a test case. Mule provides an abstract JUnit testcase called org.mule.tck.FunctionalTestCase that runs Mule inside a test case and manages the lifecycle of the server. Theorg.mule.tck.functional package contains a number of supporting classes for functionally testing Mule code, including FunctionalTestComponent.More detail on Functional Testing with Mule can be found in the .documentation

This means, a test case can be used to test a flow. If you used the Maven archetype to create your project, then you already have a skeleton testcase and configuration file. The test case looks like this:

org.mule.example.myhelloapp;package

org.mule.api.MuleMessage;import org.mule.module.client.MuleClient;import org.mule.tck.FunctionalTestCase;import org.mule.transport.NullPayload;import

class MyHelloAppTestCase FunctionalTestCasepublic extends{ getConfigResources()protected String { //TODO You'll need to edit file to make the test applicable to your modulethis

;return "myhelloapp-functional-test-config.xml" }

void testMyHelloApp() Exceptionpublic throws { MuleClient client = MuleClient(muleContext);new MuleMessage result = client.send("vm: , , );//in" "some data" nullassertNotNull(result); assertNull(result.getExceptionPayload()); assertFalse(result.getPayload() NullPayload);instanceof

//TODO Assert the correct data has been receivedassertEquals( , result.getPayloadAsString());"some data Received" }}

Page 14: .VMF &4# 5VUPSJBM

First replace the generated configuration file with the one you created for the application. We will now include an inbound VM endpoint which we'lluse to test the application. Add the following to the inbound element of your GreeterUMO service in the test configuration:

<vm:inbound-endpoint path= transformer-refs= exchange-pattern="greeter" "StringToNameString"/>"request-response"

Now let's modify the test case to call this endpoint and assert the result:

void testMyHelloApp() Exceptionpublic throws { MuleClient client = MuleClient(muleContext);new MuleMessage result = client.send("vm: , , );//greeter" "Ross" nullassertNotNull(result); assertNull(result.getExceptionPayload()); assertFalse(result.getPayload() NullPayload);instanceof

//TODO Assert the correct data has been receivedassertEquals( , result.getPayloadAsString());"Hello Ross, how are you?" }

That's it. If you execute the test case it should pass.

This simple example assumes the English locale and is not testing for different locales. If you are in a different locale, you willneed to modify the verification string to match the one created for your locale.

For more information on all topics related to configuring and using Mule, see the (login required).Mule User's Guide

Introducing Message Routing

Introducing Message Routing[ ] [ ] [ ]Overview Selecting a Message Style Summary

This lesson provides an introduction to message routing and describes when to use the different message styles.

Overview

Message routers control how messages are routed among the services in your Mule ESB application. Following is a description of the keyconcepts:

Inbound routers control how a service handles incoming messages, such as selectively consuming only those messages that meetspecific criteria or grouping messages together that share a group ID before forwarding them on.

Outbound routers control how a message is dispatched after the service has processed it, such as sending it to a list of recipients orsplitting up the message and sending the parts to different endpoints.

Asynchronous reply routers are used in request/response scenarios where message traffic is triggered by a request and the trafficneeds to be consolidated before a response is given. The classic example of this is where a request is made and tasks are executed inparallel. Each task must finish executing and the results processed before a response can be sent back.

Catch-all strategies are invoked if no routing path can be found for the current message. An inbound or outbound endpoint can beassociated with a catch-all strategy so that any orphaned messages can be caught and routed to a common location.

Filters provide the logic used to invoke a particular router. Filters can be combined using the logic filters AndFilter, OrFilter, and NotFilter.Not all routers need to use filters, but all routers support them.

Selecting a Message Style

When wiring your Mule services together, new users sometimes get confused about when to use an outbound router and when it's sufficient tosimply get a reply. The exchange-pattern attribute in Mule is how you explicitly define the message style you want. It is important to know that

Page 15: .VMF &4# 5VUPSJBM

each transport has a default exchange pattern that will be enforced if you do not specify one. Following is a description of the message styles youcan use in Mule.

Asynchronous

If you simply want to put a message on a SEDA queue after processing it, and no response to the caller is required, you can use theasynchronous message style as defined by the one-way exchange pattern. You should specify this on both the inbound and outbound endpoints.

For example:

<model name= >"Asynchronous_Message_Pattern" <service name= >"AsynchronousService"

<inbound> <jms:inbound-endpoint queue= exchange-pattern= />"test.in" "one-way" </inbound>

<component class= />"org.myorg.WidgetHandler"

<outbound> <pass-through-router> <jms:outbound-endpoint queue= exchange-pattern= >"test.out" "one-way" <pass-through-router> </outbound>

</service></model>

Request-Response

In simple scenarios that require a response, a service receives a request on a synchronous inbound endpoint, processes the request, and thensends it back to the caller as a reply. For example, if a user enters a value in an HTML form, and you want to transform that value and display theresults in the same page, you can simply configure a synchronous inbound endpoint on the service that does the transformation. This scenariodoes not use an outbound router. This is the message style and is defined using the request-response exchange pattern. request-response

For example:

<model name= >"Request-Response_Message_Pattern" <service name= >"SynchronousService"

<inbound> <http:inbound-endpoint host= port= path= exchange-pattern="localhost" "8080" "/mule/services"

/>"request-response" </inbound>

<component class= />"org.myorg.WidgetHandler"

</service></model>

Synchronous

If you need to pass the message to a second service for additional processing, you would configure an outbound router on the first service to passthe message to the second service. After the second service processes the message, the first service sends it back to the caller as a reply. This isthe message style To enable this you would put the request-response exchange pattern on both the inbound and outboundsynchronousendpoints.

For example:

Page 16: .VMF &4# 5VUPSJBM

<model name= >"Synchronous_Message_Pattern" <service name= >"SynchronousService" <inbound> <jms:inbound-endpoint queue= exchange-pattern= />"test.in" "request-response" </inbound>

<component class= />"org.myorg.WidgetHandler"

<outbound> <chaining-router> <jms:outbound-endpoint queue= exchange-pattern= />"test.out" "request-response" </chaining-router> </outbound> </service>

<service> <inbound> <jms:inbound-endpoint queue= exchange-pattern= />"test.out" "request-response" </inbound>

<component class= />"org.myorg.WidgetPackager"

</service></model>

Asynchronous Request-Response

In the most complex scenario, you can enable request-response messaging and allow the back-end process to be forked to invoke other services,returning a reply asynchronously based on the results of multiple service invocations. You can set the inbound endpoint's exchange-patternattribute to one-way, since the response will be handled by the asynchronous reply router, unless you also want to send a response to the caller.This is the message style. asynchronous request-response

In the followingexample, a requestcomes in on an HTTPendpoint, is broadcastto two endpoints usingthe Multicast router,and the results are sentasynchronously to aJMS endpoint.

Page 17: .VMF &4# 5VUPSJBM

<model name= >"Async_Request-Response_Message_Pattern" <service name= >"AsyncRequestResponseService" <inbound> <http:inbound-endpoint host= port= path= exchange-pattern="localhost" "8080" "/mule/services"

/>"one-way" </inbound>

<component class= />"org.myorg.WidgetHandler"

<async-reply timeout= >"5000" <collection-async-reply-router/> <jms:inbound-endpoint queue= exchange-pattern= />"reply.queue" "one-way" </async-reply>

<outbound> <multicasting-router> <reply-to address= />"jms://reply.queue" <jms:outbound-endpoint queue= exchange-pattern= />"service1" "one-way" <jms:outbound-endpoint queue= exchange-pattern= />"service2" "one-way" </multicasting-router> </outbound> </service></model>

Summary

This section described the different message styles you can use. For complete information, see in the Mule User'sService Messaging StylesGuide.

Now that you understand which message styles to use for routing in different scenarios, describesUnderstanding Advanced Message Routingseveral routers you can use for achieving finer control over message routing.

Understanding Advanced Message Routing

Understanding Advanced Message Routing[ ] [ ] [ ] [ ]Filtering Messages Chaining Outbound Endpoints Together Splitting Messages Processing a Message Only Once

This lesson builds on and shows you how to use specific message routers to control how a message is routedIntroducing Message Routingthrough your application.

Filtering Messages

You can control which messages a service handles by using filters. The works on inbound endpoints to controlSelective Consumer Routerwhich messages that service will process. The works on outbound endpoints to control which messages the service sends alongFiltering Routerto the next endpoint. You can use a combination of these approaches to control the message flow.

For example, if you only want to process messages that don't have errors, you can use a selective consumer to ensure that only those with theresult code "success" are processed. You can then use a to forward all other messages to another endpoint for error handling:Catch-all Strategy

Page 18: .VMF &4# 5VUPSJBM

<inbound>

<selective-consumer-router> <mulexml:jxpath-filter expression= />"msg/header/resultcode = 'success'" </selective-consumer-router>

<forwarding-catch-all-strategy> <jms:endpoint topic= exchange-pattern= />"error.topic" "one-way" </forwarding-catch-all-strategy>

</inbound>

If you want the service to process all messages but then want to specify criteria to determine where the message is sent next, you can usefiltering outbound routers. In the following example, messages that contain an exception are sent to the system administrator's email address,messages whose payload contains a specific string are sent to the string queue, and all other messages are picked up by the forwarding catch-allrouter and sent to an error queue:

<outbound>

<forwarding-catch-all-strategy> <jms:outbound-endpoint queue= exchange-pattern= />"error.queue" "one-way" </forwarding-catch-all-strategy>

<filtering-router> <smtp:outbound-endpoint to= exchange-pattern= />"[email protected]" "one-way" <payload-type-filter expectedType= />"java.lang.Exception" </filtering-router>

<filtering-router> <jms:outbound-endpoint queue= exchange-pattern= />"string.queue" "one-way" <and-filter> <payload-type-filter expectedType= />"java.lang.String" <regex-filter pattern= />"the quick brown (.*)" </and-filter> </filtering-router>

</outbound>

Similar routers are the , which allows you to process some messages and selectively forward others, and the ,forwarding router wiretap routerwhich allows you to process all messages and send them on as normal but also send a copy to another endpoint. For more information, see

in the Mule User's Guide.Inbound Routers

Chaining Outbound Endpoints Together

Let's assume we have a validation service, and if the message fails validation, the message and its exception are forwarded to another serviceAND the message and its exception are returned to the caller. You could achieve this using the , which is a fast and lightweightchaining routerconfiguration for sending a message to an endpoint and then sending the result of that endpoint to another endpoint. For example:

<chaining-router>

<vm:outbound-endpoint path= exchange-pattern= />"ValidationService" "request-response"

<vm:outbound-endpoint path= exchange-pattern= >"ValidationError" "request-response" <exception-type-filter expectedType= />"java.lang.Exception" </vm:outbound-endpoint>

</chaining-router>

You can also use the chaining router to perform protocol bridging to a single outbound endpoint. Unlike the pass-through router, the chainingrouter always returns a response. For example:

Page 19: .VMF &4# 5VUPSJBM

<service name= >"HttpProxyService"

<inbound> <!-- WSDL URL: http://localhost:8888/stockquote.asmx?wsdl --> <inbound-endpoint address= exchange-pattern= />"http://localhost:8888" "request-response" </inbound>

<outbound> <chaining-router> <outbound-endpoint address= "http://www.webservicex.net#\[header:http.request\]"exchange-pattern= />"request-response" </chaining-router> </outbound>

</service>

Splitting Messages

A message splitter can be used to break down an outgoing message into parts and dispatch those parts over different endpoints configured onthe router. For example, in an order-processing application, you might want to send different parts of the message to different services forprocessing. You could do this using one of the following routers:

List Message Splitter: accepts a list of objects that will be routed to different endpoints. For example:

<outbound>

<list-message-splitter-router">

<jms:outbound-endpoint queue= exchange-pattern= >"order.queue" "one-way" <payload-type-filter expectedType= />"com.foo.Order" </jms:outbound-endpoint>

<jms:outbound-endpoint queue= exchange-pattern= >"item.queue" "one-way" <payload-type-filter expectedType= />"com.foo.Item" </jms:outbound-endpoint>

</list-message-splitter-router>

</outbound>

Filtering XML Message Splitter: similar to the List Message Splitter but operates on XML documents. For example:

<outbound>

<mulexml:filter-based-splitter splitExpression= validateSchema="root/nodes" "true"externalSchemaLocation= >"/com/example/TheSchema.xsd"

<vm:outbound-endpoint path= exchange-pattern= >"order" "one-way" <payload-type-filter expectedType= />"com.foo.Order" </vm:outbound-endpoint>

<vm:outbound-endpoint path= exchange-pattern= >"item" "one-way" <payload-type-filter expectedType= />"com.foo.Item" </vm:outbound-endpoint>

</mulexml:filter-based-splitter>

</outbound>

Expression Splitter Router: similar to the List Message Splitter but splits the message based on an expression that returns one or moremessage parts. For example:

Page 20: .VMF &4# 5VUPSJBM

<outbound>

<expression-splitter-router evaluator= expression= "xpath" "/mule:mule/mule:model/mule:service"disableRoundRobin= failIfNoMatch= >"true" "false"

<outbound-endpoint ref= >"service1" <expression-filter evaluator= expression= />"xpath" "/mule:service/@name = 'service splitter'" </outbound-endpoint>

<outbound-endpoint ref= >"service2" <expression-filter evaluator= expression="xpath" "/mule:service/@name = 'round robin

/>deterministic'" </outbound-endpoint>

</expression-splitter-router>

</outbound>

You could also split a message into parts to improve performance. The splits the message into parts and sendsRound Robin Message Splitterthem to endpoints in a round-robin approach. The splits a single message into a number of fixed-length messagesMessage Chunking Routerthat will all be routed to the same endpoint.

After splitting messages, you use the to aggregate the message parts back together again. The aggregatorMessage Chunking Aggregatoruses the correlation ID, which is set by the outbound router, to identify which parts belong to the same message.

<inbound>

<message-chunking-aggregator-router> <expression-message-info-mapping correlationIdExpression= />"#[header:correlation]" <payload-type-filter expectedType= />"org.foo.some.Object" </message-chunking-aggregator-router>

</inbound>

Processing a Message Only Once

The ensures that only unique messages are received by a service by checking the unique message ID of the incomingIdempotent Receivermessage. The ID can be generated from the message using an expression defined in the attribute. By default, the expressionidExpressionused is , which means the underlying endpoint must support unique message IDs for this to work. In the following example, a#[message:id]unique ID is a combination of the message ID and the contents of the label field in the header, and the IDs are then written to a simple text file tokeep track of which messages have already been processed:

<inbound>

<idempotent-receiver-router idExpression= >"#[message:id]-#[header:label]" <simple-text-file-store directory= />"./idempotent" </idempotent-receiver-router>

</inbound>