Mule attachments behavioral difference in 3.5 and 3.7 - mule

I just want to send attachments in the http:request. Hence I prepared the following flows.
<flow name="http-request-payload-multipart-preparator">
<http:listener config-ref="GlobalHTTPConnector" path="/requestmultipartprep" doc:name="HTTP"/>
<expression-component doc:name="Expression"><![CDATA[
ds = new org.mule.message.ds.StringDataSource('key1','value1','text/plain');
dh = new javax.activation.DataHandler(ds);
message.outboundAttachments['key1'] = dh;
ds = new org.mule.message.ds.StringDataSource('key2','value2','text/plain');
dh = new javax.activation.DataHandler(ds);
message.outboundAttachments['key2'] = dh;]]></expression-component>
<set-payload value="#[null]" />
<http:request config-ref="HTTP_Request_Configuration" path="/simplemultiparthandler" method="POST" doc:name="HTTP"/>
</flow>
<flow name="sile-multipart-handler">
<http:listener config-ref="GlobalHTTPConnector" path="/simplemultiparthandler" doc:name="HTTP"/>
<logger level="INFO" message="#[message.inboundAttachments.keySet().toString()]" />
<logger level="INFO" message="#[message.inboundAttachments.'key1'.dataSource.name]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key1'.dataSource.content]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key2'.dataSource.name]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key2'.dataSource.content]" doc:name="Payload Logger"/>
<set-payload value="baba sai" />
</flow>
This is working fine in mule 3.7. Here I can see the I have two attachments with names 'key1' and 'key2' respectively.
But if I do the same thing in mule 3.5 with http:outbound-endpoint I am unable to get the keys. It is showing attachments names are 'value1' and 'value2' respectively.
Why is it behaving this way?
To get this done I changed the code as follows in 3.5. I exchanged the key and value names.
<flow name="http-request-payload-multipart-preparator">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" path="requestmultipart" connector-ref="NoSessionEncodingConnector" doc:name="HTTP" />
<expression-component doc:name="Expression"><![CDATA[
ds = new org.mule.message.ds.StringDataSource('value1','key1','text/plain');
dh = new javax.activation.DataHandler(ds);
message.outboundAttachments['key1'] = dh;
ds = new org.mule.message.ds.StringDataSource('value2','key2','text/plain');
dh = new javax.activation.DataHandler(ds);
message.outboundAttachments['key2'] = dh;
payload;]]></expression-component>
<set-payload value="#[null]" />
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" method="POST" doc:name="HTTP" path="simplemultiparthandler" connector-ref="NoSessionEncodingConnector" />
</flow>
<flow name="sile-multipart-handler">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="9876" path="simplemultiparthandler" connector-ref="NoSessionEncodingConnector" doc:name="HTTP" />
<logger level="INFO" message="#[message.inboundAttachments.keySet().toString()]" />
<logger level="INFO" message="#[message.inboundAttachments.'key1'.dataSource.name]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key1'.dataSource.inputStream]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key2'.dataSource.name]" doc:name="Payload Logger"/>
<logger level="INFO" message="#[message.inboundAttachments.'key2'.dataSource.inputStream]" doc:name="Payload Logger"/>
</flow>
Why is this difference in 3.5 and 3.7?

The HTTP Connector of 3.7 is a complete rewrite of the HTTP Transport of 3.5 and earlier versions.
Attachment support has always been problematic in the old transport so I reckon MuleSoft decided to fix things when building the new connector.

Related

"Redirecting into HTML page"

