Sample of @RestCall used in Anypoint Custom Connector

Seems that a simple code sample for using the Mule @RestCall in an Anypoint custom connector is hard to find. This code snippet is built from the Anypoint DevKit starter code. The sample simply uses the @RestCall and @RestUriParam annotations in a GET call. Nothing fancy, but it shows where the annotations can be placed and demonstrates the simplicity of building a REST client in a custom connector.

You can cut and paste the Java code below into the Anypoint (or Mule) studio, but be aware that the associated documentation files and MUnit test scripts will need to be changed. Also note the change to abstract class and abstract process methods.

Code

package org.mule.modules.objectexamplesrest;

import java.io.IOException;
import java.util.List;

import org.mule.api.ConnectionException;
import org.mule.api.annotations.Configurable;
import org.mule.api.annotations.Connect;
import org.mule.api.annotations.ConnectionIdentifier;
import org.mule.api.annotations.Connector;
import org.mule.api.annotations.Disconnect;
import org.mule.api.annotations.MetaDataKeyRetriever;
import org.mule.api.annotations.MetaDataRetriever;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.ValidateConnection;
import org.mule.api.annotations.display.Password;
import org.mule.api.annotations.param.ConnectionKey;
import org.mule.api.annotations.rest.HttpMethod;
import org.mule.api.annotations.rest.RestCall;
import org.mule.api.annotations.rest.RestUriParam;
import org.mule.common.metadata.MetaData;
import org.mule.common.metadata.MetaDataKey;

/**
 * Anypoint Connector
 * 
 * @author MuleSoft, Inc.
 */
@Connector(name = "objectexamplesrest", schemaVersion = "1.0", friendlyName = "ObjectExamplesRest", minMuleVersion = "3.5")
public abstract class ObjectExamplesRestConnector {
	/**
	 * Configurable
	 */
	@Configurable
	private String myProperty;

	@MetaDataKeyRetriever
	public List getMetaDataKeys() throws Exception {
		return null;
	}

	@MetaDataRetriever
	public MetaData getMetaData(MetaDataKey key) throws Exception {
		return null;
	}

	/**
	 * Set property
	 * 
	 * @param myProperty
	 *            My property
	 */
	public void setMyProperty(String myProperty) {
		this.myProperty = myProperty;
	}

	/**
	 * Get property
	 */
	public String getMyProperty() {
		return this.myProperty;
	}

	/**
	 * Connect
	 * 
	 * @param username
	 *            A username
	 * @param password
	 *            A password
	 * @throws ConnectionException
	 */
	@Connect
	public void connect(@ConnectionKey String username,
			@Password String password) throws ConnectionException {
		/*
		 * CODE FOR ESTABLISHING A CONNECTION GOES IN HERE
		 */
	}

	/**
	 * Disconnect
	 */
	@Disconnect
	public void disconnect() {
		/*
		 * CODE FOR CLOSING A CONNECTION GOES IN HERE
		 */
	}

	/**
	 * Are we connected
	 */
	@ValidateConnection
	public boolean isConnected() {
		return true;
	}

	/**
	 * Are we connected
	 */
	@ConnectionIdentifier
	public String connectionId() {
		return "001";
	}

	/**
	 * Custom processor
	 * 
	 * {@sample.xml ../../../doc/objectexamplesrest-connector.xml.sample
	 * objectexamplesrest:example}
	 * 
	 * @param objectName
	 *            object name to serialize
	 * @return serialized object
	 * @throws IOException
	 *             on error
	 */
	@Processor
	@RestCall(uri = "http://objectexamples.cloudhub.io/example/{objectName}", method = HttpMethod.GET)
	public abstract String example(@RestUriParam("objectName") String objectName)
			throws IOException;
}

Basic Authentication

To add basic authentication to the call, you need to build your own Authorization header. Here is the code to do that:


  @RestHeaderParam("Authorization")
  private String authorization = generateBasicAuthorization("username", "password");

and this is the code to build the header:


private static String generateBasicAuthorization(String userName, String password) {
  byte[] encodedPassword = (userName + ":" + password).getBytes();
  BASE64Encoder encoder = new BASE64Encoder();
  return "Basic " + encoder.encode(encodedPassword);
}

Using HttpMethod.POST

