In Mule, am trying to validate a XML against XSD.
In my flow am using schema-validation-filter component nested with in message-filter component and working as expected.
but my question is, if XML fails, how do I capture the error details in logger component and based on results in need to navigate the flow.
Basically am looking for a MEL to print the error description on the console
Note: "returnResult" is set to false, because i need, to do further operations on the XML.
here is my configuration Flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" 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.4.0" 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/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<mulexml:schema-validation-filter schemaLocations="D:\MuleStudio\workspace\exceptiontest\src\test\resources\sample.xsd" returnResult="false" name="Schema_Validation" doc:name="Schema Validation"/>
<flow name="ExceptionTestFlow2" doc:name="ExceptionTestFlow2">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" path="dataQ" doc:name="HTTP"/>
<expression-filter expression="#[message.payload != '/favicon.ico' ]" doc:name="Expression does't allow /favicon.ico"/>
<set-payload value="<data>
<books>
<book edition='1.0'>
<auth> auth</auth>
<title>title</title>
<pulbisher>pub</pulbisher>
</book>
</books>
</data>
" doc:name="XML is set as payload tp the current flow"/>
<logger message="::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Actual Flow Started :::::::::::::::::::::::::::::::::::::::::::::::::" level="INFO" doc:name="indicates Actual Flow Started Logger"/>
<logger message="paylad is :::: #[payload] :::::" level="INFO" doc:name="Prints current Payload"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="dataQ" doc:name="VMQ_stores current xml which needs to be validated_senderQ"/>
</flow>
<flow name="ExceptionTestFlow1" doc:name="ExceptionTestFlow1">
<vm:inbound-endpoint exchange-pattern="one-way" path="dataQ" doc:name="VMQ_stores current xml which needs to be validated_receiverQ"/>
<logger message="::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Flow Started :::::::::::::::::::::::::::::::::::::::::::::::::" level="DEBUG" doc:name="indicates Flow Started Logger"/>
<message-filter doc:name="filter to validate xml against xsd" throwOnUnaccepted="true">
<filter ref="Schema_Validation"/>
</message-filter>
<logger message=" validation is true and the payload is :::: #[payload]" level="INFO" doc:name="current Payload"/>
<logger message="::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: End of Actual Flow:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::" level="INFO" doc:name="indicates Flow End Logger"/>
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="exception.causedBy(org.mule.api.routing.filter.FilterUnacceptedException)" enableNotifications="false" doc:name="FilterUnacceptedException">
<logger message="::::::::::::::::::::::::::::::::::: in FilterUnacceptedException :::::::::::::::::::::::::" level="ERROR" doc:name="indicates FilterUnacceptedException Flow Started Logger"/>
<set-payload value="The request cannot be processed, the error is #[exception.getMessage()]" doc:name="Set Payload"/> <!-- [1] -->
<set-property propertyName="http.status" value="500" doc:name="Property"/>
<logger message=":::::::::::: end of FilterUnacceptedException with a payload as #[message.payload] ::::::::::::" level="INFO" doc:name="indicates FilterUnacceptedException End Logger"/> <!-- [2] -->
</catch-exception-strategy>
<catch-exception-strategy enableNotifications="false" doc:name="default">
<logger message=":::::::::::::::::::::: in default::::::::::::::::::::::::::::" level="ERROR" doc:name="indicates defaultException Flow Started Logger"/>
<set-payload value="The request cannot be processed, the error is #[exception.getSummaryMessage()]" doc:name="Set Payload"/>
<logger message="::::::::::::::::::::::::::::::::::::::::::::: END of Default Exception :::::::::::::::::::::::::::::::::::" level="INFO" doc:name="indicates DefaultException End Logger"/> <!-- [1] -->
<!-- [2] -->
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
<flow name="Flow_If_XML_not_valid" doc:name="Flow_If_XML_not_valid">
<logger message=":::::::::::::::::::::::::::: #[payload] :::::::::::::: onThrow ::::::" level="INFO" doc:name="Should Print error description"/>
</flow>
</mule>
Have added an exception strategy that gives the following output:
Message has been rejected by filter. Message payload is of type: String
Code : MULE_ERROR--2
Exception stack is:
1. Message has been rejected by filter. Message payload is of type: String (org.mule.api.routing.filter.FilterUnacceptedException)
... http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/routing/filter/FilterUnacceptedException.html)..
I need to be able to pinpoint which field is causing the problem.
Since the filter is configured to throw on unaccepted, you need to have an exception strategy in place in order to deal with the error.
Read: http://www.mulesoft.org/documentation/display/current/Error+Handling
You don't, see the SchemaValidationFilter source file. The SAXException is just catch and log (in debug). I think you need make your own SchemaValidationFilter. (Inherit Mule Validator)
package what.the.fuck.customFilter;
import java.io.IOException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMResult;
import org.mule.api.MuleMessage;
import org.mule.api.transport.PropertyScope;
import org.mule.module.xml.filters.SchemaValidationFilter;
import org.xml.sax.SAXException;
public class SchemaValidationFilterWithTrace extends SchemaValidationFilter {
public final static String SAX_ERROR_PROPERTIES = "SAX_ERROR_PROPERTIES";
public final static boolean RETURN_RESULT = false;
public final static String SCHEMA_LOCATION = "what.the.fuck.xsd";
public SchemaValidationFilterWithTrace(){
super();
super.setReturnResult(false);
super.setSchemaLocations(SCHEMA_LOCATION);
}
/**
* Accepts the message if schema validation passes.
*
* #param message The message.
* #return Whether the message passes schema validation.
*/
#Override
public boolean accept(MuleMessage message)
{
Source source;
try
{
source = loadSource(message);
}
catch (Exception e)
{
if (e instanceof RuntimeException)
{
throw (RuntimeException) e;
}
if (logger.isInfoEnabled())
{
logger.info("SchemaValidationFilter rejected a message because there was a problem interpreting the payload as XML.", e);
}
return false;
}
if (source == null)
{
if (logger.isInfoEnabled())
{
logger.info("SchemaValidationFilter rejected a message because the XML source was null.");
}
return false;
}
DOMResult result = null;
try
{
if (super.isReturnResult())
{
result = new DOMResult();
createValidator().validate(source, result);
}
else
{
createValidator().validate(source);
}
}
catch (SAXException e)
{
message.setProperty(SAX_ERROR_PROPERTIES, e.getMessage(), PropertyScope.OUTBOUND);
if (logger.isDebugEnabled())
{
logger.debug(
"SchemaValidationFilter rejected a message because it apparently failed to validate against the schema.",
e);
}
return false;
}
catch (IOException e)
{
if (logger.isInfoEnabled())
{
logger.info(
"SchemaValidationFilter rejected a message because there was a problem reading the XML.",
e);
}
return false;
}
finally
{
if (result != null && result.getNode() != null)
{
message.setPayload(result.getNode());
}
}
if (logger.isDebugEnabled())
{
logger.debug("SchemaValidationFilter accepted the message.");
}
return true;
}
}
Related
How to find Http error payload in exception object ?
System 1 -> Call's Mule server . Mule server -> Docusign / some one else.
Docusign / some one returns 400 error with json payload (includes errorCode etc)
I need to return the exact details back to System 1.
how will i do this?
1) I did try to add all codes in success codes 200..599, then even error is having 200 ok . This will cause more problem, because I have to add lot of choice routing as some flows are having more data conversion.
2) Ideal soln -> Raise exception as usual. This has to be caught in choice exception. Now I have to send the same status_code and the json response back to the caller.
Issue -? how can i find the payload returned by HTTP in exception object. Where is stored in exception object.
Here is the sample- one way of handling this kind of scenario , use validation Component to throw exception and capture in your mainflow either by exceptionHandling or by APIKIT ExceptionHandling
<flow name="routeexceptionFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Configuration" path="/in" method="POST" doc:name="HTTP">
<http:success-status-code-validator values="200..599"/>
</http:request>
<validation:is-false config-ref="Validation_Configuration" message="#[payload]" exceptionClass="nz.co.exception.BadRequestException" expression="#[message.inboundProperties['http.status'] ==400]" doc:name="Validate Bad Request"/>
<validation:is-false config-ref="Validation_Configuration" message="#[payload]" expression="#[message.inboundProperties['http.status'] !=200]" doc:name="Capture all other Exceptions"/>
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy when="#[exception.causeMatches('nz.co.exception.BadRequestException')]" doc:name="Catch Exception Strategy">
<set-payload value="#[exception.message]" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="****log all other exception****" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
</flow>
Add this class in your java folder
package nz.co.exception;
public class BadRequestException extends Exception {
private static final long serialVersionUID = 8546839078847602529L;
public BadRequestException() {
super();
}
public BadRequestException(String message) {
super(message);
}
public BadRequestException(Throwable t) {
super(t);
}
public BadRequestException(String message, Throwable t) {
super(message, t);
}
}
In your project if you are using APIKIT Router , then instead of using exceptionHandling as above, add directly nz.co.exception.BadRequestException in 400 ReturnCode apikitExceptionHandling.
I created a simple flow which creates a list of names transforms it. The transformer throws an IllegalArgumentException to break the flow. Unfortunately, the failureExpression does not work even though an exception is thrown. It doesn't match any exceptions. I have included the flow and the transformer.
Here is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
xmlns:http="http://www.mulesoft.org/schema/mule/http" 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" xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/scripting
http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.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
http://www.mulesoft.org/schema/mule/vm
http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/http
http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<spring:beans>
<spring:bean name="transf" class="com.until.sucessful.tests.StringAppenderTransformer" />
<spring:bean id="objectStore" class="org.mule.util.store.SimpleMemoryObjectStore" />
</spring:beans>
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration" />
<flow name="untilsuccessfultestsFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/mytest" doc:name="HTTP" />
<splitter expression="#[xpath3('//Names')]" doc:name="Splitter" />
<until-successful maxRetries="5" millisBetweenRetries="5000" doc:name="Until Successful" objectStore-ref="objectStore" failureExpression="#[exception is java.lang.IllegalArgumentException)]">
<vm:outbound-endpoint path="process-vm" exchange-pattern="request-response" />
</until-successful>
<logger level="INFO" message="After the scoped processor :: #[payload]" doc:name="Logger" />
</flow>
<flow name="processorFlow">
<vm:inbound-endpoint path="process-vm" exchange-pattern="request-response" />
<logger level="INFO" message="Before component #[payload]" doc:name="Logger" />
<transformer ref="transf" />
</flow>
</mule>
Here is my Transformer
public class StringAppenderTransformer extends AbstractTransformer {
#Override
protected Object doTransform(Object src, String enc) throws TransformerException {
String payload = (String) src;
List<String> results = new ArrayList<>();
System.out.println("Upon entry in transformer payload is :: " + payload);
System.out.println("About to return from transformer payload is :: " + payload.split("\\s+"));
int i = 1;
for (String args : payload.split("\\s+")) {
System.out.println("" + i + " " + args);
i++;
if (args != null && args.trim().equals("")) {
results.add(args);
} else {
throw new IllegalArgumentException("Break the Flow!!!!!!");
}
}
return results;
}
}
According to documentation :
https://docs.mulesoft.com/mule-user-guide/v/3.5/until-successful-scope
failureExpression
Specifies an expression that, when it evaluated to true, determines
that the processing of one route was a failure. If no expression is
provided, only an exception will be treated as a processing failure.
So 2 options, remove that expression or be sure that the MEL return true. #[exception.causeMatches("java.lang.IllegalArgumentException")]
I am using Anypoint Studio 6.1 and Mule 3.8.1 and want to return an Exception message with the "\n" returned as a new line. I am trying to use System.getProperty("line.separator") but the "\n" still appear in the message as text and not a new line.
How can I get this to work?
XML Test Flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" 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"
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">
<flow name="tempflowFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test-flow" allowedMethods="GET" doc:name="HTTP"/>
<set-payload value="{
"Exception": {
"status": -1,
"description": "\nJson content is not compliant with schema\ncom.github.fge.jsonschema.core.report.ListProcessingReport: failure\n--- BEGIN MESSAGES ---\nerror: object has too many properties (found 2 but schema requires at most 1)\n level: \"error\"\n schema: {\"loadingURI\":\"file:/C:/temp.json#\",\"pointer\":\"/properties/field1\"}\n instance: {\"pointer\":\"/field1\"}\n domain: \"validation\"\n keyword: \"maxProperties\"\n found: 2\n required: 1\n--- END MESSAGES ---\n (org.mule.module.json.validation.JsonSchemaValidationException)."
}
}" encoding="UTF-8" mimeType="application/json" doc:name="Set Payload"/>
<logger message="#[payload.replace("\n", System.getProperty('line.separator'))]" level="INFO" doc:name="Logger"/>
<set-payload value="#[payload.replace("\n", System.getProperty('line.separator'))]" encoding="UTF-8" mimeType="application/json" doc:name="Set Payload"/>
</flow>
</mule>
Thanks
Looks like you need to escape the newline character. Also, use single quotes (') instead of double quotes (") inside MEL expression.
<logger message="#[payload.replace('\\n', System.getProperty('line.separator'))]" level="INFO"
doc:name="Logger" />
<set-payload value="#[payload.replace('\\n', System.getProperty('line.separator'))]" encoding="UTF-8"
mimeType="application/json" doc:name="Set Payload" />
Above code seems to work:
INFO 2017-02-09 18:03:09,349 [Mule.app.deployer.monitor.1.thread.1] org.mule.module.launcher.MuleDeploymentService:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Started app 'test2' +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO 2017-02-09 18:03:17,280 [[test2].HTTP_Listener_Configuration.worker.01] org.mule.api.processor.LoggerMessageProcessor: { "Exception": { "status": -1, "description": "
Json content is not compliant with schema
com.github.fge.jsonschema.core.report.ListProcessingReport: failure
--- BEGIN MESSAGES ---
error: object has too many properties (found 2 but schema requires at most 1)
level: \"error\"
schema: {\"loadingURI\":\"file:/C:/temp.json#\",\"pointer\":\"/properties/field1\"}
instance: {\"pointer\":\"/field1\"}
domain: \"validation\"
keyword: \"maxProperties\"
found: 2
required: 1
--- END MESSAGES ---
(org.mule.module.json.validation.JsonSchemaValidationException)." } }
Mule log
Mule Flows:
<jersey:resources doc:name="REST">
<component class="com.test.qb.rest.MapIIFContent"/>
<jersey:exception-mapper class="com.test.qb.exception.IIFExceptionMapper" />
</jersey:resources>
<catch-exception-strategy doc:name="Audit Exception" >
<set-variable variableName="status" value="Failure" doc:name="Status"/>
<flow-ref name="QB:audit" doc:name="audit"/>
<http:response-builder status="500" contentType="application/json" doc:name="Status Code"/>
</catch-exception-strategy>
<logger message=" ===Reached here====" level="INFO" doc:name="Logger"/> <!-- Line 10-->
Java Rest component:
Rest Component:
try{
String s =null;
s.toString();// throw nullpointer exception
} catch (IIFException e) {
return Response.status(500).entity(e.getMessage()).type("Application/json").build();
}
return Response.ok(res).build();
When I run this, it goes to catch block in Java Rest component with error status as 500.
But in Mule flows i am expecting flow should reach
'catch-exception-strategy doc:name="Audit Exception" >
block, but it doesn't reach there, instead it reaches to line 10. How do I handle this?
I made rest component to throw checked custom exception instead of returning Rest Response status:
try{
String s =null;
s.toString();
} catch (IIFException e) {
throw new IIFException(e.toString(),e.getCause());
}
return Response.ok(res).build();
And in my exception flows, made it as:
<catch-exception-strategy doc:name="Audit Exception" >
<expression-component doc:name="Create error response"><![CDATA[#[payload = "{\"status\":\"error\", \"message\":\"" + exception.cause.message + "\"}"]]]></expression-component>
<http:response-builder status="500" contentType="application/json" doc:name="Status Code"/>
</catch-exception-strategy>
I need to send multiple response from a mule flow one to a http endpoint which would be JSON and another to an SMTP endpoint where the recipient receives a custom email. If I use a transformer to transform the json respone which is default both endpoints receive the same custom email format. So how can I send the default JSON response to the http endpoint and the Custom Transformer generated email to the smtp endpoint below is my flow and Custom Transformer
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:smtp="http://www.mulesoft.org/schema/mule/smtp" xmlns:smtps="http://www.mulesoft.org/schema/mule/smtps" xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper" xmlns:email="http://www.mulesoft.org/schema/mule/email" xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:jersey="http://www.mulesoft.org/schema/mule/jersey" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:json="http://www.mulesoft.org/schema/mule/json" 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.4.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/jersey http://www.mulesoft.org/schema/mule/jersey/current/mule-jersey.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd
http://www.mulesoft.org/schema/mule/email http://www.mulesoft.org/schema/mule/email/current/mule-email.xsd
http://www.mulesoft.org/schema/mule/ee/data-mapper http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.mulesoft.org/schema/mule/smtps http://www.mulesoft.org/schema/mule/smtps/current/mule-smtps.xsd">
<data-mapper:config name="json2_to_json" transformationGraphPath="json2_to_json.grf" doc:name="json_to_json"/>
<flow name="jirarestFlow3" doc:name="jirarestFlow3">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="6767" doc:name="HTTP" contentType="application/json"/>
<logger message="This is from hari #[message.payload]" level="DEBUG" doc:name="Logger"/>
<data-mapper:transform config-ref="json2_to_json" doc:name="JSON To JSON"/>
<logger level="DEBUG" doc:name="Logger" message="This is from Data Mapper #[json:fields/priority/id]"/>
<set-variable variableName="myPayload" value="#[json:fields/reporter/emailAddress]" doc:name="tmpPayload"/>
<logger message="MyPayload is #[myPayload]" level="DEBUG" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="9999" path="rest/api/2/issue/" method="POST" user="" password="" contentType="application/json" doc:name="HTTP"/>
<response>
<!--set-variable variableName="responsePayload" value="#[message.payload]" doc:name="respPayload"/-->
<!--http:response-builder doc:name="HTTP Response Builder" contentType="text/plain" status="200"/-->
<!--expression-transformer doc:name="Expression" /-->
<custom-transformer class="org.hhmi.transformer.EmailBodyTransformer" doc:name="Java"/>
<smtps:outbound-endpoint host="smtp.gmail.com" port="465" user="pandalai" password="soapui67" to="#[myPayload]" from="pandalai#gmail.com" subject="Jira Ticket" responseTimeout="10000" mimeType="text/plain" doc:name="SMTP">
<email:string-to-email-transformer doc:name="Email to String"/>
</smtps:outbound-endpoint>
</response>
</flow>
</mule>
Custom Transformer
package org.xxx.transformer;
import org.apache.log4j.Logger;
import org.xxx.dto.JsonBean;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageTransformer;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
public class EmailBodyTransformer extends AbstractMessageTransformer {
public static Logger logger = Logger.getLogger(EmailBodyTransformer.class);
#Override
public Object transformMessage(MuleMessage message, String outputEncoding)
throws TransformerException {
// TODO Auto-generated method stub
StringBuffer html = new StringBuffer();
Map<String,String> map = new HashMap<String,String>();
ObjectMapper mapper = new ObjectMapper();
JsonBean jBean = new JsonBean();
try {
logger.debug("EmailBodyTransformer payload "
+ message.getPayloadAsString());
logger.debug("EmailBodyTransformer class " + message.getClass());
map = mapper.readValue(message.getPayloadAsString(),
new TypeReference<HashMap<String,String>>(){});
jBean.setId(map.get("id"));
jBean.setKey(map.get("key"));
jBean.setSelf(map.get("self"));
System.out.println("EmailBodyTransformer id from map: "+ jBean.getId());
System.out.println("EmailBodyTransformer map: "+ map);
/* html.append("");
html.append("");
html.append("");
html.append("Dear ").append(jBean.getId()).append(" ");
html.append("Thank you for your order. Your transaction reference is: <strong>");
html.append(jBean.getKey()).append("</strong>");
html.append("");*/
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return message;
//return html;
}
}
The <response></response> tags mean, that whatever you put there will be put into your http:inbound-endpoint response. Since smtp is asynchronous, it will be ignored in the response phase, and the block will return whatever it gets from your custom transformer.
The solution is to move the contents inside the <response></response> block into an <async></async> block, so your custom transformer will not interfere with the http response. Inside the <response></response> block you will need just an <object-to-string-transformer> to transform your http:outbound-endpoint into a string.
EDIT:
Move the <object-to-string-transformer> after the http:outbound-endpoint and change your transformer to take String, not input stream. Otherwise the input stream gets closed once either of the two readers reads it. You will not need the <response></response> after this.
Your requirement is exactly what mule-requester-module is based on:
http://java.dzone.com/articles/introducing-mule-requester
example project: https://github.com/mulesoft/mule-module-requester
This module allows you to asynchronously do two things.
Hope this helps