Access Keys:
Skip to content (Access Key - 0)

Contents

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 line

We'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 
          "-//MuleSource //DTD mule-configuration XML V1.0//EN"
          "http://mule.mulesource.org/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 Configuration

Most 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 Class

The 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 + " !";
    }
}
Extra Credit
If you want to skip ahead a bit, you can take a look at the documentation for Writing Components.

Tying it all together

Here are the steps we go through inside of Mule :

  • System.in accepts data
  • Mule locates our implementation class (FirstHelloWorld) and delivers the data (event) to an acceptible method (helloWorld)
  • Our implementation class creates a new String (event) and returns it
  • Mule accepts the String (event) and sends it so System.out

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.

Endpoints

Endpoints are described as a collection of :

  1. Endpoint URI - an Endpoint must have an Endpoint URI; an address that is used to reference a resource or service either locally or remotely. This must be a valid URI.
  2. Connector - used to connect to the underlying transport. Often the connector is not explicitly set, instead the connector for the endpoint is found based on the scheme of the Endpoint URI. (Emphasis added).
  3. Filter - a filter to apply to messages being recieved on the endpoint. See the Transports Guide for information about filtering support for a specific transport.
  4. Transaction - Transactions can be begun or committed when an event is received or sent. See the Transports Guide for information about transactionsupport for a specific transport.
  5. Properties - These can be set to override certain properties on the connector for this endpoint instance. For example, when using a smtp endpoint you may want to overload the from address.

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 Web

Now 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 :

  • http://localhost:9080 accepts data
  • Mule locates our implementation class (SecondHelloWorld) and delivers the data (event) to an acceptible method (helloWorld)
  • Our implementation class creates a new String (event) and returns it
  • Mule accepts the String (event) and sends it to System.out

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 [MULE: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 2

So, 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 {{
Hello World, and hello /?name=Fred ! (bytes)
}}

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

Adaptavist Theme Builder Powered by Atlassian Confluence