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
When I connect to:
http://legacy.cafebonappetit.com/api/2/menus?cafe=261
I get back JSON as I should. However, I'm unable to do this with the Mulesoft HTTP Connector. When I try, I get back 500. Here is my XML:
<flow name="GetDiningInfo">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dining" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="/api/2/menus" method="GET" doc:name="GET announcement from dining server" followRedirects="true" host="legacy.cafebonappetit.com" port="80">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
</http:request-builder>
</http:request>
<logger level="INFO" doc:name="Logger"/>
</flow>
The connector global config is:
<http:request-config name="HTTPReqConfigforCafeBonAppetit.com" host="legacy.cafebonappetit.com" port="80" basePath="/api/2" doc:name="HTTP Request Configuration"/>
What am I doing wrong?
Thanks...
UPDATE: Still no joy. I'm still getting back a 500 internal server failure through Mule.
Here is the latest code that does not duplicate the path:
<http:request-config name="HTTPReqConfigforCafeBonAppetit" host="legacy.cafebonappetit.com" port="80" basePath="/api/2/" doc:name="HTTP Request Configuration" usePersistentConnections="false"/>
<flow name="GetDiningInfo">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dining" doc:name="HTTP"/>
<http:request config-ref="HTTPReqConfigforCafeBonAppetit" path="menus" method="GET" doc:name="GET menu" followRedirects="true" parseResponse="false">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
</http:request-builder>
</http:request>
<logger level="INFO" doc:name="Logger"/>
</flow>
Have you evaluated the URL request result? By referring that configuration it should be http://legacy.cafebonappetit.com/api/2/api/2/menus?cafe=261
That's why you unable to get the expected result. Therefore replace the path of http:request with /menus, without the base path /api/2. Because it's already defined in http:request-config
The server for legacy.cafebonappetit.com cannot handle the header Host including the port (which is valid). The HTTP connector sends Host: legacy.cafebonappetit.com:80 by default causing the server to reject the request, so you need to explicitly add the Host header, as in the example below.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="legacy.cafebonappetit.com" port="80" basePath="/api/2" doc:name="HTTP Request Configuration"/>
<flow name="so-testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dining" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="menus" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
<http:header headerName="Host" value="legacy.cafebonappetit.com"/>
</http:request-builder>
<http:success-status-code-validator values="100..599"/>
</http:request>
</flow>
The example also includes a status code validator for all codes which allows you to see the exact error the server sends when the explicit Host header is removed.
Well the trouble here is when you send a request to the server by the 80 port. The server rejects the request immediately. To resolve this you got to add the header, so this way the server understand and process the request.
To do that just add the following line: $<http:header headerName="Host" value="the_host"/>.
The following XML got the solution:
<http:listener-config name="localhost" port="8085" doc:name="HTTP Listener Configuration" host="0.0.0.0"/>
<http:request-config name="HTTP_Request_Configuration" host="legacy.cafebonappetit.com" port="80" doc:name="HTTP Request Configuration" basePath="/api/2"/>
<flow name="GetDiningInfo">
<http:listener config-ref="localhost" path="/dining" doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="/menus" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
<http:header headerName="Host" value="legacy.cafebonappetit.com"/>
</http:request-builder>
<http:success-status-code-validator values="100..599"/>
</http:request>
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
</flow>
The only way to resolve this issue is to make the server process the request.
Add this line in the xml,
<http:header headerName="Host" value="the_host"/>
You have to delete base path from global configuration of delete path in your xml because it generates url like : http://legacy.cafebonappetit.com/api/2/api/2/menus?cafe=261
here in url api/2/api/2 generated twice so thats why error occured
The server for legacy.cafebonappetit.com cannot handle the header Host including the port (which is valid).
The HTTP connector sends Host: legacy.cafebonappetit.com:80 by default causing the server to reject the request, so you need to explicitly add the Host header, as in the example below.
enter image description here
you can use the code like this
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0"
port="8081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
host="legacy.cafebonappetit.com" port="80" basePath="/api/2" doc:name="HTTP
Request Configuration"/>
<flow name="so-testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dining"
doc:name="HTTP"/>
<http:request config-ref="HTTP_Request_Configuration" path="menus"
method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
<http:header headerName="Host" value="legacy.cafebonappetit.com"/>
</http:request-builder>
<http:success-status-code-validator values="100..599"/>
</http:request>
</flow>
Use this below code for your issue...
<http:request config-ref="HTTP_Request_Configuration" path="/menus" method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="cafe" value="261"/>
<http:header headerName="Host" value="the_host"/>
</http:request-builder>
<http:success-status-code-validator values="100..599"/>
</http:request>
http:request-builder
try to add a header
The below code seems to work.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8084" doc:name="HTTP Listener Configuration"/>
<http:endpoint exchange-pattern="request-response" method="POST" name="HTTP" address="http://legacy.cafebonappetit.com/api/2/menus?cafe=261" doc:name="HTTP"/>
<flow name="GetDiningInfo">
<http:listener config-ref="HTTP_Listener_Configuration" path="/dining" doc:name="HTTP"/>
<logger level="INFO" doc:name="Logger"/>
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.
<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 am using the following fork and join pattern in my flow.Parallel processing works just fine. However, I have issues with exception handling. I want to implement an exception strategy for the processing happening on VM response inbound endpoint of the router. However, it seems my nothing happens when I am trying to write to response, from within the catch exception strategy block. When there is an exception, I am able to see the log statement from the catch block, but the response on browser just hangs.
Please suggest.
<flow name="forkAndJoinFlow" doc:name="forkAndJoinFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="81" path="lowestprice" doc:name="HTTP"/>
<not-filter doc:name="Not">
<wildcard-filter pattern="*favicon*" caseSensitive="true"/>
</not-filter>
<request-reply>
<all>
<vm:outbound-endpoint path="shop1"/>
<vm:outbound-endpoint path="shop2"/>
</all>
<vm:inbound-endpoint path="response">
<message-properties-transformer>
<add-message-property key="MULE_CORRELATION_GROUP_SIZE" value="2" />
</message-properties-transformer>
<collection-aggregator />
</vm:inbound-endpoint>
</request-reply>
<expression-transformer evaluator="groovy" expression="java.util.Collections.min(payload)" doc:name="Expression"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger level="WARN" message="#[string:Lowest price: #[payload]]" doc:name="Logger"/>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="EXCEPTION:#[payload]" level="INFO" doc:name="Logger"></logger>
<!--Nothing happens after this-->
<object-to-string-transformer doc:name="Object to String"></object-to-string-transformer></catch-exception-strategy>
</flow>
<flow name="shop1Flow" doc:name="shop1Flow">
<vm:inbound-endpoint path="shop1" doc:name="VM"/>
<logger level="INFO" message="SHOP1 Flow..." doc:name="Logger"/>
<expression-transformer evaluator="groovy" expression="new java.lang.Double(1000.0 * Math.random()).intValue()" doc:name="Expression"/>
<logger level="WARN" message="#[string:Price from shop 1: #[payload]]" doc:name="Logger"/>
</flow>
<flow name="shop2Flow" doc:name="shop2Flow">
<vm:inbound-endpoint path="shop2" doc:name="VM"/>
<logger level="INFO" message="SHOP2 Flow..." doc:name="Logger"/>
<expression-transformer evaluator="groovy" expression="new java.lang.Double(1000.0 * Math.random()).intValue()" doc:name="Expression"/>
<logger level="WARN" message="#[string:Price from shop 2: #[payload]]" doc:name="Logger"/>`enter code here`
</flow>
</mule>