Help on POSTing data with @RestCall can be found here: http://forum.mulesoft.org/mulesoft/topics/can_restpostparam_be_used_to_post_json. Basically you can build the POSTed data in the Anypoint flow that uses the connector and pass that value as a String parameter to the connector method specifying the @Payload annotation in front of the parameter in the method signature.  Or you can use the multipart form data format and include @RestPostParam annotations for each field of the method call which is to be included in the POSTed data.  The latter method will create a POSTed data stream of ampersand separated name value pairs (such as name=Bill&phone=(999)555-1212).

Advertisement

Auto-Generate Example of JSON or XML objects

This code snippet can be used for Mule application workflows that are required to produce ‘mocked’ JSON or XML serialized objects for use in an agile development process.  The interceptor requires a result class and a serialized format specification, from which an example can be produced. These two items can be specified in a variety of ways to the interceptor.  At the most basic level, the interceptor can use an Http request url’s relative path to designate the class and format.  An example of using the url to specify the generation of a JSON object is:

http://localhost:8081/example/org.myclasses.MyClass.json

The serialized object replaces the Mule message payload.  The Accept request header can be used instead of the .json or .xml suffix in the request url.

The Mule marshal configuration can also ‘hardcode’ the content type, by using the configuration property “contentType”.  Specifying the content type in the Mule marshal configuration disables the Content-Type specification and forces the work flow to alway produce the indicated serialization format.

Finally, the Mule configuration can ‘hardcode’ the result class name so that the workflow always produces the same object regardless of what was specified in the request’s relative url.

Usage

The following xml is added to the Mule flow to marshal the object into a serialized format based entirely on the request’s relative url and optionally the Accept header:

<custom-interceptor class="org.mule.interceptor.ExampleGenerator" />

Alternatively, the following xml inserted into the Mule flow will force the example to always produce specific class:

<custom-interceptor class="org.mule.interceptor.MarshalObjectInterceptor" />
<spring:property name=”resultClass” value="org.myclasses.MyObj" />
</custom-interceptor>

The following Mule configuration entry will force the example to always produce specific class and serialized format:

<custom-interceptor class="org.mule.interceptor.MarshalObjectInterceptor" />
<spring:property name=”resultClass” value="org.myclasses.MyObj" />
<spring:property name=”contentType” value="application/json" />
</custom-interceptor>

Cut and paste the Java code below into the Anypoint (or Mule) studio as a new Java class file (in the src directory).

Code


package org.mule.interceptor;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.log4j.Logger;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.interceptor.Interceptor;
import org.mule.api.transformer.TransformerException;
import org.mule.config.i18n.MessageFactory;
import org.mule.processor.AbstractInterceptingMessageProcessor;

/**
 * An object name can be specified in the url with either a .json or .xml
 * extension. This will generate an example of the object into the specified
 * serialized format. For example,
 * http://localhost:8081/example/org.myobjs.MyObj.xml will create an example of
 * the org.myobjs.MyObj in serialized xml format. The interceptor can also be
 * configured to 'hardcode' the object type and/or serialized form using the
 * interceptor configuration properties.
 * 
 * To 'hardcode' the object name, use the resultClass property:
 * 
 * <spring:property name="resultClass" value="org.mystuff.MyClass"/>
 * 
 * The content type can be specified as a configuration property as well. In the
 * case where both resultClass and contentType are specified, the resultClass
 * property will override any class specified in the contentType property. Here
 * is an example of specifying
 * 
 * <spring:property name="contentType"
 * value="application/xml;class=org.mystuff.MyClass"/>
 * 
 * @return the class to build from the serialized string in the message package.
 */