I have a flow where I am trying to load a HTML page if successfully login or fails. Flow is working but while doing POST job on browser side it's not redirecting to the loginSuccessful.html or login/loginFailure.html.
<flow name="GetLoginPage">
<http:listener config-ref="HTTP_Listener_Configuration" path="/login" allowedMethods="GET" doc:name="HTTP"/>
<parse-template location="login/index.html" doc:name="Parse Template"/>
</flow>
<flow name="Dologin">
<http:listener config-ref="HTTP_Listener_Configuration" path="/login" allowedMethods="POST" doc:name="HTTP"/>
<logger message="trying to login!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<choice doc:name="Choice">
<when expression="#[payload.username == "mule" and payload.password == "mule"]">
<logger message="login successfully!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<parse-template location="login/loginSuccessful.html" doc:name="Parse Template"/>
</when>
<otherwise>
<logger message="login failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" level="INFO" doc:name="Logger"/>
<parse-template location="login/loginFailure.html" doc:name="Parse Template"/>
</otherwise>
</choice>
</flow>
I took the liberty of creating my own payload in JSON and added the payload values from above:
{
"name": "mule",
"password": "mule"
}
Then, added a data transformer from JSON to Java, then I mildly adjusted your conditional test to eliminate the encoded quotes and replaced them with single quotes:
payload.username == 'mule' and payload.password == 'mule'
And the choice router correctly to pick up my test files with the parse template.

"Read multiple file from different location simultaneously and merge them into one payload"

I am reading the multiple files from different folder and merging them into one but not able to merge into one file.
I am using composite source where I added two file connector then I am logging the payload into logger. payload I am getting one by one. How can I get the one payload combination of the two different payloads or multiple files input?
<flow name="file2Flow">
<composite-source doc:name="Copy_of_Composite Source">
<file:inbound-endpoint path="src/main/resources/input1" responseTimeout="10000" doc:name="File"/>
<file:inbound-endpoint path="src/main/resources/input2" responseTimeout="10000" doc:name="File"/>
</composite-source>
<file:file-to-string-transformer doc:name="File to String"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
also I am trying this but not getting output
<flow name="file2file2Flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/files" doc:name="HTTP"/>
<scatter-gather doc:name="Scatter-Gather">
<file:outbound-endpoint path="src/main/resources/input1" responseTimeout="10000" doc:name="File"/>
<file:outbound-endpoint path="src/main/resources/input1" responseTimeout="10000" doc:name="File"/>
</scatter-gather>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
post1: payload[0],
post2: payload[1]
}]]>
</dw:set-payload>
</dw:transform-message>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
file:inbound-endpoint will poll one directory, so if you need different directories that won't work.
composite-source allows it, but they wont be available in the same payload.
file:outbound-endpoint is for writing files only.
In Mule 3, you can achieve this though through a combination of a poll to trigger the flow, scatter-gather to route to multiple processors and the mule requester module to read files mid flow.
Mule Requester Module: https://www.mulesoft.com/exchange/68ef9520-24e9-4cf2-b2f5-620025690913/requester-module/
Rough example:
<flow name="dw-testFlow">
<poll doc:name="Poll" frequency="10000">
<logger level="INFO" doc:name="Logger" />
</poll>
<scatter-gather doc:name="Scatter-Gather">
<mulerequester:request config-ref="muleRequesterConfig" resource="myFileEndpoint" doc:name="Mule Requester" />
<mulerequester:request config-ref="muleRequesterConfig" resource="myFileEndpoint" doc:name="Mule Requester" />
</scatter-gather>
</flow>

How can I find if URI parameter exists in Mule?

