The Difference of Two Maps

I recently needed to determine the difference between an inbound set of data for an identifier (provided as a JSON object) and the same identifier stored in persistent storage.

Turns out that by converting the inbound data into a Map and the persisted record also into a Map, the com.google.collect.Maps class can be used to compare the two Maps. The following code shows how to return the difference as a JSON object containing the field name (key), the inbound value (left), the associated stored value (right) as well as any inbound data that was unmatched in the stored data.

Code


package org.pdd.util;

import java.util.ArrayList;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.MapDifference;
import com.google.common.collect.MapDifference.ValueDifference;

public class Differences {
	String key = "";
	Object left = null;
	Object right = null;

	public Object getLeft() {
		return left;
	}

	public void setLeft(Object left) {
		this.left = left;
	}

	public Object getRight() {
		return right;
	}

	public void setRight(Object right) {
		this.right = right;
	}

	public String getKey() {
		return key;
	}

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

	/**
	 * Compare the left side map against the right side map and return a json
	 * object containing the differences in the values and the values that are
	 * provided on the left side but not provided on the right side.
	 * 
	 * This is intended to be used in comparing an input set of values (the left
	 * side) against a stored set of values (the right side), with the intention
	 * of updating the stored values with the updated and/or new values from the
	 * input.
	 * 
	 * @param left
	 *            the input values
	 * @param right
	 *            the stored values
	 * @return A JSON formatted string of the update values
	 */
	public static String arrayOfDifferences(Map left,
			Map right) {
		ArrayList differences = new ArrayList();

		MapDifference valueDifferences = com.google.common.collect.Maps
				.difference(left, right);
		Map<String, ValueDifference> diff = valueDifferences
				.entriesDiffering();
		for (String key : diff.keySet()) {
			ValueDifference values = diff.get(key);
			Differences difference = new Differences();
			difference.setKey(key);
			difference.setLeft(values.leftValue());
			difference.setRight(values.rightValue());
			differences.add(difference);
		}
		Map onlyOnLeft = valueDifferences.entriesOnlyOnLeft();
		for (String key : onlyOnLeft.keySet()) {
			Differences difference = new Differences();
			difference.setKey(key);
			difference.setLeft(onlyOnLeft.get(key));
			difference.setRight(null);
			differences.add(difference);
		}
		ObjectMapper mapper = new ObjectMapper();
		try {
			return (String) mapper.writeValueAsString(differences);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			return "[]";
		}
	}
}

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" />

OAuth2 Provider User Name

In many uses cases for API’s, the authenticated user id (or user name) is required in order to determine further access rights to resources controlled by the API.  The Anypoint Platform API OAuth2 Provider policy provides user authentication which can be captured by the API proxy and passed along to the API implementations.  To pass a “user_id” property on to the API implementation from the proxy, edit the proxy generated by the API Platform and insert the following property component:

<set-property propertyName="user_id"
  value="#[flowVars['mule.oauth2.access_token_store_holder'].resourceOwnerAuthentication.principal.username]"
doc:name="Add user_id" />

Controlling Mule Application Flow Thread Concurrency

There is a page in the Mulesoft documentation regarding the use of threads and thread pools in an Anypoint application. That documentation is here.

The following picture is from that page and illustrates where threads are used during the execution of an Anypoint application:

thread_pooling
There is a lot being shown in the picture. In particular, note that if a workflow is a:

  • synchronous process, then the receiver thread is used to execute the entire flow from the inbound endpoint up to the outbound endpoint,
  • asynchronous process, then the inbound endpoint, the flow and the outbound endpoint each have a pool of threads and phase (or stage) is executed in its own thread

An endpoint’s connector configuration contains the thread pooling information in the receiver-threading-profile and dispatcher-threading-profile child elements of the connector configuration. For example, a pair of VM inbound and outbound endpoints might have their threading limited to four concurrently running threads by the following code:

<vm:connector name="SFDC-Q" validateConnections="true" doc:name="SFDC-Q">
  <receiver-threading-profile
    maxThreadsActive="4"
    poolExhaustedAction="WAIT"
    threadWaitTimeout="-1"/>
  <dispatcher-threading-profile
    maxThreadsActive="4"
    poolExhaustedAction="WAIT"
    threadWaitTimeout="-1"/>
