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
Related
I'm trying to convert JSON to a pdf file but when I am trying to open the file getting the "Failed to load PDF document" error in mule 4 (runtime 4.2.1).
How can I fix this issue?
code:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
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:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="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/core
http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="79ef9cde-39c4-449a-8cac-9aeb3be30c27" >
<http:listener-connection host="0.0.0.0" port="8084" />
</http:listener-config>
<file:config name="File_Config" doc:name="File Config" doc:id="d67cbdb7-3bc8-4f04-8d7f-862c539f5f3f" >
<file:connection workingDir="D:\Devendra\workspace_dev\mule4\pdf\src\main\resources\pdf" />
</file:config>
<flow name="pdfFlow" doc:id="eaef4b93-c6f1-4e01-9df3-93e2ba2dcba4" >
<http:listener doc:name="Listener" doc:id="1407afe8-dbea-4f67-8514-29b8039c5638" config-ref="HTTP_Listener_config" path="/pdf"/>
<set-payload value="#[payload]" doc:name="Set Payload" doc:id="a250f9a4-c633-4ce1-a75d-8668d2dede10" mimeType="application/json"/>
<file:write doc:name="Write" doc:id="ca2c47a2-924d-445a-8ca1-7de6197cd583" path="test.pdf" config-ref="File_Config"/>
<logger level="INFO" doc:name="Logger" doc:id="0c629051-500e-4bc0-82b4-74b6c79ec567" message="#[payload]"/>
</flow>
</mule>
I suspect that the problem is that the flow is writing a JSON file to a file called test.pdf. If you try to open with a PDF reader, it will fail because a JSON document is not a PDF file.
<set-payload value="#[payload]" doc:name="Set Payload" doc:id="a250f9a4-c633-4ce1-a75d-8668d2dede10" mimeType="application/json"/>
Mule doesn't have the feature to convert to PDF, so you will need to implement that transformation using Java code calling some PDF generation library.
It is not possible in dataweave st away, so please write a java code.
Below is the Java code that will help you
Put that java class inside src/main/java/com/pdf/JsonToPDF.java folder
package com.pdf;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
public class JsonToPDF {
public static void jsontopdf(String filename,String content) {
Document document = new Document();
try
{
File file = new File(filename);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
document.add(new Paragraph(content));
document.close();
writer.close();
} catch (DocumentException e)
{
e.printStackTrace();
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
}
and call this static method in your Dataweave. Below is the dataweave code
%dw 2.0
import java!com::pdf::JsonToPDF
output application/java
---
{
pdf :JsonToPDF::jsontopdf("C:\\Users\\nanmanikanta\\Desktop\\Integration\\test.pdf","{
'test': 'test'
}")
}
You can change this java to just write a pdf or make this class to return a pdf filestream and give to other processors.
You can multiple things.
For your reference here is the itext library sample code links :
https://howtodoinjava.com/library/read-generate-pdf-java-itext/
I'm new to Mule and I'm trying to get the very first example from the book "Mule in Action" working.
I'm using Mule 3.9 and Anypoint Studio 6.4.1. In chapter 1 they describe a very basic product_registration flow that I have created as follows:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:jms="http://www.mulesoft.org/schema/mule/jms" 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
http://www.mulesoft.org/schema/mule/jms
http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8880" basePath="products" doc:name="HTTP Listener Configuration"/>
<jms:activemq-connector name="Active_MQ" username="admin" password="admin" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="product_registrationFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger Before"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger level="INFO" doc:name="Logger After"/>
<jms:outbound-endpoint doc:name="JMS" queue="products"/>
</flow>
</mule>
and an accompanying functional test:
#Test
public void testCanRegisterProducts() throws Exception {
LocalMuleClient client = muleContext.getClient();
String productAsJson = "{ \"name\":\"Widget\", \"price\": 9.99, \"weight\": 1.0, \"sku\": \"abcd-56789\" }";
MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);
client.dispatch("http://localhost:8880/products", source);
MuleMessage result = client.request("jms://products", RECEIVE_TIMEOUT);
assertNotNull(result);
assertFalse(result.getPayload() instanceof NullPayload);
assertEquals(productAsJson, result.getPayloadAsString());
}
When I run the test it fails at the last assert because the actual payload is:
{NullPayload}
And if I look directly in ActiveMQ I see that payload. If I manually post to Mule (using a tool like Poster in Chrome, setting only the header Content-Type: application/json) the payload is valid JSON and I can get the test to pass (because it is getting the pending message from the queue posted by Poster and the message it creates is at the end of the queue with payload {NullPayload}.
Can someone shed some light on why the flow fails when invoked from the JUnit test, but seems to work when invoked by using a tool like Poster?
Update: With the help of Pierre B. I got it working. The initialization of the MuleMessage in the FunctionalTestCase was updated as follows:
MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);
source.setProperty("Content-Type", "application/json", PropertyScope.INBOUND);
source.setProperty("Content-Length", Integer.valueOf(productAsJson.length()), PropertyScope.INBOUND);
You said it works when you POST a message using an external tool instead of MuleClient:
using a tool like Poster in Chrome, setting only the header Content-Type: application/json
Try adding the same header to your MuleMessage such as:
MuleMessage source = new DefaultMuleMessage(productAsJson, muleContext);
# define the headers
Map<String, Object> headers = new HashMap<String, Object>(1);
headers.put("Content-Type", "application/json");
headers.put("Content-Length", sourceLength);
# add the headers as function parameter
client.dispatch("http://localhost:8880/products", source, headers);
EDIT: as #sceaj pointed out, both Content-Type and Content-Length headers are required.
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")]
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;
}
}
Short: I want to post a couple of parameters (like user=admin, key=12345678) using the POST method to a PHP page (like localhost/post-debug.php). The script would read the $_POST values and do whatever.
My questions are:
1. How can I get the example below to work?
2. How can I create the Map Payload with POST parameters from a JSON encoded payload and send it to the PHP script?
Below is an isolated case I am trying to get running (the parameters are "read" from the HTTP endpoint). I am calling directly from the browser the following URL:
http://localhost:8081/httpPost?user=admin&key=12345678
The underlying XML:
<?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" version="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.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 ">
<flow name="httpPostTestFlow1" doc:name="httpPostTestFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="httpPost" doc:name="HTTP"/>
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map"/>
<echo-component doc:name="Echo"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost/post-debug.php" port="80" contentType="application/x-www-form-urlencoded" doc:name="HTTP" />
</flow>
</mule>
I am using MuleStudio 1.3.2, Mule ESB v.3.3.
I've reviewed many similar questions but none got me on the right track.
Here is the solution for question 2 (answering question 1 won't help):
<flow name="httpPostTestFlow1">
<http:inbound-endpoint exchange-pattern="request-response"
host="localhost" port="8081" path="httpPost" />
<json:json-to-object-transformer
returnClass="java.util.Map" />
<http:outbound-endpoint exchange-pattern="request-response"
host="localhost" port="80" path="post-debug.php" method="POST"
contentType="application/x-www-form-urlencoded" />
<copy-properties propertyName="*" />
</flow>
I've used the following to check it works fine:
curl -H "Content-Type: application/json" -d '{"param1":"value1","param2":"value2"}' http://localhost:8081/httpPost
Note that I use copy-properties to propagate all the response headers from the PHP script invocation back to the original caller. Remove it if you don't care.
Have you tried configuring your outbound endpoint like this:
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="80" path="post-debug.php" contentType="application/x-www-form-urlencoded" doc:name="HTTP" method="POST"/>
Questions a little old, but just hit the same problem. I never could get the "body-to-parameter-map-transformer" to work, so I threw in a custom java component. It parses a URLEncoded param string into a HashMap. Set your vars based on that.
import java.util.HashMap;
import java.util.Iterator;
import org.json.JSONException;
import org.json.JSONObject;
public class ParseParams {
public static HashMap<String, String> jsonToMap(String t) throws JSONException {
HashMap<String, String> map = new HashMap<String, String>();
JSONObject jObject = new JSONObject(t);
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
String value = jObject.getString(key);
map.put(key, value);
}
return map;
}
}