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

Annotated Java Beans for Marshalling

This provides an example of an annotated Java bean that will reliably marshal as either JSON or XML.  The use of a java.util.Date object requires a custom marshal process to render the date consistently in both JSON and XML.  In this case, the Date object is rendered as a unix epoch timestamp.  Which on most *nix systems is the number of milliseconds since 1/1/1970 at UTC.

Annotated Java Bean

The following Java object can be ‘marshalled’ with either the FasterXML Jackson library (for json) or the JAXB library (for xml).  Note that the Jackson library can use many of the JAXB annotations, so for instance, there is no need to repeat the attribute naming (the XmlElement for instance) with its Jackson equivalent unless the attribute names are different between the two formats (as is the case with list naming).


package org.t35;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.mule.marshalling.xml.adapter.EpochMillisAdapter;

import com.fasterxml.jackson.annotation.JsonProperty;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class RegistrationDTO implements Cloneable {
	@XmlElement(required = true)
	private static String registrationCode = UUID.randomUUID().toString();
	
	@XmlElement(required = false)
	private String firstName;
	
	@XmlElement(required = false)
	private String middleName;
	
	@XmlElement(required = false)
	private String lastName;
	
	@XmlElement(required = true)
	private String email;
	
	@XmlElement(required = false)
	private String phone;
	
	@XmlElement(required = false)
	private String street;
	
	@XmlElement(required = false)
	private String city;
	
	@XmlElement(required = false)
	private String provinceOrState;
	
	@XmlElement(required = false)
	private String country;
	
	@XmlElement(required = false)
	private String postalCode;
	
	@XmlElement(required = false)
	private double registrationCost;
	
	@XmlElement(required = false)
	@XmlJavaTypeAdapter(EpochMillisAdapter.class)
	private Date registrationDate;
	
	@XmlElement(required = false)
	@XmlJavaTypeAdapter(EpochMillisAdapter.class)
	private Date attendenceDate;
	
	@JsonProperty("referenceCodes")
	@XmlElement(required = false, name = "referenceCode")
	private List referenceCodes = new ArrayList();
	
	@JsonProperty("items")
	@XmlElement(required = false, name = "item")
	private List items = new ArrayList();

	
	//----------------------------------------------------------//

	@Override
	public RegistrationDTO clone() throws CloneNotSupportedException {
		return (RegistrationDTO) super.clone();
	}
	
	@Override
	public String toString() {
		DecimalFormat df = new DecimalFormat();
		df.setMinimumFractionDigits(2);
		df.setMaximumFractionDigits(2);
		df.setMinimumIntegerDigits(1);
		df.setMaximumIntegerDigits(10);
		df.setRoundingMode(RoundingMode.DOWN);
		
		StringBuffer sb = new StringBuffer();
		sb.append(registrationCode).append("|");
		sb.append(firstName).append("|");
		sb.append(middleName).append("|");
		sb.append(lastName).append("|");
		sb.append(email).append("|");
		sb.append(phone).append("|");
		sb.append(street).append("|");
		sb.append(city).append("|");
		sb.append(provinceOrState).append("|");
		sb.append(country).append("|");
		sb.append(postalCode).append("|");
		sb.append(df.format(registrationCost)).append("|");
		sb.append(registrationDate.toString()).append("|");
		sb.append(attendenceDate.toString()).append("|");
		sb.append("References(").append(referenceCodes.size()).append(") ");
		for (String ref:referenceCodes) {
			sb.append(ref).append("|");
		}
		sb.append("items(").append(items.size()).append(") ");
		for (RegistrationItemDTO item: items) {
			sb.append(item.toString()).append("|");
		}
		return sb.toString();
	}

	public static String getRegistrationCode() {
		return registrationCode;
	}

	public static void setRegistrationCode(String registrationCode) {
		RegistrationDTO.registrationCode = registrationCode;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getMiddleName() {
		return middleName;
	}

	public void setMiddleName(String middleName) {
		this.middleName = middleName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getProvinceOrState() {
		return provinceOrState;
	}

	public void setProvinceOrState(String provinceOrState) {
		this.provinceOrState = provinceOrState;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getPostalCode() {
		return postalCode;
	}

	public void setPostalCode(String postalCode) {
		this.postalCode = postalCode;
	}

	public Double getRegistrationCost() {
		return registrationCost;
	}

	public void setRegistrationCost(Double registrationCost) {
		this.registrationCost = registrationCost;
	}

	public Date RegistrationDate() {
		return registrationDate;
	}

	public void setRegistrationDate(Date registrationDate) {
		this.registrationDate = registrationDate;
	}

	public Date getAttendenceDate() {
		return attendenceDate;
	}

	public void setAttendenceDate(Date attendenceDate) {
		this.attendenceDate = attendenceDate;
	}

	public List getReferenceCodes() {
		return referenceCodes;
	}

	public void setReferenceCodes(List referenceCodes) {
		this.referenceCodes = referenceCodes;
	}

	public List getItems() {
		return items;
	}

	public void setItems(List items) {
		this.items = items;
	}

}

XmlJavaAdapter

The XmlJavaAdapter used for the Date rendering the Java bean is shown below. Since Jackson is already annotating the date as a unix epoch date, marshalling instructions are only required for the JAXB serialization. Note that java.util.Date values are affected by physical machine configurations, so using the Date object does not guarantee that the serialized data is accurate. Check your implementations and deployments to verify that your machine’s are correctly producing unix epoch timestamps.


package org.mule.marshalling.xml.adapter;

import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class EpochMillisAdapter extends XmlAdapter {

	@Override
	public String marshal(Date v) throws Exception {
		return Long.valueOf(v.getTime()).toString();
	}

	@Override
	public Date unmarshal(String v) throws Exception {
		return new Date(Long.parseLong(v));
	}

}

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>

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>

UnMarshalling Interceptor for Mule

This code snippet can be used for Mule application workflows that require a generic un-marshaling component to convert a JSON or XML serialized object into an instantiated Java object. 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 serialized object is POSTed to the Mule application in the request body and a Content-Type header is included in the request to indicate the serialized format is either “application/json” or “application/xml”.

The Mule application un-marshals the serialized object using either JaxB (for XML format) or Jackson (for JSON format). The specific object to un-marshal is specified as a Java class name in either the Mule un-marshal configuration or in the Content-Type header provided by the invoking component. This latter function is meant to support RESTful API’s that utilize a mime attribute extension to define the specific object type being transmitted. For instance, the following header would attempt to instantiate the serialized JSON data as an InvoiceItem:

Content-Type: application/json;class=org.example.InvoiceItem

Specifying the object type in the Mule un-marshal configuration disables the Content-Type specification of object type.

Usage

The following xml is added to the Mule flow to un-marshal the serialized object based entirely on the Content-Type specified by the request:

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

Alternatively, the following xml inserted into the Mule flow will force the un-marshalling to use the InvoiceItem object type:

<custom-interceptor class="org.mule.interceptor.UnMarshalObjectInterceptor" />
<spring:property name=”resultClass” value="org.example.InvoiceItem" />
</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.StringReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

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;

/**
 * 
 * Uses Content-Type inbound property to define both the mime type and the
 * output class. For instance:
 * 
 * 
 * Content-Type: application/json;class=org.obj.MyObject
 * 
 *                    or
 * 
 * Content-Type: application/xml;class=org.obj.MyObject
 * 
 * 
 * The Mule interceptor is configured with the custom-interceptor tag:
 * 
 * 
 * <custom-interceptor class="org.mule.interceptor.UnMarshalObjectInterceptor"/>
 * 
 * 
 * The resultClass configuration property can be specified in the interceptor
 * configuration, which will be used to override the class specified in the
 * Content-Type inbound property.
 * 
 * A default content type can be specified with the defaultContentType
 * configuration property.
 * 
 * Note that the unmarshalled objects use Jackson or JaxB for performing the
 * transformation. Therefore, the result class should be annotated with
 * appropriate @Json and @Xml verbs, for example:
 * 
 * @XmlRootElement, @XmlAccessorType(XmlAccessType.FIELD),
 * @XmlElement(required=false name="alternalteName"), @JsonProperty,
 * etc. will be used in the transformation.
 * 
 * 
 * 
 * @author peterdunworth
 * 
 */
public class UnMarshalObjectInterceptor extends
		AbstractInterceptingMessageProcessor implements Interceptor {

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

	private String resultClass = null;
	private String defaultContentType = "application/json";

	/**
	 * Can be set with a
	 * 
	 * 
	 * 	<spring:property name="resultClass" value="org.mystuff.MyClass"/>
	 * 
	 * 
	 * If specified, the Content-Type attribute class is ignored.
	 * 
	 * @return the class to build from the serialized string in the message
	 *         package.
	 */
	public String getResultClass() {
		return resultClass;
	}

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

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

	public void setDefaultContentType(String defaultContentType) {
		this.defaultContentType = defaultContentType;
	}

	/**
	 * Transforms the message payload to the indicated output Class using the
	 * serialized message payload. The serialized format is specified in the
	 * Content-Type property.
	 * 
	 * The default content type can be specified with the default content type
	 * property.
	 * 
	 * 
	 */
	@Override
	public MuleEvent process(MuleEvent event) throws MuleException {
		MuleMessage message = event.getMessage();
		log.trace("message.getInboundProperty.Content-Type:"
				+ message.getInboundProperty("Content-Type"));

		String contentType = null;
		String outputClassName = null;

		if (!((String) message.getInboundProperty("http.method"))
				.equalsIgnoreCase("get")) {
			// allow flow to override the content type
			contentType = message.getInboundProperty("Content-Type");
		}
		if (contentType == null) {
			contentType = defaultContentType;
		}

		/**
		 * Specified property overrides the content-type specification
		 */
		if (resultClass != null) {
			outputClassName = resultClass;

		} else {
			int className = contentType.lastIndexOf(";class=");
			if (className < 5) {
				throw new TransformerException(
						MessageFactory
								.createStaticMessage("Missing ';class=' at the end of the Content-Type"));
			}
			outputClassName = contentType.substring(className + 7);
			int endOfClassName = outputClassName.indexOf(";");
			if (endOfClassName > 0) {
				outputClassName = outputClassName.substring(0, endOfClassName);
			}
			outputClassName = outputClassName.trim();
		}

		try {
			if (contentType.contains("application/json")) {
				message.setPayload(transformJSON(message, outputClassName));
				return processNext(event);
			} else if (contentType.contains("application/xml")) {
				message.setPayload(transformXML(message, outputClassName));
				return processNext(event);
			}
			return processNext(event);
		} catch (Exception e) {
			e.printStackTrace();
			message.setOutboundProperty("UnMarshalObjectErrorMsg", e.toString());
			throw new TransformerException(
					MessageFactory.createStaticMessage("UnMarshal Exception: "
							+ e.toString()));
		}
	}

	private Object transformJSON(MuleMessage message, String outputClassName)
			throws Exception {
		Class outputClass = Class.forName(outputClassName);
		Object obj = doTransformJSON(outputClass, message.getPayloadAsString());
		return obj;
	}

	public static Object doTransformJSON(Class iClass, String payload)
			throws Exception {
		log.trace("transformJSON");
		StringReader reader = null;
		try {
			ObjectMapper mapper = new ObjectMapper();
			reader = new StringReader(payload);
			@SuppressWarnings("unchecked")
			Object obj = mapper.readValue(reader, iClass);
			return obj;
		} catch (Exception e) {
			throw e;
		} finally {
			if (reader != null) {
				IOUtils.closeQuietly(reader);
			}
		}
	}

	private Object transformXML(MuleMessage message, String outputClassName)
			throws Exception {
		Class outputClass = Class.forName(outputClassName);
		Object obj = doTransformXML(outputClass, message.getPayloadAsString());
		return obj;
	}

	public static Object doTransformXML(Class iClass, String payload)
			throws JAXBException {
		log.trace("transformXML");

		StringReader reader = null;
		try {
			JAXBContext context = JAXBContext.newInstance(iClass);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			reader = new StringReader(payload);
			Object obj = unmarshaller.unmarshal(reader);
			return obj;
		} catch (JAXBException e) {
			if (e.getCause() == null) {
				throw e;
			}
			throw new JAXBException(e.getCause().toString());
		} finally {
			if (reader != null) {
				IOUtils.closeQuietly(reader);
			}
		}
	}
}

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>