</vm:connector>
<flow name="collectInput" doc:name="collectInput">
  ...
  <vm:outbound-endpoint exchange-pattern="one-way"
    doc:name="toSFDC-Q" connector-ref="SFDC-Q" address="vm://sfdcQ" />
</flow>
<flow name="processFlow" doc:name="processFlow">
 <vm:inbound-endpoint exchange-pattern="one-way"
 doc:name="fromSFDC-Q" connector-ref="SFDC-Q" address="vm://sfdcQ" />
  ...
</flow>

This defines the pool of available threads going out to an endpoint and coming into an endpoint, but does not necessarily define the pool of threads that run the flow. For synchronous flows, the receiver thread is used to execute the flow components. For asynchronous flows, a thread from the flow’s thread pool is used to execute flow component’s. So for asynchronous flows, the flow’s thread pool is used to control the number of concurrently executing threads. The flow’s processingStrategy is where the minimum and maximum available threads are configured. The processingStrategy for a flow is specified as a reference to a Global Element (the Global Processing Strategies) in application. An example of setting the maximum number of currently running threads for a flow to four is shown below:

<queued-asynchronous-processing-strategy doc:name="Queued Asynchronous Processing Strategy"
  name="Queued_Asynchronous_Processing_Strategy" 
  maxThreads="4" 
  minThreads="4"/>
<flow name="processFlow" doc:name="processFlow"
    processingStrategy="Queued_Asynchronous_Processing_Strategy" 
    initialState="started">
  <vm:inbound-endpoint exchange-pattern="one-way" doc:name="fromSFDC-Q"
    connector-ref="SFDC-Q" address="vm://sfdcQ" />
  ...
</flow>

More later…

Integrating Mule application build with Jenkins

Just ran across this bit of information for integrating Mule application builds with Jenkins as part of a continuous integration.  The reference is from the Mulesoft Knowledge Center. Note that the variables (ie: ${var_name} are all standard Jenkins values.  Here is what the knowledge center post says:

When leveraging continuous integration, we might want to publish the newly built applications to MMC so they can get easily deployed.
This can be done using the MMC REST API. Jenkins as well provides a useful set of information that can be leveraged to achieve this goal.

Configuration Steps:

 

1) Configure a new Maven process with your source code repository and adapt it to your preferences.

2) Add a new command line ‘Post Step’ that runs only upon successful builds, the contents of the post-step would be the following:
 
curl –basic -u admin:admin -F file=@${WORKSPACE}/target/${POM_ARTIFACTID}-${POM_VERSION}.zip -F name=${POM_ARTIFACTID} -F version=1.0 –header ‘Content-Type: multipart/form-data’ http://localhost:8080/mmc/api/repository
This way the resulting application will be published to the MMC repository and it will be ready for you to create a deployment. Please note that you would need to adapt the MMC URL to match your infrastructure.
For more information about the options you have, please visit the MMC REST API documentation page:

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>

Mark Down Plugins for Eclipse and Anypoint Studio

Editing and viewing mark down annotated documents in Eclipse and Anypoint Studio with a simple text editor is okay…but there are a couple of plugins that can be helpful as well.

 

GFM Viewer

This provides a GitHub flavored view of files with the ‘.md’ extension when viewing them in Eclipse or Anypoint Studio.  The links don’t work for me, but just seeing the page itself is a nice to have.  The last time I added this plug-in, it was hard to find the update site, so:

The Eclipse update site for this plugin is: https://raw.github.com/satyagraha/gfm_viewer/master/p2-composite/.

The documentation is in the GitHub project: https://github.com/satyagraha/gfm_viewer/blob/master/README.md;

 

Mark Down Text Editor

A companion to the GFM Viewer is Markdown Text Editor which provides a color coded editor special built for editing markdown formatted text files (identified with the ‘.md’ extension).

The Eclipse update site for this plugin is: http://dl.bintray.com/enide/Markdown/1.1.0/
The documentation is in the Eclipse Marketplace: http://marketplace.eclipse.org/content/markdown-text-editor

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

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>