Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

Developing Components

When developing components, you focus on developing code to handle the business logic, not to integrate the component with Mule. For example, if you are developing a component that adds customer data to an invoice, you focus on writing code that queries the customer database and updates the invoice as needed. You do not have to write any special code to handle the message that’s passed to the component or to integrate with Mule, as all integration is handled through configuration. You can develop the component as a POJO, or as a web service using popular containers such as Spring, EJB, or Plexus.

Mule does allow you to enable components to obtain information about or even control the current message instead of just working with the message payload. To enable the component to work directly with the message, you must implement the Callable interface in the component (see Entry Points below).

To get started with developing Mule components, you can use the Mule IDE. The Mule IDE is an Eclipse plug-in that provides an integrated development environment for developing Mule applications. You can also use the standard components provided with Mule, or use them as a starting point for building your own.

Entry Point

The entry point is the method in your component that is invoked by Mule when a message is received. To specify the method explicitly on your endpoint, you can use the method argument on the endpoint, such as:

<outbound-endpoint address="ejb://localhost:1099/SomeService?method=remoteMethod"/>

Or:

<ejb:endpoint host="localhost" port="1099" object="SomeService" method="remoteMethod"/>

If you do not specify this argument, Mule uses an entry point resolver to dynamically choose the method to invoke based on the payload type of the message. When the match is found, the method is cached with the parameter types so that introspection is only done once per method for the life of the flow. If multiple methods in the component match the payload type, or no method matches, an error is thrown. You can also call a method on the component that has no arguments.

Alternatively, your component can implement the org.mule.api.lifecycle.Callable interface. If your component implements this interface, it overrides any dynamic resolution and calls the interface method implementation instead.

For details on configuring entry point resolvers, see Entry Point Resolver Configuration Reference.

Legacy Entry Point Resolver Set

The LegacyEntryPointResolverSet is used if no other resolver is configured. The LegacyEntryPointResolverSet provides generic entry point resolution as follows:

  1. Check the methods of the component’s class for annotations (see org.mule.impl.model.resolvers.AnnotatedEntryPointResolver).

  2. Use the "method" attribute as described above, if one is specified (see org.mule.model.resolvers.MethodHeaderPropertyEntryPointResolver).

  3. If the component implements the org.mule.api.lifecycle.Callable lifecycle interface, use the onCall(MuleEventContext) method to receive the message.

  4. The message type is matched against methods on the component to see if there is a method that accepts the transformer return type. If so, this method is used. Note if there is more than one match, an exception is thrown.

  5. If none of the above finds a match, an exception is thrown and the component registration fails.

There are many scenarios where the LegacyEntryPointResolverSet is unsuitable. More control is available by extending its set of implementations, or by configuring a completely new set. There are several EntryPointResolver implementations, such as org.mule.model.resolvers.CallableEntryPointResolver, org.mule.model.resolvers.MethodHeaderPropertyEntryPointResolver, and org.mule.model.resolvers.ReflectionEntryPointResolver. While these are used in the LegacyEntryPointResolverSet, they can be more comprehensively configured when specified separately.

Calling No-arguments Methods

If you want to call a method with no arguments, you can use the org.mule.model.resolvers.NoArgumentsEntryPointResolver. Regardless of the payload of the current message, this resolver looks only for no-argument methods in the component. Additionally, ReflectionEntryPointResolver supports the resolution of no-argument methods if the payload received is of type NullPayload.

Custom Entry Point Resolver

If you want to create your own entry point resolver, you create a class that implements the EntryPointResolver interface and specify it with the <custom-entry-point-resolver> element in your Mule configuration.

Default Message Flow Behavior

Mule has some default behavior rules about managing message flow to and from your component.

  1. When a message is received, the entry point method is invoked as described above.

  2. The response or outbound message is obtained as follows:

    • If the method invoked is not void, (that is, Callable.onEvent() returns an Object), the method return value is used. If null is returned, no further processing is done for the current request.

    • If the method is void, the parameters used to invoke the method are used. This assumes that the parameters themselves were altered or there was no change to the message.

  3. If the inbound endpoint has an exchange pattern configured that returns a response then the result of the component invocation is returned to caller.

  4. The outbound message is then routed according the <outbound> configuration:

Customizing the Message Flow Behavior

To customize the message flow behavior, you must get a reference to org.mule.api.MuleEventContext. You can get the reference by implementing the Callable interface, which passes the event context as a parameter on this interface:


         
      
1
2
3
4
public interface Callable
{
    public Object onCall(MuleEventContext eventContext) throws Exception;
}

From the MuleEventContext, you can send and receive events synchronously and asynchronously, manage transactions, and override the default event flow behavior. For example:


         
      
1
2
3
4
5
6
7
8
9
MuleEventContext context = RequestContext.getEventContext();
OutboundEndpoint endpoint = ...
 
//to send asynchronously
context.dispatchEvent(new MuleMessage("IBM:0.01", null), endpoint);
 
//or to request
InboundEndpoint endpoint = ...
MuleMessage quote = context.requestEvent(endpoint, 5000);

Even when you use the event context to manually control event flow, when your method returns, Mule routes the outbound event as normal. You can stop Mule processing events further as follows:

  • If your method is not void, you can return null. This approach tells Mule there is no further event information to process.

  • If your method is void, Mule uses the inbound message payload as the outbound message payload. You can override this behavior using the setStopFurtherProcessing method as described below.

Halting Message Flow

To halt the message flow, you can either call setStopFurtherProcessing()`from the MuleEventContext or else throw an exception. This causes the `ExceptionStrategy on the component to be invoked.

The use of additional flows or the use of component bindings is much preferred to the above techniques to control message flow from within your component implementation. This is because it allows for a much more decoupled implementation that can be modified via your configuration file and avoids the need to use Mule API in your component implementations. To take this approach, do one of the following:

  • Ensure your components are implemented in such a way that they do a single unit of work that do not need to do any message sending/receiving. This additional sending/receiving/routing is then done using Mule flows.

  • Design your component in such a way that interface methods can be mapped to outbound endpoints and then use bindings to map these in configuration. For information on how to configure bindings, see Configuring Java Components.

Component Lifecycle

Your component can implement several lifecycle interfaces. The lifecycle flow typically looks like this, with onCall() often being replaced by an entry point resolver as described above:

component-lifecycle

Following are the most commonly used interfaces:

  • org.mule.api.lifecycle.Initialisable

    This is called only once for the lifecycle of the component. It is called when the component is created when the component pool initializes.

  • org.mule.api.lifecycle.Startable

    This is called when the component is started. This happens once when the server starts and whenever the component is stopped and started either through the API or JMX.

  • org.mule.api.lifecycle.Stoppable

    This is called when the component is stopped. This happens when the server stops or whenever the component is stopped either through the API or JMX.

  • org.mule.api.lifecycle.Disposable

    This is called when the component is disposed. This is called once when the server shuts down.

For more information, see the Javadocs.