Mule Models
A Mule model manages the runtime behaviour of the service components that a Mule instance hosts. The manner in which these components are invoked and treated is all encapsulated inside the current Mule model. By default, Mule uses the SEDA model but it ships with a number of other models too.
You can indicate which model to use for your components by using the type attribute in the <model> tags. You can also have multiple models within a single Mule instance.
<model name="mainSection" type="SEDA"> ... </model>
Inside a Mule Model
Every Mule Model implements the UMOModel interface. This represents the behaviour of a Mule server and all models implement this interface. The fields and methods that this interface publishes are:
- Name - This is a string value that refers to the name of the model and is set as an attribute within the <model> tags. It is required when multiple models exist in a single configuration file.
- EntryPointResolver - This refers to a class that implements the UMOEntryPointResolver interface. This class will be used to determine the entry point for any hosted component when a message is received.
- ExceptionListener - The exception strategy to use for the entire model. The exception strategy is used to handle any exceptions that occur when a component is processing a message.
- lifecycleAdapterFactory - This is used by the model to create lifecycle adapters which are needed to translate Mule lifecycle event into events that UMO components registered with the model understand.
- registerComponent() - This method accepts a UMODescriptor and registers that component with the Mule manager. The Mule manager handles constructing the component at run time. There is a complementary method called unregisterComponent() that performs the opposite task and there is a helper method called isComponentRegistered() that checks to see if a component with a particular name is registered or not.
- getDescriptor() - returns a UMODescriptor for a specific component.
- stopComponent() - stops the specified component from processing.
- startComponent() - starts the specified component and allows it to continue processing
- pauseComponent() - allows you to temporarily halt a component's processing. Unlike stopComponent(), messages from the inbound endpoints will still be consumed as the inbound flow stage will be able to queue these messages for processing.
- resumeComponent() - resumes a component that had been paused.
For a complete list of fields and methods, see; http://www.muleumo.org/docs/apidocs/org/mule/umo/model/UMOModel.html
An abstract class that implements this interface and which is the parent for all models is org.mule.impl.model.AbstractModel.
Entry Point Resolver
Defined by the org.mule.umo.model.UMOEntryPointResolver interface, an entry point resolver is used to determine what method to invoke on an UMO component when event is received for it's consumption. There is a DynamicEntryPointResolver that is used if no other is configured on the model (see the Configuration Guide for more information). The DynamicEntryPointResolver provides entry point resolution for common usage, the steps it takes are -
- Checks to see if the component implements the org.mule.umo.lifecycle.Callable lifecycle interface, then the onCall(UMOEventContext) method will be used to receive the event.
- If the component has a transformer configured for it, the return type for the transformer will be matched against methods on the component to see if there is a method that accepts the transformer return type. If so this event will be used. Note if there is more than one match, an exception will be thrown.
- If there is a method on the component that accepts an org.mule.umo.UMOEventContext . If so this event will be used. Note if there is more than one match, an exception will be thrown.
- The last check determines if there are any methods on the component that accept a java.util.Event. If so this event will be used. Note if there is more than one match, an exception will be thrown.
- If none of the above find a match an exception will be thrown and the component registration will fail.
Of course there are many scenarios where the DynamicEntryPointResolver is suitable. For example, if you are migrating from another framework you may want to restrict (such as org.mule.model.CallableEntryPointResolver that only accepts components that extend org.mule.umo.lifecycle.Callable ) or change the way the entry point is resolved. To implement a custom Entry Point Resolver the org.mule.model.EntryPointResolver must be implemented.
Lifecycle Adapter
Defined by the
org.mule.umo.lifecycle.UMOLifecycleAdapter
interface, the lifecycle adapter is responsible for mapping the mule component lifecycle to the underlying component. The DefaultLifecycleAdapter simply delegates lifecycle events to the component where the component implements zero or more UMO lifecycle interfaces.
Clearly this isn't suitable for existing components that you want to be managed by Mule, as they will most likely have their own lifecycle methods that will still need to be invoked in the Mule framework. Luckily, the
org.mule.umo.lifecycle.LifecycleAdapter
is very simple to implement.
Lifecycle adapters are configured using an implementation of
org.mule.umo.lifecycle.UMOLifecycleAdapterFactory
. The factory is declared in the configuration of the model. A default is provided DefaultLifecycleAdapterFactory.
Mule Models
Mule provides the following models:
- SEDA is the default model (Staged Event Driven Architecture)
- SEDA optimized is similar to the SEDA model but contains certain assumptions that help improve performance.
- The Direct model is a very simple one where there is no threading or pooling of components
- The Pipeline model is similar to the Direct model but contains certain assumptions that help improve performance.
- Streaming allows for the streaming of large amounts of data
- Inherited is an indication that you wish to inherit a model from a different configuration file.
- Custom means that you will implement your own model
SEDA Optimised Model
The org.mule.impl.model.seda.optimised.OptimisedSedaModel model enhances the default SEDA model by assuming that all the components which it hosts implement the Callable interface. This avoids the need for the costly reflection and introspection on hosted beans. If a hosted component does not implement Callable, then a java.lang.IllegalArgumentException is raised.
Since this model assumes that SEDA (and therefore asynchronous processing) will be used throughout, both reply-to properties and response-routers are ignored.
The Direct Model
The org.mule.impl.model.direct.DirectModel model does not have any of the advantages of the SEDA model. There is no thread management and components are not pooled to service incoming messages, even if the message flow is asynchronous.
Parts of this model can be simulated when using the SEDA model; e.g., if you want to eliminate the component pool, you can set a <mule-descriptor>'s singleton attribute to true to make sure that only one instance of your component is loaded at run time.
All other features, like the DynamicEntryPointResolver, are inherited from the AbstractModel.
The Pipeline Model
The org.mule.impl.model.pipeline.PipelineModel class enhances the Direct model by assuming that all the components which it hosts implement the Callable interface. This avoids the need for the costly reflection and introspection on hosted beans. If a hosted component does not implement Callable, then a org.mule.umo.lifecycle.InitialisationException is raised.
The Streaming Model
Streaming allows you to stream data through Mule, or through service components rather than having to read the whole item into memory, leading to more efficient processing of large files or records. This technique is supported across TCP, File, HTTP and SOAP (Xfire) although support for FTP will be available shortly.
As of 1.4, "streaming" has been added as a type to the Mule model. Your Mule endpoints will need to understand how to stream data - you can configure this by setting the "streaming" attribute to true for each endpoint.
The Inherited Model
The "inherited" type is not really a model but an indication to Mule that the model type was defined in a previous configuration file.
Inside the first configuration file, you can define your model and all it's properties, etc. Inside secondary configuration files, you can either declare separate and independent models or else you can simply inherit the model used in the first configuration file. This allows you to split your Mule configuration into multiple files. The root element will still be <mule-configuration> as is shown in the next slide.
Note that configuration files are loaded sequentially, so the master configuration has to be passed to the configuration builder class first, e.g.,
java -cp ... org.mule.MuleServer -config conf/mule-config.xml, conf/mule-component2-config.xml
The Custom Model
The "custom" type allows you to use a model of your own, should you wish to implement one of your own. You will need to set the className attribute to point to your model, or you can use the ref attribute if your model is declared inside some other container, like Spring. If you do not set the className attribute, an IllegalArgumentException will be raised.
You can implement your own model by inheriting from the AbstractModel class which handles certain default behaviour, or you can code your own and implement the UMOModel interface instead.