I want to check if a URI parameter exists in the URL using Mule 3.8.3 and also need to make sure that inboundProperties is not empty either when using the Choice component in Anypoint Studio 6.2 and Mule 3.8.3.
I have tried:
#[message.inboundProperties.'http.uri.params'.code != empty]
#[org.mule.util.StringUtils.isNotEmpty(message.inboundProperties.'http.uri.params'.code)]
For both I get
org.mule.api.expression.ExpressionRuntimeException: Execution of the
expression
"org.mule.util.StringUtils.isNotEmpty(message.inboundProperties.'http.query.params'.code)"
failed.
Is there any other way to try?
There are two "Expression" in palate.
1.Expression-transformer
Example : <expression-transformer expression="#[message.inboundProperties.'http.uri.params'.param != empty]" doc:name="Expression"/>
2.Expression-component
Example : <expression-component doc:name="Expression"/>
Make sure you use "Expression-transformer" as shown below
Try below flow in Anypoint Studio.It works for me.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8082" basePath="/testapi" doc:name="HTTP Listener Configuration"/>
<flow name="uri">
<http:listener path="uri/{param}/resource" config-ref="HTTP_Listener_Configuration" doc:name="HTTP"/>
<expression-transformer expression="#[message.inboundProperties.'http.uri.params'.param != empty]" doc:name="Expression"/>
<object-to-string-transformer doc:name="Object to String"/>
<set-payload value="#[payload]" doc:name="Set Payload"/>
</flow>
Test above with below url in your browser
http://localhost:8082/testapi/uri/testUriParam/resource
This could be used with Choice component component as well.
Try below code :
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8082" basePath="/testapi" doc:name="HTTP Listener Configuration"/>
<flow name="uri">
<http:listener path="uri/{param}/resource" config-ref="HTTP_Listener_Configuration" doc:name="HTTP"/>
<choice doc:name="Choice">
<when expression="#[message.inboundProperties.'http.uri.params'.param != empty]">
<logger message="Found URI Param" level="INFO" doc:name="Logger"/>
<set-payload value="Found URI Param" doc:name="Set Payload"/>
</when>
<otherwise>
<logger level="INFO" doc:name="Logger" message="URI Param not found"/>
<set-payload value="URI Param not found" doc:name="Set Payload"/>
</otherwise>
</choice>
</flow>

Mule Flow Reference Component throwing TransformerMessagingException while passing json

I have two flow one receive the xml payload and another json. I am routing the xml call to json flow using mule flow reference component after converting the xml to json payload. and second flow returns the json payload that i need to convert back to xml and reply to client.
My mule flow reference is throwing TransformerMsgException while receiving the json response from second flow.
Failed to transform from "json" to "java.lang.String" (org.mule.api.transformer.TransformerException). Message payload is of type: String
Here are the code for your reference -
<flow name="post:/chkdb:application/json:chkd-config">
<logger message="========json payload==>>>>==== #[message.payload]" level="INFO" doc:name="Logger"/>
<set-variable variableName="GGG_Number" value="#[json:ggg]" doc:name="Variable"/>
<!-- db call returns the payload-->
<choice doc:name="Choice">
<when expression="#[message.payload.size()>0]">
<set-payload value="{"indicator":"True"}" mimeType="application/json" doc:name="Set Payload"/>
</when>
<otherwise>
<set-payload value="{"indicator":"False"}" mimeType="application/json" doc:name="Set Payload"/>
</otherwise>
</choice>
<logger message="=========after producing json output=======" level="INFO" doc:name="Logger"/>
</flow>
<flow name="post:/chkdb:application/xml:chkdb-config">
<logger message="========= xml payload======== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:xml-to-json-transformer mimeType="application/json" doc:name="XML to JSON"/>
<flow-ref name="post:/chkdb:application/json:chkdb-config" doc:name="post:/chkdb:application/json:chkdbapi-config"/> <!-- Getting exception here -->
<logger message=" after subflow call ==== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:json-to-xml-transformer mimeType="application/xml" doc:name="JSON to XML"/>
<logger message="after json to xml conversion" level="INFO" doc:name="Logger"/>
</flow>
XML Request -
<ggg>DeJmp03bkqALlRFYmgu4+A==</ggg>
How i should retrieve the json response from other flow to current flow.
There is something missing here
First flow name: post:/chkdb:application/json:chkdbapi-config
Second flow name: post:/chkdb:application/xml:chkdbapi-config
Flow ref in second flow: post:/chkdb:application/json:chkdb-config
You are not referencing First flow.
So from your flow posted I can find few issues as follows :-
1. You are using where is the flow post:/chkdb:application/json:chkdb-config doesn't exits and it should be post:/chkdb:application/json:chkdbapi-config instead
2. Right now in the flow you are using <when expression="#[message.payload.size()>0]"> where as the message payload is in String format right now.
So, you can either use <when expression="#[message.payload.length()>0]">, using length() instead of size() or put a <json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/>before choice if you use #[message.payload.size()>0]
So the full code will be something as follows :-
<flow name="post:/chkdb:application/json:chkdbapi-config">
<logger message="========json payload==>>>>==== #[message.payload]" level="INFO" doc:name="Logger"/>
<!-- <json:json-to-object-transformer returnClass="java.lang.Object" doc:name="JSON to Object"/> --> <!-- incase you use #[message.payload.size()>0] in your choice -->
<!-- db call returns the payload-->
<set-variable variableName="GGG_Number" value="#[json:ggg]" doc:name="Variable"/>
<choice doc:name="Choice">
<when expression="#[message.payload.length()>0]">
<set-payload value="{"indicator":"True"}" mimeType="application/json" doc:name="Set Payload"/>
</when>
<otherwise>
<set-payload value="{"indicator":"False"}" mimeType="application/json" doc:name="Set Payload"/>
</otherwise>
</choice>
<logger message="=========after producing json output=======" level="INFO" doc:name="Logger"/>
</flow>
<flow name="post:/chkdb:application/xml:chkdbapi-config">
<logger message="========= xml payload======== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:xml-to-json-transformer mimeType="application/json" doc:name="XML to JSON"/>
<flow-ref name="post:/chkdb:application/json:chkdbapi-config" doc:name="post:/chkdb:application/json:chkdbapi-config"/> <!-- Getting exception here -->
<logger message=" after subflow call ==== #[message.payload]" level="INFO" doc:name="Logger"/>
<json:json-to-xml-transformer mimeType="application/xml" doc:name="JSON to XML"/>
<logger message="after json to xml conversion" level="INFO" doc:name="Logger"/>
</flow>

