Contact Us 1-800-596-4880

Creating Custom Transformer Classes

A custom transformer is a user-defined transformer class that implements org.mule.api.transformer.Transformer. Your class can extend AbstractTransformer or AbstractMessageTransformer, depending on your needs. This page describes how to create a custom transformer in more detail.

Access Transformer Annotation if you are looking for information about creating a transformer with the Transformer Annotation.

Transformer Classes

AbstractTransformer allows you to access and transform the source payload and to specify the encoding to use (if required). It defines methods for controlling the object types this transformer supports and validates the expected return type, leaving you to implement a single doTransform() method.

import org.mule.transformer.AbstractTransformer;

public class OrderToHtmlTransformer extends AbstractTransformer
{
    public Object doTransform(Object src, String encoding) throws TransformerException
}

If you need to transform the message header and attachments, you can use AbstractMessageTransformer instead to change them directly on the message passed in. In this case, you return the transformed message payload by overriding the method transform(MuleMessage message, String encoding). You can use message.getProperty(Object key) to retrieve the properties or message.setProperty(Object key, Object value) to set properties on the transformed message.

For example:

import org.mule.transformer.AbstractMessageTransformer;

public class OrderToHtmlTransformer extends AbstractMessageTransformer
{
    public Object transform(MuleMessage message, String encoding) throws TransformerException
}

Registering Source and Return Types

You can specify which source types a transformer can accept and which type it can return. This allows Mule to validate the incoming message before invoking the transformer and to validate the output before sending the message on. If Creating Discoverable Transformers, you must set the source and return types.

For example, for the Order bean to HTML transformer, you would specify in the constructor that the transformer converts only message payloads of type Order:

public class OrderToHtmlTransformer extends AbstractMessageTransformer
{
    public OrderToHtmlTransformer() {
        registerSourceType(DataTypeFactory.create(Order.class));
        setReturnDataType(DataTypeFactory.STRING);
        setName("OrderToHTML");
    }
}

Because the source type is specified, you don’t need to do any type checking in your transform() method. However, if you add more than one source type, you do need to check for each type in your transform() method.

Notice that the above code sets the name of the transformer. Usually, you set the transformer name in the XML configuration when the transformer is declared. If no name is set, Mule generates a name based on the first source type and return class, such as "OrderToString" if the above example did not specify the name.

Using Transformer Lifecycle Methods

All objects in Mule have lifecycles associated with them. For transformers, there are two lifecycle methods that are most useful.

By default AbstractMessageTransformer and AbstractTransformer both implement the org.mule.api.lifecycle.Initialisable interface. After all bean properties are set on the transformer (if any), the doInitialise() method is called. This is useful for transformers to do any initialization or validation work. For example, if a transformer requires that an external file be loaded before the transformer can operate, you would load the file via the doInitialise() method.

If you want your transformer to clear up resources when the transformer is no longer needed, your transformer must implement org.mule.api.lifecycle.Disposable `and implement the `dispose() method.

Creating Discoverable Transformers

Mule can perform automatic transformations. For example, when you call the getPayload() method on a MuleMessage and pass in the required type as follows:

Document doc = (Document)muleMessage.getPayload(org.dom4j.Document.class);

Mule looks at the current payload type and tries to find a transformer that can convert it to an org.dom4j.Document object. Mule provides several standard transformers for switching between common types such as strings, byte[], InputStream, and more. Also, transports usually have transformers for specific message types such as JMSMessage or HttpRequest. When creating a custom transformer, you can set its priority higher than the standard transformers so that it takes precedence.

To make a transformer discoverable, it must implement:

This interface introduces two methods, getPriorityWeighting() and setPriorityWeighting(int weighting). Weighting resolves conflicts when two or more transformers match the search criteria. The weighting is a number between 1 and 10, with 10 being the highest priority. As a rule, Mule transformers have a priority of 1 and should always have a lower priority than any custom transformers.

For example, to make the OrderToHtmlTransformer discoverable, you would define it as follows:

public class OrderToHtmlTransformer
extends AbstractMessageTransformer
implements DiscoverableTransformer
{
    private int weighting = DiscoverableTransformer. DEFAULT_PRIORITY_WEIGHTING + 1;

    int getPriorityWeighting() {
        return weighting;
    }

    void setPriorityWeighting(int weighting) {
        this.weighting = weighting;
    }
}

This transformer converts from an Order object to a String, which the standard ObjectToString transformer also does, but ObjectToHtml is used because it has a higher priority weighting.

You can test this as follows:

MuleMessage message = new DefaultMuleMessage(new Order(...));
String html = (String)muleMessage.getPayload(java.lang.String);

Registering the Transformer

After creating a transformer, you must register it so that Mule can discover it at runtime. You can register the transformer simply by configuring it using the <custom-transformer> element in your Mule configuration file.

Alternatively, if you want your transformer to be loaded automatically by Mule when your module (JAR) is on the class path, you add a registry-bootstrap.properties file to your JAR under the /META-INF/services/org/mule/config directory. The contents of registry-bootstrap.properties should look something like this:

orderToHtml=com.foo.OrderToHtml

When Mule starts, it discovers this bootstrap file before loading any configuration and installs any objects listed in the file into the local registry. For more information, see Bootstrapping the Registry.

Examples

To create an HTML message that includes the transactionId from the message header, you can extend AbstractMessageTransformer and write the transform() method as follows:

public Object transform(MuleMessage message, String encoding) throws TransformerException
{
    Order order = (Order)message.getPayload();
    StringBuffer html = new StringBuffer();
    html.append("");
    html.append("");
    html.append("");
    html.append("Dear ").append(order.getCustomer().getName()).append("
");
    html.append("Thank you for your order. Your transaction reference is: <strong>");
    html.append(message.getProperty("transactionId").append("</strong>");
    html.append("("");
    return html.toString();
}

You can find examples in Anypoint Exchange. The following example is for a custom transformer called StringToNameString, which wraps Java string in a custom class called NameString:

package org.mule.example.hello;

import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractTransformer;
import org.mule.transformer.types.DataTypeFactory;

/**
 * <code>StringToNameString</code> converts from a String to a NameString object.
 */
public class StringToNameString extends AbstractTransformer
{

    public StringToNameString()
    {
        super();
        this.registerSourceType(DataTypeFactory.STRING);
        this.setReturnDataType(DataTypeFactory.create(NameString.class));
    }

    @Override
    public Object doTransform(Object src, String encoding) throws TransformerException
    {
        return new NameString((String) src);
    }

}

The transformer is then configured as follows:

<custom-transformer name="StringToNameString" class="org.mule.example.hello.StringToNameString"/>
...
<flow name="Hello World">
...
    <vm:inbound-endpoint path="greeter" transformer-refs="StringToNameString" exchange-pattern="request-response"/>
...

Alternatively you can configure transformer directly in the connector, as follows:

<flow name="Hello World">
    <vm:inbound-endpoint path="greeter" exchange-pattern="request-response">
        <custom-transformer class="org.mule.example.hello.StringToNameString"/>
    </vm:inbound-endpoint>
...