mule code
<flow name="getDetails">
<http:inbound-endpoint doc:description="This endpoint receives an HTTP message." doc:name="HTTP" exchange-pattern="request-response" host="localhost" port="8081" path="getDetails"/>
<json:xml-to-json-transformer doc:name="XML to JSON" mimeType="text/json" ignoreBadInput="true"/>
<logger message="xml to json output #[message.payload]" level="INFO" doc:name="Logger"/>
<logger message=" custom header username ... #[message.outboundProperties.get('http.headers.username')]" level="INFO" />
<logger message=" custom header username ... #[message.inboundProperties.get('http.headers.username')]" level="INFO" />
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/callReservation" method="POST" contentType="application/json" doc:name="HTTP"/>
</flow>
Here i give input as employee xml in the body
and in header i give username=user1 password=pwd1 in postman rest client
<?xml version="1.0" encoding="UTF-8"?>
<employee>
<name>abc</name>
<address>add1</address>
<phone>1212</phone>
</employee>
I got like error like below
com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '{' (code 123) in prolog; expected '<'
at [row,col {unknown-source}]: [1,1] (javax.xml.transform.TransformerException) (org.mule.api.transformer.TransformerException). Message payload is of type: String
using header and xmlto json conversion is mandatory for me.
can anyone help me out
Following code works fine for me. HTH.
<flow name="getDetails" doc:name="getDetails">
<http:inbound-endpoint doc:description="This endpoint receives an HTTP message."
doc:name="HTTP" exchange-pattern="request-response" host="localhost"
port="1000" path="getDetails" />
<json:xml-to-json-transformer doc:name="XML to JSON"
mimeType="text/json" ignoreBadInput="true" />
<logger message="xml to json output #[message.payload]" level="INFO"
doc:name="Logger" />
<logger
message=" custom header username ... #[message.inboundProperties.'http.headers'.username]"
level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response"
address="http://localhost:1001/callReservation" method="POST"
contentType="application/json" doc:name="HTTP" />
</flow>
<flow name="testFlow1" doc:name="testFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="1001" path="callReservation" doc:name="HTTP"/>
<json:json-to-xml-transformer doc:name="JSON to XML"/>
<logger message="Data received : #[payload]" level="INFO" doc:name="Logger"/>
</flow>
I am getting the value using following :-
<logger message=" custom header username ... #[message.inboundProperties['username']]"
level="INFO" doc:name="Logger"/>
You need to pass the XML in the body of postman
UPDATE
I am getting the value as below :-
Use the data mapper after the http:outBound to convert to json response.
Related
I have this mule flow , where its polling the source folder to read the text file which I am adding as a attachment and sending through REST call , the same attachment I am trying to read in the different flow but inbound attachment is coming as null , please have a look into the code and help me on this.
<flow name="createAttachment" doc:description="Reading file and sending as attachment.">
<file:inbound-endpoint path="src/test/resources/in/attachment/" responseTimeout="10000" doc:name="File"/>
<file:file-to-byte-array-transformer doc:name="File to Byte Array"/>
<!-- <set-attachment attachmentName="#[originalFilename]" value="#[payload]" contentType="multipart/form-data" doc:name="Attachment"/> -->
<set-attachment attachmentName="#[originalFilename]" value="#[payload]" contentType="multipart/form-data" doc:name="Attachment" />
<http:request config-ref="HTTP_Request_Configuration" path="attachment/excel" method="POST" doc:name="HTTP"/>
</flow>
<flow name="readAttachment">
<http:listener config-ref="HTTP_Listener_Configuration" path="attachment/excel" allowedMethods="POST" parseRequest="false" />
<set-payload value="#[message.inboundAttachments['myattachment.txt']]" doc:name="Retrieve Attachments"/>
<set-payload value="#[payload.getInputStream() ]" doc:name="Get Inputstream from Payload"/>
<file:outbound-endpoint path="src/test/resources/out/attachment" responseTimeout="10000" doc:name="File" outputPattern="#[server.dateTime.toString()].pdf"/>
</flow>
I used the following:
<flow name="readAttachment">
<http:listener config-ref="HTTP_Listener_Configuration"
path="/" allowedMethods="POST" parseRequest="false" doc:name="HTTP" />
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="#[payload]" level="INFO" doc:name="Logger" /><file:outbound-endpoint path="src/test/resources" connector-ref="File" responseTimeout="10000" doc:name="File"/>
</flow>
When the attachment was received it was automatically parsed to be the payload, so it was just a case of turning the byte array to string.
I hope this helps
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" contentType="application/x-www-form-urlencoded" path="getDetails" />
<object-to-string-transformer doc:name="Object to String"/>
<logger message=" Logging ...... #[message.payload]" level="INFO" doc:name="Logger"/>
<logger level="INFO" message=" Logging mule.......#[message.payloadAs(java.lang.String)]" doc:name="Logger"/>
<logger level="INFO" message="Logging demo .......... #[payload]" doc:name="Logger"/>
i invoke thru chrome rest client
http://localhost:8081/getDetails
METHOD : post
below is json data
{
"id": "1", "firstName": "xyz", "lastName": "abc", "address":"xy"
}
whatever json data i passed , i just want to print for processing . but In logging it shows null payload
any correct solutions are welcome
Strange, but I tried your scenario by following :-
<flow name="Flow1" doc:name="Flow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" contentType="application/x-www-form-urlencoded" path="getDetails" />
<object-to-string-transformer doc:name="Object to String"/>
<logger message=" Logging ...... #[message.payload]" level="INFO" doc:name="Logger"/>
<logger level="INFO" message=" Logging mule.......#[message.payloadAs(java.lang.String)]" doc:name="Logger"/>
<logger level="INFO" message="Logging demo .......... #[payload]" doc:name="Logger"/>
</flow>
And you can see I am able to log the values :-
Your code is absolutely correct. As Anirban pointed out, you may be making mistake while invoking the service. I tried invoking this service using postman plugin in Chrome and selected post with raw XML and it worked fine. Please try with postman and confirm if you still have the same issue.
<flow name="listobjects">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="listobjects" contentType="text/plain" doc:name="HTTP"/>
<s3:list-objects config-ref="Amazon_S3" bucketName="demo" doc:name="Amazon S3" maxKeys="5" />
<!-- <payload-type-filter expectedType="java.util.List" doc:name="Payload"/> -->
<foreach collection="#[payload]" doc:name="For Each">
<!-- <foreach doc:name="For Each file"> -->
<logger message=" inside foreach...... #[payload.getKey()] ...." level="INFO" doc:name="Logger" />
<s3:get-object-content config-ref="Amazon_S3" bucketName="demo" key="#[payload.getKey()]" doc:name="Amazon S3"/>
<object-to-byte-array-transformer/>
<file:outbound-endpoint path="C:\output" responseTimeout="10000" doc:name="File" outputPattern="#[payload.getKey()] "></file:outbound-endpoint>
</foreach>
</flow>
I have bucket name called demo.
In that bucket I have 3 pdf files. I want to download all files and put it in c:\output folder.
I hit my url like http://localhost:8081/listobjects.
But I got the error:
Could not find a transformer to transform "CollectionDataType{type=org.mule.module.s3.simpleapi.SimpleAmazonS3AmazonDevKitImpl$S3ObjectSummaryIterable, itemType=com.amazonaws.services.s3.model.S3ObjectSummary, mimeType='/'}" to "SimpleDataType{type=org.mule.api.transport.OutputHandler, mimeType='/'}". (org.mule.api.transformer.TransformerException) (org.mule.api.transformer.TransformerException). Message payload is of type: SimpleAmazonS3AmazonDevKitImpl$S3ObjectSummaryIterable
The error occurs because after the foreach processor the payload is an instance of an S3 class, and you haven't specified any Content-Type to return. So Mule tries to transform the S3 instance to the default SimpleDataType and fails.
One way to solve it is simply to add something like
<set-property propertyName="Content-Type" value="application/json" doc:name="Content-Type" />
<set-payload value="{'result': 'ok'}"/>
at the end to make it explicit.
Also note that in your flow after running:
<object-to-byte-array-transformer/>
the S3 payload is gone, so #[payload.getKey()] will fail in the next processor:
<file:outbound-endpoint path="C:\output" responseTimeout="10000" doc:name="File" outputPattern="#[payload.getKey()] "></file:outbound-endpoint>
I've run this without problems:
<flow name="listobjects">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8083" path="listobjects" contentType="text/plain" doc:name="HTTP"/>
<s3:list-objects config-ref="Amazon_S3" bucketName="mule_test" doc:name="Amazon S3" maxKeys="5" />
<foreach collection="#[payload]" doc:name="For Each">
<logger message=" inside foreach...... #[payload.getKey()] ...." level="INFO" doc:name="Logger" />
<set-variable variableName="fileKey" value="#[payload.getKey()]" doc:name="Variable" />
<s3:get-object-content config-ref="Amazon_S3" bucketName="#[payload.getBucketName()]" key="#[payload.getKey()]" doc:name="Amazon S3"/>
<object-to-byte-array-transformer/>
<file:outbound-endpoint path="/tmp" responseTimeout="10000" doc:name="File" outputPattern="#[flowVars.fileKey] "></file:outbound-endpoint>
</foreach>
<set-property propertyName="Content-Type" value="application/json" doc:name="Content-Type" />
<set-payload value="{'result': 'ok'}"/>
</flow>
I read data from salesforce and split it using collection splitter. I want to aggregate all data into single list. First I count all records and I set that counter with MULE_CORRELATION_GROUP_SIZE. But my counter gives me wrong count..And my data didn't aggregate..
How can I solve this problem
Is my following flow right?
Following is my code
<flow name="davesalesforceFlow1Tmp" doc:name="davesalesforceFlow1Tmp">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8080" doc:name="HTTP" path="test" contentType="text/plain" />
<sfdc:query config-ref="salesforce" doc:name="Salesforce" query="My query"/>
<collection-splitter doc:name="Collection Splitter"/>
<set-session-variable variableName="cnt"
value="#[org.mule.util.StringUtils.countMatches(message.payload, '\n') + org.mule.util.StringUtils.countMatches(message.payload, ',') - 1]" doc:name="Session Variable"/>
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE"
value="#[sessionVars.cnt]" doc:name="Property"/>
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
I also tried following code But in output got only single record
<flow name="davesalesforceFlow1Tmp" doc:name="davesalesforceFlow1Tmp">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8080" doc:name="HTTP" path="test" contentType="text/plain" />
<sfdc:query config-ref="salesforce" doc:name="Salesforce" query="My query"/>
<collection-splitter doc:name="Collection Splitter"/>
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE"
value="#[message.outboundProperties['MULE_CORRELATION_SEQUENCE']]" doc:name="Property"/>
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
<logger message="MY PAYLOAD IS #[payload]" level="INFO" doc:name="Logger"/>
</flow>
</flow>
If you use the collection splitter and aggregator together theres no need to keep track of the count or anything.
Mule will take care of this via the MULE_CORRELATION_* header behind the scenes.
Only if you are dong for complex splits and aggregates may you need to modify these headers yourself.
<logger level="INFO" message="size before: #[payload.size()]" />
<collection-splitter />
<logger level="INFO" message="Individual item: #[payload]" />
<collection-aggregator />
<logger level="INFO" message="size after: #[payload.size()]" />
I'm currently writing a rather simple mule-flow that uses basic authentication
<custom-transformer class="com.org.HttpRequestToMyRequest" name="HttpRequestToMyRequest" doc:name="Java"/>
<flow name="Input_Flow" doc:name="Input_Flow">
<http:inbound-endpoint exchange-pattern="request-response" host="http://12.23.34.45" port="1234" path="/foo">
<mule-ss:http-security-filter realm="mule-realm"/>
</http:inbound-endpoint>
<flow-ref name="Sorting_Flow" doc:name="Sorting flow"/>
</flow>
<sub-flow name="Sorting_Flow" doc:name="Sorting_Flow">
<transformer ref="HttpRequestToMyRequest" doc:name="Transform Http Request to POJO with interesting methods"/>
<enricher target="#[variable:authorized]">
<http:outbound-endpoint exchange-pattern="request-response" host="12.34.45.56" port="1234" path="foo/bar" method="GET" disableTransportTransformer="true"
responseTransformer-refs="ObjectToString" doc:name="Authorization Service"/>
</enricher>
<choice doc:name="Choice">
<when expression="header:INVOCATION:authorized=true">
<processor-chain>
<component class="com.org.MyClass"/>
<transformer ref="MyObjToString"/>
<http:response-builder status="200" contentType="text/xml" doc:name="HTTP Response Builder"/>
</processor-chain>
</when>
<when SOMETHING ELSE>
DO SOMETHING ELSE
</when>
</choice>
</sub-flow>
If I remove the http-security-filter then this flow works as expected and the payload in the MuleMessage is of the type MyRequest returned by the HttpRequestToMyRequest transformer. But once i add the security-filter the enricher changes my payload from the expected type to a byte[]. If i convert the byte[] to a String then it turns out to be the instancename of MyRequest (com.org.MyRequest#15ae9009).
Any help or ideas would be appreciated.
Edit
Just to be clear. Here are three flow xml fragments where two behave well and the last one has the strange behaviour i don't understand.
This flow, where I've commented out the security-filter on the inbound endpoint, works as expected and the ClassNameLogger statements prints out, in order, String, MyRequest, MyRequest.
<custom-transformer class="com.org.HttpRequestToMyRequest" name="HttpRequestToMyRequest" doc:name="Java"/>
<custom-transformer class="com.org.ClassNameLogger" name="ClassNameLogger" doc:name="Java"/>
<flow name="Input_Flow" doc:name="Input_Flow">
<http:inbound-endpoint exchange-pattern="request-response" host="http://12.23.34.45" port="1234" path="/foo">
<!-- <mule-ss:http-security-filter realm="mule-realm"/> -->
</http:inbound-endpoint>
<flow-ref name="Sorting_Flow" doc:name="Sorting flow"/>
</flow>
<sub-flow name="Sorting_Flow" doc:name="Sorting_Flow">
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<transformer ref="HttpRequestToMyRequest" doc:name="Transform Http Request to POJO with interesting methods"/>
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<enricher target="#[variable:authorized]">
<http:outbound-endpoint exchange-pattern="request-response" host="12.34.45.56" port="1234" path="foo/bar" method="GET" disableTransportTransformer="true"
responseTransformer-refs="ObjectToString" doc:name="Authorization Service"/>
</enricher>
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<choice doc:name="Choice">
<when expression="header:INVOCATION:authorized=true">
<processor-chain>
<component class="com.org.MyClass"/>
<transformer ref="MyObjToString"/>
<http:response-builder status="200" contentType="text/xml" doc:name="HTTP Response Builder"/>
</processor-chain>
</when>
<when SOMETHING ELSE>
DO SOMETHING ELSE
</when>
</choice>
</sub-flow>
This flow, where I've commented out the enricher, works as expected, aside from the fact that it doesn't enter the choise since the variable set by the enricher is not defined. The ClassNameLogger statements prints out, in order, String, MyRequest, MyRequest.
<custom-transformer class="com.org.HttpRequestToMyRequest" name="HttpRequestToMyRequest" doc:name="Java"/>
<custom-transformer class="com.org.ClassNameLogger" name="ClassNameLogger" doc:name="Java"/>
<flow name="Input_Flow" doc:name="Input_Flow">
<http:inbound-endpoint exchange-pattern="request-response" host="http://12.23.34.45" port="1234" path="/foo">
<mule-ss:http-security-filter realm="mule-realm"/>
</http:inbound-endpoint>
<flow-ref name="Sorting_Flow" doc:name="Sorting flow"/>
</flow>
<sub-flow name="Sorting_Flow" doc:name="Sorting_Flow">
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<transformer ref="HttpRequestToMyRequest" doc:name="Transform Http Request to POJO with interesting methods"/>
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<!-- <enricher target="#[variable:authorized]">
<http:outbound-endpoint exchange-pattern="request-response" host="12.34.45.56" port="1234" path="foo/bar" method="GET" disableTransportTransformer="true"
responseTransformer-refs="ObjectToString" doc:name="Authorization Service"/>
</enricher> -->
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<choice doc:name="Choice">
<when expression="header:INVOCATION:authorized=true">
<processor-chain>
<component class="com.org.MyClass"/>
<transformer ref="MyObjToString"/>
<http:response-builder status="200" contentType="text/xml" doc:name="HTTP Response Builder"/>
</processor-chain>
</when>
<when SOMETHING ELSE>
DO SOMETHING ELSE
</when>
</choice>
</sub-flow>
This flow, where I have both the enricher and the security-filter in place, doesn't work as expected and the ClassNameLogger statements prints out, in order, String, MyRequest, byte[].
<custom-transformer class="com.org.HttpRequestToMyRequest" name="HttpRequestToMyRequest" doc:name="Java"/>
<custom-transformer class="com.org.ClassNameLogger" name="ClassNameLogger" doc:name="Java"/>
<flow name="Input_Flow" doc:name="Input_Flow">
<http:inbound-endpoint exchange-pattern="request-response" host="http://12.23.34.45" port="1234" path="/foo">
<mule-ss:http-security-filter realm="mule-realm"/>
</http:inbound-endpoint>
<flow-ref name="Sorting_Flow" doc:name="Sorting flow"/>
</flow>
<sub-flow name="Sorting_Flow" doc:name="Sorting_Flow">
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<transformer ref="HttpRequestToMyRequest" doc:name="Transform Http Request to POJO with interesting methods"/>
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<enricher target="#[variable:authorized]">
<http:outbound-endpoint exchange-pattern="request-response" host="12.34.45.56" port="1234" path="foo/bar" method="GET" disableTransportTransformer="true"
responseTransformer-refs="ObjectToString" doc:name="Authorization Service"/>
</enricher>
<transformer ref="ClassNameLogger" doc:name="Logs The Class Name of MuleMessage payload"/>
<choice doc:name="Choice">
<when expression="header:INVOCATION:authorized=true">
<processor-chain>
<component class="com.org.MyClass"/>
<transformer ref="MyObjToString"/>
<http:response-builder status="200" contentType="text/xml" doc:name="HTTP Response Builder"/>
</processor-chain>
</when>
<when SOMETHING ELSE>
DO SOMETHING ELSE
</when>
</choice>
</sub-flow>
Edit 2
The code in the HttpRequestToMyRequest transformer
public class HttpRequestToMyRequest extends AbstractMessageTransformer{
#Override
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
if("/foo".equals(message.getInboundProperty("http.request.path")){
return new MyFooRequest();
}
if("/bar".equals(message.getInboundParameter("http.request.path")){
return new MyBarRequest();
}
else return new MyEmptyRequest();
}
}
Edit 3
Apparently this was something Mule 3.3 specific. Once I upgraded to 3.4 everything started working as expected.
With Mule 3.4, I notice no difference of payload type with or without the http-security-filter element.
It is either a java.lang.String if the request is an HTTP GET or java.io.InputStream if it is a POST or PUT.
Since you are on 3.3, you are possibly hitting a bug that is gone in 3.4, since I don't have any issue. If that is the case, finding a workaround for the issue on 3.3 would be hairy: upgrading to 3.4 is the path forward.