Until Successful returning an Boolean value in MULE ESB

I am using an until successful scope for my outbound endpoint. Am getting a proper response but when it comes out of until successful am getting boolean value my flow is given below
<flow name="testFlow1" doc:name="testFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="test" doc:name="HTTP"/>
<until-successful maxRetries="5" failureExpression="#[message.inboundProperties['http.status'] != 200]" synchronous="true" doc:name="Until Successful">
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="www.example.com" doc:name="HTTP"/>
</until-successful>
<logger message="`From outbound #[payload]`" level="INFO" doc:name="Logger"/>
</flow>
</mule>
But am getting output in logger as
From outbound true
Hi there not sure what could be happening but here is a example run in 3.6.0 and it works properly:
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="9090" doc:name="HTTP Listener Configuration"/>
<spring:beans>
<spring:bean id="objectStore" class="org.mule.util.store.SimpleMemoryObjectStore"/>
</spring:beans>
<http:request-config name="HTTP_Request_Configuration" host="localhost" port="9090" doc:name="HTTP Request Configuration"/>
<flow name="zzzFlow1" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-payload value="#['laleros']" doc:name="Set Payload"/>
<logger message="*************************** #[payload]" level="INFO" doc:name="Logger"/>
<until-successful maxRetries="5" doc:name="Until Successful" synchronous="true">
<http:request config-ref="HTTP_Request_Configuration" path="/t" method="POST" doc:name="HTTP"/>
</until-successful>
<object-to-string-transformer doc:name="Object to String"/>
<logger message="*************************** #[payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="tFlow1" >
<http:listener config-ref="HTTP_Listener_Configuration" path="/t" doc:name="HTTP"/>
<object-to-string-transformer doc:name="Object to String"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
Here is the output I'm getting:
*******************************************************************************************************
* - - + APPLICATION + - - * - - + DOMAIN + - - * - - + STATUS + - - *
*******************************************************************************************************
* zzz * default * DEPLOYED *
*******************************************************************************************************
INFO 2015-02-23 14:10:17,540 [[zzz].HTTP_Listener_Configuration.worker.01] org.mule.api.processor.LoggerMessageProcessor: *************************** laleros
INFO 2015-02-23 14:10:17,593 [[zzz].HTTP_Listener_Configuration.worker.02] org.mule.api.processor.LoggerMessageProcessor: laleros
INFO 2015-02-23 14:10:17,670 [[zzz].HTTP_Listener_Configuration.worker.01] org.mule.api.processor.LoggerMessageProcessor: *************************** laleros
And just FYI, I reckon you need the transformer after the the http request to serialise the response for it usually returns the stream as payload.
HIH
your definition of until-successful scope requires additional configuration need to be done.
give glance over the below link
UntilSuccessful component to poll http endpoint till condition is met