public class ExampleGenerator extends AbstractInterceptingMessageProcessor
		implements Interceptor {

	public static Logger log = Logger.getLogger(ExampleGenerator.class);

	private String resultClass = null;
	private String contentType = null;

	public String getResultClass() {
		return resultClass;
	}

	public void setResultClass(String resultClass) {
		this.resultClass = resultClass;
	}

	/**
	 * Can be set with a
	 * 
	 * 
	 * <spring:property name="contentType" value="application/json"/>
	 * 
	 * 
	 * Default value is application/json
	 * 
	 * @return the content type
	 */
	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public ExampleGenerator() {
	}

	/**
	 * Set the message payload to the serialized form of the configured or
	 * specified object.
	 */
	public MuleEvent process(MuleEvent event) throws MuleException {
		MuleMessage message = event.getMessage();
		String outputClassName = null;
		String useContentType = null;

		useContentType = contentType;
		outputClassName = resultClass;

		/**
		 * Specified property overrides the url request
		 */
		if (resultClass != null) {
			outputClassName = resultClass;
		} else if (contentType != null) {
			int className = contentType.lastIndexOf(";class=");
			if (className > 4) {
				outputClassName = contentType.substring(className + 7);
				int endOfClassName = outputClassName.indexOf(";");
				if (endOfClassName > 0) {
					outputClassName = outputClassName.substring(0,
							endOfClassName);
				}
				outputClassName = outputClassName.trim();
			}
		}

		if (outputClassName == null) {
			outputClassName = message.getInboundProperty("http.relative.path");
		}

		if (outputClassName == null || outputClassName.trim().length() <= 0) {
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("No class name was specified in the request URL or in the resultClass property"));
		}

		if (outputClassName.toLowerCase().endsWith(".json")) {
			outputClassName = outputClassName.substring(0,
					outputClassName.length() - 5);
			if (useContentType == null) {
				useContentType = "application/json";
			}
		} else if (outputClassName.toLowerCase().endsWith(".xml")) {
			outputClassName = outputClassName.substring(0,
					outputClassName.length() - 4);
			if (useContentType == null) {
				useContentType = "application/xml";
			}
		}

		if (useContentType == null) {
			/* last option is to use what was specified in the request */
			useContentType = message.getInboundProperty("Accept");
		}

		if (useContentType == null
				|| (!useContentType.contains("application/json") && !useContentType
						.contains("application/xml"))) {
			useContentType = "application/json";
		}
		message.setOutboundProperty("Content-Type", useContentType);

		try {
			message.setPayload(examples(outputClassName, useContentType));
			return processNext(event);
		} catch (Exception e) {
			e.printStackTrace();
			message.setOutboundProperty("ExampleGeneratorErrorMsg",
					e.toString());
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("Example Generator Exception: "
									+ e.toString()));
		}
	}

	private static void assignFieldValue(Object inputObject,
			String inputFieldClassName, Field field) throws Exception {

		ArrayList arrayList = null;
		Object obj = inputObject;
		String fieldClassName = inputFieldClassName;

		if (inputFieldClassName.startsWith("java.util.List<")) {
			fieldClassName = inputFieldClassName.substring(
					"java.util.List<".length(),
					inputFieldClassName.length() - 1);
			arrayList = new ArrayList();
			field.set(obj, arrayList);
		} else if (inputFieldClassName.startsWith("class ")) {
			fieldClassName = inputFieldClassName.substring("class ".length(),
					inputFieldClassName.length());
		}

		if (fieldClassName.equals("java.lang.String")) {
			StringBuilder sb = new StringBuilder();
			sb.append("_").append(field.getName()).append("_");
			if (arrayList != null) {
				arrayList.add(sb.toString());
				arrayList.add(sb.toString());
				arrayList = null;
			} else {
				field.set(obj, sb.toString());
			}
		} else if (fieldClassName.equals("java.util.Date")) {
			Calendar calendar = Calendar.getInstance(TimeZone
					.getTimeZone("UTC"));
			Date date = calendar.getTime();

			if (arrayList != null) {
				arrayList.add(date);
				arrayList.add(date);
				arrayList = null;
			} else {
				field.set(obj, date);
			}
		} else if (fieldClassName.equals("java.lang.Boolean")) {
			if (arrayList != null) {
				arrayList.add(Boolean.valueOf(true));
				arrayList.add(Boolean.valueOf(true));
				arrayList = null;
			} else {
				field.set(obj, Boolean.valueOf(true));
			}
		} else if (fieldClassName.equals("java.lang.Short")) {
			if (arrayList != null) {
				arrayList.add(Short.valueOf((short) 7));
				arrayList.add(Short.valueOf((short) 7));
				arrayList = null;
			} else {
				field.set(obj, Short.valueOf((short) 7));
			}
		} else if (fieldClassName.equals("java.lang.Byte")) {
			if (arrayList != null) {
				arrayList.add(Byte.valueOf((byte) 66));
				arrayList.add(Byte.valueOf((byte) 66));
				arrayList = null;
			} else {
				field.set(obj, Byte.valueOf((byte) 66));
			}
		} else if (fieldClassName.equals("java.lang.Integer")) {
			if (arrayList != null) {
				arrayList.add(Integer.valueOf(10));
				arrayList.add(Integer.valueOf(10));
				arrayList = null;
			} else {
				field.set(obj, Integer.valueOf(10));
			}
		} else if (fieldClassName.equals("java.lang.Long")) {
			if (arrayList != null) {
				arrayList.add(Long.valueOf(999999L));
				arrayList.add(Long.valueOf(999999L));
				arrayList = null;
			} else {
				field.set(obj, Long.valueOf(999999L));
			}
		} else if (fieldClassName.equals("java.lang.Float")) {
			if (arrayList != null) {
				arrayList.add(Float.valueOf(34.8f));
				arrayList.add(Float.valueOf(34.8f));
				arrayList = null;
			} else {
				field.set(obj, Float.valueOf(34.8f));
			}
		} else if (fieldClassName.equals("java.lang.Double")) {
			if (arrayList != null) {
				arrayList.add(Double.valueOf(8888888.6d));
				arrayList.add(Double.valueOf(8888888.6d));
				arrayList = null;
			} else {
				field.set(obj, Double.valueOf(8888888.6d));
			}
		} else if (fieldClassName.equals("boolean")) {
			if (arrayList != null) {
				arrayList.add(true);
				arrayList.add(true);
				arrayList = null;
			} else {
				field.set(obj, true);
			}
		} else if (fieldClassName.equals("short")) {
			if (arrayList != null) {
				arrayList.add(7);
				arrayList.add(7);
				arrayList = null;
			} else {
				field.set(obj, 7);
			}
		} else if (fieldClassName.equals("char")) {
			if (arrayList != null) {
				arrayList.add('B');
				arrayList.add('B');
				arrayList = null;
			} else {
				field.set(obj, 'B');
			}
		} else if (fieldClassName.equals("byte")) {
			if (arrayList != null) {
				arrayList.add((byte) 66);
				arrayList.add((byte) 66);
				arrayList = null;
			} else {
				field.set(obj, (byte) 66);
			}
		} else if (fieldClassName.equals("int")) {
			if (arrayList != null) {
				arrayList.add(10);
				arrayList.add(10);
				arrayList = null;
			} else {
				field.set(obj, 10);
			}
		} else if (fieldClassName.equals("long")) {
			if (arrayList != null) {
				arrayList.add(999999L);
				arrayList.add(999999L);
				arrayList = null;
			} else {
				field.set(obj, 999999L);
			}
		} else if (fieldClassName.equals("float")) {
			if (arrayList != null) {
				arrayList.add(34.8f);
				arrayList.add(34.8f);
				arrayList = null;
			} else {
				field.set(obj, 34.8f);
			}
		} else if (fieldClassName.equals("double")) {
			if (arrayList != null) {
				arrayList.add(8888888.6d);
				arrayList.add(8888888.6d);
				arrayList = null;
			} else {
				field.set(obj, 8888888.6d);
			}
		} else {
			if (arrayList != null) {
				arrayList.add(examples(fieldClassName));
				arrayList.add(examples(fieldClassName));
				arrayList = null;
			} else {
				field.set(obj, examples(fieldClassName));
			}

		}

	}

	public static Object examples(String outputClassName) throws Exception {
		Class outputClass = Class.forName(outputClassName);
		Object exampleObj = outputClass.newInstance();
		Field[] fields = outputClass.getDeclaredFields();
		for (Field field : fields) {
			String fieldClassName = field.getGenericType().toString();
			field.setAccessible(true);
			assignFieldValue(exampleObj, fieldClassName, field);
		}
		return exampleObj;
	}

	public static String examples(String outputClassName, String contentType)
			throws Exception {
		Class outputClass = Class.forName(outputClassName);
		Object exampleObj = examples(outputClassName);
		if (contentType.contains("application/xml")) {
			return (String) MarshalObjectInterceptor.doTransformXML(
					outputClass, exampleObj);
		} else {
			return (String) MarshalObjectInterceptor.doTransformJSON(
					outputClass, exampleObj);
		}
	}

}

