Mule : Hello World and friends
This page last changed on May 31, 2006 by tcarlson.
Hello World!Everyone seems to be pretty comfortable with the typical "Hello World" examples to being learning a new technology, so lets start there. Hello World on the command lineWe're going to construct a simple application that reads in text from the System.in stream and emits some modified text to the System.out stream. Normally, Hello World apps don't require any input (beyond execution of the program), but since Mule is a SEDA framework, it requires an event to trigger action. In this case, it's pretty simple to accept input, so we'll use that as our example. This example mimics the example from Hello World Example, but is simpler in some ways. Our FirstHelloWorld class looks like this : FirstHelloWorld.java package com.loopysoft.mule.tutorial.helloWorld; public class FirstHelloWorld { public String helloWorld(String promptText) { //We print our triumphant message and say hello to the person at the prompt return "Hello World, and hello " + promptText + " !"; } } Our corresponding Mule configuration file looks like this (descriptions have been removed in this document, see the sample source for the descriptions): <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mule-configuration PUBLIC "-//SymphonySoft //DTD mule-configuration XML V1.0//EN" "http://www.symphonysoft.com/dtds/mule/mule-configuration.dtd"> <mule-configuration id="Hello_World_1" version="1.0"> <connector name="SystemStreamConnector" className="org.mule.providers.stream.SystemStreamConnector"> <properties> <property name="promptMessage" value="Please enter your name: "/> <property name="messageDelayTime" value="1000"/> </properties> </connector> <model name="helloWorld"> <mule-descriptor name="HelloWorldUMO" implementation="com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld"> <inbound-router> <endpoint address="stream://System.in"/> </inbound-router> <outbound-router> <router className="org.mule.routing.outbound.OutboundPassThroughRouter"> <endpoint address="stream://System.out"/> </router> </outbound-router> </mule-descriptor> </model> </mule-configuration> If you're following along with the code samples, you can run the example with ./startMule.sh etc/mule/helloworld/hello-world-1.mule.xml and you'll see something like this : ********************************************************************** * Mule - Universal Message Objects version 1.2 * * SymphonySoft Limited * * For help or more information go to http://www.muleumo.org * * * * Server started: Sat Dec 17 10:55:42 PST 2005 * * JDK: 1.5.0_01 (mixed mode, sharing) * * OS: Linux (2.6.12-10-386, i386) * * * * Agents Running: * * Mule Admin: accepting connections on tcp://localhost:60504 * ********************************************************************** Please enter your name: Fred Smith Hello World, and hello Fred Smith ! So, you've now constructed a very simple UMO, configuration, and interacted with your UMO through Mule. Lets look at each of the pieces involved to see how that worked. Mule ConfigurationMost of the heavy lifting in this example is done for you by Mule. To see how data flows in and out of Mule, and also your code, lets take a look at the configuration. Within the mule-configuration tag, we create a model that contains our UMOs (insert description of what a model means). We only have one UMO (HelloWorldUMO). The mule-descriptor describes the UMO and associated configuration information. We specify our implementation class (the class handling our events), inbound router (where events come from), and outbound-router (where the events from the UMO go). The routers we've specified deal with Endpoints. For now, understand that Endpoints link the VM streams with our UMO. <model name="helloWorld"> <mule-descriptor name="HelloWorldUMO" implementation="com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld"> <inbound-router> <endpoint address="stream://System.in"/> </inbound-router> <outbound-router> <router className="org.mule.routing.outbound.OutboundPassThroughRouter"> <endpoint address="stream://System.out"/> </router> </outbound-router> </mule-descriptor> </model> Connector configurations are used to override the connectors default settings. Normally, you won't need to do this, but we do here so that we can modify the input stream parameters. Don't worry about this for now. <connector name="SystemStreamConnector" className="org.mule.providers.stream.SystemStreamConnector"> <properties> <property name="promptMessage" value="Please enter your name: "/> <property name="messageDelayTime" value="1000"/> </properties> </connector> FirstHelloWorld ClassThe FirstHelloWorld class is very simple. All we do is expose a method that accepts a String and returns a String. For now, just understand that Mule automagically found the right method on your class and then did the "Right Thing" with the results of your method. FirstHelloWorld.java package com.loopysoft.mule.tutorial.helloWorld; public class FirstHelloWorld { public String helloWorld(String promptText) { //We print our triumphant message and say hello to the person at the prompt return "Hello World, and hello " + promptText + " !"; } }
Tying it all togetherHere are the steps we go through inside of Mule :
This may seem obvious, but there has been quite a bit done by Mule behind the scenes. First, we didn't specify a method to use on our implementation class, so how did Mule figure out which method to use? Well, there's only one method, but that's not how Mule picked helloWorld. Under the covers, Mule has the ability to introspect the interface of classes it interacts with, so we don't have to specify which events are sent to particular methods (as long as the methods don't have ambiguous signatures. We'll talk about this more later). In our case, System.in accepted a String, and Mule figured out to send that String to the right method on our object. The return path is similar, with our returned String being sent to System.out. To discover more about how Mule links all of our pieces together, we need to talk about Endpoints. EndpointsEndpoints are described as a collection of :
For our purposes, we only need to look at the Endpoint URI. An Endpoint URI provides an easy way to specify an Endpoint (otherwise you specify a configuration section for your Endpoints, which we'll do later). We use two endpoints, both of which are well-known streams in Java; System.in and System.out. (For now ignore the router classname attribute). The Endpoints links the VM streams with our UMO. An Endpoint URI specifies the Transport Provider to be used, which in our case is stream. You can find guides for all the Transport Providers in the Transports Guide. Hello World 2 from the WebNow that we've built a simple UMO, lets make it more useful by exposing it to people on the web. Here's the flow we'd like to achieve :
Lets modify our configuration to match our desired flow : <model name="helloWorld"> <mule-descriptor name="HelloWorldUMO" implementation="com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld"> <inbound-router> <endpoint address="http://localhost:9080"/> </inbound-router> <outbound-router> <router className="org.mule.routing.outbound.OutboundPassThroughRouter"> <endpoint address="stream://System.out"/> </router> </outbound-router> </mule-descriptor> </model> However, when we run this, and call our URL ( http://localhost:9080 ) we get the following errors (full stack traces removed, and restructured): 0 [HelloWorldUMO.2] ERROR org.mule.impl.DefaultComponentExceptionStrategy - ******************************************************************************** Message : Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld Type : org.mule.model.NoSatisfiableMethodsException Code : 101216 JavaDoc : http://mule.codehaus.org/docs/apidocs/org/mule/model/NoSatisfiableMethodsException.html ******************************************************************************** Exception stack is: 1. Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld (org.mule.model.NoSatisfiableMethodsException) org.mule.model.DynamicEntryPoint:120 (http://mule.codehaus.org/docs/apidocs/org/mule/model/NoSatisfiableMethodsException.html) ******************************************************************************** Root Exception stack trace: org.mule.model.NoSatisfiableMethodsException: Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld <snip> ******************************************************************************** 18 [HelloWorldUMO.2] ERROR org.mule.impl.DefaultComponentExceptionStrategy - Caught exception in Exception Strategy for: HelloWorldUMO: org.mule.umo.MessagingException: Failed to invoke UMO Component: HelloWorldUMO. Message payload is of type: [B org.mule.umo.MessagingException: Failed to invoke UMO Component: HelloWorldUMO. Message payload is of type: [B <snip> Caused by: org.mule.model.NoSatisfiableMethodsException: Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld <snip> There's a few important things to notice in the stack trace. The first is the Mule "exception report" (need a better term?) : 0 [HelloWorldUMO.2] ERROR org.mule.impl.DefaultComponentExceptionStrategy - ******************************************************************************** Message : Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld Type : org.mule.model.NoSatisfiableMethodsException Code : 101216 JavaDoc : http://mule.codehaus.org/docs/apidocs/org/mule/model/NoSatisfiableMethodsException.html ******************************************************************************** Exception stack is: 1. Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld (org.mule.model.NoSatisfiableMethodsException) org.mule.model.DynamicEntryPoint:120 (http://mule.codehaus.org/docs/apidocs/org/mule/model/NoSatisfiableMethodsException.html) Here, you can see which exception strategy is being used (org.mule.impl.DefaultComponentExceptionStrategy, more on this elsewhere), and what the human readable reason for the exception was ("Exception stack is:...."). Our root problem is : 18 [HelloWorldUMO.2] ERROR org.mule.impl.DefaultComponentExceptionStrategy -
Caught exception in Exception Strategy for: HelloWorldUMO: org.mule.umo.MessagingException:
Failed to invoke UMO Component: HelloWorldUMO. Message payload is of type: [B
org.mule.umo.MessagingException: Failed to invoke UMO Component: HelloWorldUMO. Message payload is of type: [B
<snip>
Caused by: org.mule.model.NoSatisfiableMethodsException:
Could not find entry point on: com.loopysoft.mule.tutorial.helloWorld.FirstHelloWorld
<snip>
This means that, when Mule attempted to deliver a message to our UMO, the payload type [B (That's B for byte (primitive byte, not object byte) and ] for array) couldn't be delivered to any of the methods we have. So lets create a new HelloWorld (called SecondHelloWorld as well as a new mule config). HelloWorld, take 2So, now we have a slightly modified HelloWorld UMO that looks like this public class SecondHelloWorld { public String helloWorld(String promptText) { //We print our triumphant message and say hello to the person at the prompt return "Hello World, and hello " + promptText + " !(string)"; } public String helloWorld(byte [] bytes) { String promptText = new String(bytes); return "Hello World, and hello " + promptText + " ! (bytes)"; } } We've added another method that accepts bytes instead, and adds a comment to note which method is being called. Now, we can fire up our browser and hit http://localhost:9080/?name=Fred . Watching the output we see {{ Well, that's close, but not quite what the same results as last time. In this case, we get to learn about Endpoint Transformation to get our message to come out correctly. 1. Transformation |
![]() |
Document generated by Confluence on Oct 03, 2006 09:23 |