Friday, 22 March 2013

Create Custom Transformer in mule 3.3 using Annotation

Creating Custom Transformers in mule 3.3 is a lot easier using annotation rather than extending AbstractMessageTransformer.
Let's take an example as to how to do it .
Suppose we want to read json from an input file and want to convert it in java object. Although mule do it automatically as it has built in support for Jackson , but sometimes you want to have your own ObjectMapper and other things like this.Then you can use your own transformer.You can create any kind of transformer as long as return type and source type of transformer are not ambiguous with other transfomers.
here is our flow :

First of all create a Transformer class like this along with all the annotations. In this transformer input type is InputStream and output is our JSonBean Object.
import java.io.IOException;
import java.io.InputStream;

import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.mule.api.annotations.ContainsTransformerMethods;
import org.mule.api.annotations.Transformer;


@ContainsTransformerMethods
public class MyTransformer {
 
 @Transformer
 public JsonBean toJson(InputStream src) throws JsonParseException, JsonMappingException, IOException
 {
  ObjectMapper mapper = new ObjectMapper();
  return (JsonBean)mapper.readValue(src,JsonBean.class);
 }

}
and this is our Component which takes its parameter as Converted java object not json. Do not forget to use @Payload annotation , because from this , mule will identify that it needs to apply transfomer to convert incoming inputstream in payload to JsonBean type.
import org.mule.api.MuleMessage;
import org.mule.api.annotations.param.Payload;


public class TestComponent {
 

 public JsonBean callIt(@Payload JsonBean bean)
 {
  System.out.println(bean.getCustEm());
  return bean;
 }
 
 

}
This is the corresponding java bean for input json


public class JsonBean {
 /**
  * 
  */
 
 private String CustNo ;
 
 private String result;
 public String getResult() {
  return result;
 }
 public void setResult(String result) {
  this.result = result;
 }
 public String getCustNo() {
  return CustNo;
 }
 public void setCustNo(String custNo) {
  this.CustNo = custNo;
 }
 
 

}
<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" 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="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd 
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 ">
 <spring:bean id="nn" name="nn" class="MyTransformer"/>
 <!-- <auto-transformer returnClass="JsonBean.class"/> -->
    <flow name="customTransformertestFlow1" doc:name="customTransformertestFlow1">
     
        <file:inbound-endpoint path="/home/somani" pollingFrequency="100000" responseTimeout="10000" doc:name="File">
            <file:filename-regex-filter pattern="abc.json" caseSensitive="false"/>
        </file:inbound-endpoint>
        <component class="TestComponent" doc:name="Java">
        </component>
    </flow>
    
</mule>
Declare your custom transformer bean in to xml file , otherwise mule won't be able to find this transformer. I tried using auto-transfomer tag also but it was not working.
There is no need to fit your transformer in mule flow . As mule will automatically detect and apply appropriate transformer based on input and output type of message payload .
If you try to do this you will get error like this :
Cannot convert value of type [X] to required type [Y] for property 'messageProcessors[0]': no matching editors or conversion strategy found .
If you really need to fit the transformer in flow , you should use AbstractMessageTransformer as it is the Type of org.mule.api.processor.MessageProcessor which is necessary for calling transformer explicitly.


Post and comment if you have any questions !!