Routing to flow via HTTP Relative Path

Packaging multiple Anypoint API proxies into a single deployment package is sometimes required. This can be done by creating a large project that has everything in it already. But what if you really want to have the proxies implemented independently in their own projects and just want to “grab” the finished flow from its project and drop it into a package with several other proxies?

You could create a custom proxy that has a single inbound HTTP endpoint that examines the request and sends each on to an “outbound HTTP endpoint” workflow depending upon the http.relative.path variable. You could use a choice router to examine relative path and invoke the appropriate flow. If you just want to “drop” the outbound flow into the package, you can eliminate the choice router with a custom java class that routes the message to a flow whose flow name closely matches the relative path. For instance:

package org.mule.httprouter;

import org.mule.api.DefaultMuleException;
import org.mule.api.MuleContext;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.interceptor.Interceptor;
import org.mule.config.i18n.MessageFactory;
import org.mule.construct.Flow;
import org.mule.processor.AbstractInterceptingMessageProcessor;

public class HttpRelativePathRouter extends
		AbstractInterceptingMessageProcessor implements Interceptor {
	private MuleContext muleContext;

	public void setMuleContext(MuleContext context) {
		this.muleContext = context;
	}

	public MuleEvent process(MuleEvent event) throws MuleException {
		MuleMessage message = event.getMessage();
		String flowName = message.getInboundProperty("http.relative.path");
		Flow flow = null;
		while (flowName.length() > 0) {
			//System.out.println("checkflowName: " + flowName);
			flow = (Flow) muleContext.getRegistry().lookupFlowConstruct(
					flowName);
			if (flow == null) {
				int idx = flowName.lastIndexOf("/");
				if (idx <= 0) {
					break;
				}
				flowName = flowName.substring(0, idx);
			} else {
				break;
			}
		}
		if (flow == null) {
			flow = (Flow) muleContext.getRegistry().lookupFlowConstruct(
					"DefaultFlow");
		}
		if (flow == null) {
			throw new DefaultMuleException(
					MessageFactory
							.createStaticMessage("DefaultFlow is not defined"));
		}
		return flow.process(event);
	}
}

Use the following xml to include the interceptor in the inbound HTTP workflow:

<custom-interceptor class="org.mule.httprouter.HttpRelativePathRouter" />
Advertisement

Memcached Component for Mule

This code snippet can be used for Mule application workflows that require the ability to place a serializable object into a memcached or pull a serialized object from memcached.  The component is implemented as an Anypoint custom transformer that uses the payload as the source of the put and the target of the get operations.

Usage

The following xml is an Anypoint application with a workflow that performs a get and a second workflow that performs a put.  Both use an Http inbound endpoint to trigger the memcached operation.  Note that the transformer uses a spring bean to configure an xmemcached client builder (the factory).  Transformer properties are used to define the operation to be performed (put or get), the key value to use in the memcached and memcachedClientBuilder references the xmemcached client builder defined in the spring bean.  For the put operation, the expire property defines the number of seconds to hold the cache entry before it is evicted from memcached.

Sample Anypoint Application XML

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http"
	xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core"
	xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
	xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.5.1"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
	<spring:beans>
		<spring:bean id="memcachedClientBuilder" scope="prototype"
			name="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
			<!-- list of memcached server ports. -->
			<spring:constructor-arg value="192.168.191.129:11211" />
			<spring:property name="connectionPoolSize" value="5"></spring:property>
			<spring:property name="commandFactory">
				<spring:bean class="net.rubyeye.xmemcached.command.BinaryCommandFactory"></spring:bean>
			</spring:property>
			<spring:property name="sessionLocator">
				<spring:bean
					class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"></spring:bean>
			</spring:property>
			<spring:property name="transcoder">
				<spring:bean
					class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
			</spring:property>
		</spring:bean>
	</spring:beans>

	<flow name="putFlow" doc:name="putFlow">
		<http:inbound-endpoint exchange-pattern="request-response"
			host="localhost" port="8081" path="put" doc:name="HTTP"/>
        <object-to-string-transformer doc:name="Object to String"/>
		<logger message="#[payload]" level="INFO" doc:name="Logger" />
		<custom-transformer class="org.pdd.memcached.MemcachedTransformer"
			doc:name="Java">
			<spring:property name="operation" value="put" />
			<spring:property name="key" value="abc" />
            <spring:property name="memcachedClientBuilder" ref="memcachedClientBuilder"/>
            <spring:property name="expire" value="30"/>
		</custom-transformer>
	</flow>

	<flow name="getFlow" doc:name="getFlow">
		<http:inbound-endpoint exchange-pattern="request-response"
			host="localhost" port="8082" path="get" doc:name="HTTP" />
		<logger message="#[payload]" level="INFO" doc:name="Logger" />
		<custom-transformer class="org.pdd.memcached.MemcachedTransformer"
			doc:name="Java">
			<spring:property name="operation" value="get" />
			<spring:property name="key" value="abc" />
            <spring:property name="memcachedClientBuilder" ref="memcachedClientBuilder"/>
		</custom-transformer>
	</flow>