Eclipse Maven Dependencies

If this code is built in Eclipse instead of Anypoint (Mule) Studio, the following maven dependencies are required. Once built, the jar file can be dropped into the lib folder of the Mule project directory (and the jar file added to the build path).


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.t35</groupId>
    <artifactId>mule-marshalling-interceptor</artifactId>
    <version>0.0.1</version>
    <name>Marshalling Interceptor for Mule ESB</name>
    <description>Marshalling Interceptor for Mule ESB</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <mule.version>3.4.1</mule.version>
        <jdkName>JavaSE-1.6</jdkName>
        <jdk.version>1.6</jdk.version>
        <junit.version>4.9</junit.version>
    </properties>

    <repositories>
        <repository>
            <id>Central</id>
            <name>Central</name>
            <url>http://repo1.maven.org/maven2/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-releases</id>
            <name>MuleSoft Releases Repository</name>
            <url>http://repository.mulesoft.org/releases/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-snapshots</id>
            <name>MuleSoft Snapshots Repository</name>
            <url>http://repository.mulesoft.org/snapshots/</url>
            <layout>default</layout>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>http://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                    <encoding>ISO-8859-1</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2.1</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>project</descriptorRef>
                    </descriptorRefs>
                    <finalName>mule-marshalling-interceptors</finalName>
                </configuration>
            </plugin>
            <!-- plugin> <groupId>org.jsonschema2pojo</groupId> <artifactId>jsonschema2pojo-maven-plugin</artifactId> 
                <version>0.4.2</version> <configuration> <sourceDirectory>${basedir}/src/main/api/schemas</sourceDirectory> 
                <targetPackage>com.example.types</targetPackage> </configuration> <executions> 
                <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> 
                </plugin -->
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.mule</groupId>
            <artifactId>mule-core</artifactId>
            <version>${mule.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>
</project>

Marshalling Interceptor for Mule

This code snippet can be used for Mule application workflows that require a generic marshaling component to serialize a Java object into either a JSON or XML format. The serialized format is chosen by the execution component that is invoking the Mule application workflow. Typically this is an http request utilizing a RESTful interface that has been exposed by the Mule application workflow.  The Accept header is used to specify whether JSON or XML is to be produced.

The serialized object replaces the Mule message payload and a Content-Type header is included in the outbound properties to indicate the serialized format is either “application/json” or “application/xml”.

The Mule application marshals the serialized object using either JaxB (for XML format) or Jackson (for JSON format). The specific object to marshal is the message payload and is expected to be a Java object that is annotated for serialization. As mentioned earlier, the Accept inbound property indicates what serialization format to use.  For instance, request XML serialized data, use this Accept header:

Accept: application/xml

The Mule marshal configuration can also ‘hardcode’ the content type, by using the configuration property “contentType”.  Specifying the content type in the Mule marshal configuration disables the Content-Type specification and forces the work flow to alway produce the indicated serialization format.

Usage

The following xml is added to the Mule flow to marshal the object into a serialized format based entirely on the Accept header specified by the request:

<custom-interceptor class="org.mule.interceptor.MarshalObjectInterceptor" />

Alternatively, the following xml inserted into the Mule flow will force the marshalling to always produce an XML serialized form:

<custom-interceptor class="org.mule.interceptor.MarshalObjectInterceptor" />
<spring:property name=”contentType” value="application/xml" />
</custom-interceptor>

Cut and paste the Java code below into the Anypoint (or Mule) studio as a new Java class file (in the src directory).

Code


package org.mule.interceptor;

import java.io.StringWriter;
import java.util.StringTokenizer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.interceptor.Interceptor;
import org.mule.api.transformer.TransformerException;
import org.mule.config.i18n.MessageFactory;
import org.mule.processor.AbstractInterceptingMessageProcessor;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 
 * Converts the message payload object into a serialized string (json or xml)
 * based on the Accept inbound property in the request. For example:
 * 
 * 
 * Accept: application/json
 *           or
 * Accept: application/xml
 * 
 * 
 * The Mule interceptor is configured with the custom-interceptor tag:
 * 
 * 
 * <custom-interceptor class="org.mule.interceptor.MarshalObjectInterceptor"/>
 * 
 * 
 * The content type can be overridden by interceptor configuration by specifying
 * a contentType property in the interceptor configuration. Default value for
 * the returned content type is "application/json" if neither an Accept inbound
 * property or the contentType property is specified.
 * 
 * 
 * 
 * @author peterdunworth
 * 
 */
public class MarshalObjectInterceptor extends
		AbstractInterceptingMessageProcessor implements Interceptor {

	public static Logger log = Logger.getLogger(MarshalObjectInterceptor.class);

	private String contentType = null;

	/**
	 * Can be set with a
	 * 
	 * 
	 * <spring:property name="contentType" value="application/json"/>
	 * 
	 * 
	 * @return the default content type
	 */
	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public MuleEvent process(MuleEvent event) throws MuleException {
		MuleMessage message = event.getMessage();
		log.trace("message.getInboundProperty.Accept:"
				+ message.getInboundProperty("Accept"));

		// allow flow to override what is generated
		String useContentType = null;
		if (contentType != null) {
			useContentType = contentType;
		} else {
			useContentType = message.getInboundProperty("Accept");
		}
		String outputEncoding = "UTF-8";

		try {
			if (useContentType == null) {
				useContentType = "application/json";
			}
			message.setPayload(firstRecognizedType(message, outputEncoding,
					useContentType));
			message.setOutboundProperty("Content-Type", useContentType);
			return processNext(event);
		} catch (Exception e) {
			e.printStackTrace();
			message.setOutboundProperty("MarshalObjectErrorMsg", e.toString());
			throw new TransformerException(
					MessageFactory.createStaticMessage("Marshal Exception: "
							+ e.toString()));
		}
	}

	private Object firstRecognizedType(MuleMessage message,
			String outputEncoding, String mimeTypes) throws Exception {
		StringTokenizer tok = new StringTokenizer(mimeTypes, ", ");
		while (tok.hasMoreElements()) {
			String mtype = tok.nextToken();
			if (mtype.equalsIgnoreCase("application/json")) {
				return transformJSON(message, outputEncoding);
			} else if (mtype.equalsIgnoreCase("application/xml")) {
				return transformXML(message, outputEncoding);
			}
		}
		return transformJSON(message, outputEncoding);
	}

	private Object transformJSON(MuleMessage message, String outputEncoding)
			throws Exception {
		Object obj = message.getPayload();
		return doTransformJSON(obj.getClass(), obj);
	}

	public static Object doTransformJSON(Class iClass, Object payload)
			throws Exception {
		log.trace("transformJSON");
		ObjectMapper mapper = new ObjectMapper();
		// mapper.enable(SerializationFeature.INDENT_OUTPUT);
		return mapper.writeValueAsString(payload);
	}

	private Object transformXML(MuleMessage message, String outputEncoding)
			throws Exception {
		Object obj = message.getPayload();
		return doTransformXML(obj.getClass(), obj);
	}

	public static Object doTransformXML(Class iClass, Object payload)
			throws Exception {
		log.trace("transformXML");
		StringWriter writer = new StringWriter();
		try {
			JAXBContext context = JAXBContext.newInstance(iClass);
			Marshaller marshaller = context.createMarshaller();
			// marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
			// Boolean.TRUE);
			marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
			marshaller.marshal(payload, writer);
			return writer.toString();
		} finally {
			if (writer != null) {
				IOUtils.closeQuietly(writer);
			}
		}
	}

}

Eclipse Maven Dependencies

If this code is built in Eclipse instead of Anypoint (Mule) Studio, the following maven dependencies are required. Once built, the jar file can be dropped into the lib folder of the Mule project directory (and the jar file added to the build path).


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.t35</groupId>
    <artifactId>mule-marshalling-interceptor</artifactId>
    <version>0.0.1</version>
    <name>Marshalling Interceptor for Mule ESB</name>
    <description>Marshalling Interceptor for Mule ESB</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <mule.version>3.4.1</mule.version>
        <jdkName>JavaSE-1.6</jdkName>
        <jdk.version>1.6</jdk.version>
        <junit.version>4.9</junit.version>
    </properties>

    <repositories>
        <repository>
            <id>Central</id>
            <name>Central</name>
            <url>http://repo1.maven.org/maven2/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-releases</id>
            <name>MuleSoft Releases Repository</name>
            <url>http://repository.mulesoft.org/releases/</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-snapshots</id>
            <name>MuleSoft Snapshots Repository</name>
            <url>http://repository.mulesoft.org/snapshots/</url>
            <layout>default</layout>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>http://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                    <encoding>ISO-8859-1</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2.1</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>project</descriptorRef>
                    </descriptorRefs>
                    <finalName>mule-marshalling-interceptors</finalName>
                </configuration>
            </plugin>
            <!-- plugin> <groupId>org.jsonschema2pojo</groupId> <artifactId>jsonschema2pojo-maven-plugin</artifactId> 
                <version>0.4.2</version> <configuration> <sourceDirectory>${basedir}/src/main/api/schemas</sourceDirectory> 
                <targetPackage>com.example.types</targetPackage> </configuration> <executions> 
                <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> 
                </plugin -->
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.mule</groupId>
            <artifactId>mule-core</artifactId>
            <version>${mule.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>
</project>