</mule>

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.pdd.memcached;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;

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 org.mule.transformer.AbstractMessageTransformer;
import org.mule.transformer.AbstractTransformer;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * Get or put a payload using memcached entry referenced by a key value. This
 * requires setting up a Spring Bean in the flow to define the memcached client
 * builder. 
    
		
                
                
                
                
                        
                
                
                        
                
                
                        
                
        
    
 * 
 * 
 * Then configure a custom java transformer in the flow. For instance: 
 		
			
			
            
		
* 
 * 
 * @author peterdunworth
 * 
 */
public class MemcachedTransformer extends AbstractMessageTransformer {

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

	private static String operator_msg = "operation property must be specified as either get or put";

	private MemcachedClientBuilder memcachedClientBuilder = null;
	// get or put
	private String operation = "get";
	private String key = null;
	private String resultClass = null;
	private String expire = null;
	private int ttl = 54000; // seconds=15min

	public MemcachedClientBuilder getMemcachedClientBuilder() {
		return memcachedClientBuilder;
	}

	public void setMemcachedClientBuilder(
			MemcachedClientBuilder memcachedClientBuilder) {
		this.memcachedClientBuilder = memcachedClientBuilder;
	}

	public String getOperation() {
		return operation;
	}

	public void setOperation(String operation) {
		this.operation = operation.trim().toLowerCase();
	}

	public String getResultClass() {
		return resultClass;
	}

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

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key.trim();
	}

	public String getExpire() {
		expire = Integer.toString(ttl);
		return expire;
	}

	public void setExpire(String expire) {
		this.ttl = Integer.parseInt(expire);
		this.expire = expire;
	}

	public int getTtl() {
		return ttl;
	}

	public void setTtl(int ttl) {
		this.ttl = ttl;
	}

	@Override
	public Object transformMessage(MuleMessage message, String encoding)
			throws TransformerException {

		if (memcachedClientBuilder == null) {
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("Missing Spring bean memcachedClientBuilder"));
		}
		if (operation == null || operation.isEmpty()) {
			throw new TransformerException(
					MessageFactory.createStaticMessage(operator_msg));
		}
		if (key == null || key.isEmpty()) {
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("key property must be the cache key value"));
		}
		try {
			MemcachedClient memcachedClient = memcachedClientBuilder.build();

			if (operation.equals("get")) {
				return memcachedClient.get(key);
			} else if (operation.equals("put")) {
				memcachedClient.set(key, ttl, message.getPayload());
				return message.getPayload();
			} else {
				throw new TransformerException(
						MessageFactory.createStaticMessage(operator_msg));
			}
		} catch (TransformerException e) {
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			throw new TransformerException(
					MessageFactory.createStaticMessage("transformMessage caught Exception: "
							+ e.toString()), e);
		}
	}
}

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&#8243; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”&gt;
<modelVersion>4.0.0</modelVersion>
<groupId>org.pdd.memcached</groupId>
<artifactId>memcached-transformer</artifactId>
<version>0.0.1</version>
<name>memcached transformer</name><properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><mule.version>3.5.0</mule.version>
<eclipsePluginVersion>2.8</eclipsePluginVersion>
<jdkName>JavaSE-1.7</jdkName>
<jdk.version>1.7</jdk.version>
<junit.version>4.9</junit.version>
</properties><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>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.0.0</version>
</dependency>

<dependency>
<groupId>org.mule</groupId>
<artifactId>mule-core</artifactId>
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mulesoft.muleesb.modules</groupId>
<artifactId>mule-module-boot-ee</artifactId>
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-module-spring-config</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.cloveretl</groupId>
<artifactId>cloveretl-engine</artifactId>
<version>${mule.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

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

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).

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>