I am building an api to which i am sending a json request as below :
{
"type":"string",
"code": 101
}
I am using a choice router and i am routing the message based in the code .
i.e if code is not 101 and 100 then when condition will be executed
When Expression is - #[json:code != 101 && json:code != 100]
but even if code is 103 the above experession is returning true.
I'm assuming your comment "code is in double quotes" means the payload is like this:
{
"type": "string",
"code": "100"
}
If so, I'd recommend you convert it to Java and work from there. If the code is a string you need to acount for that as 100 != '100':
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<choice doc:name="Choice - Code?">
<when expression="#[payload.code != '101' && payload.code != '100']">
<logger level="INFO" doc:name="Logger - Do this"/>
</when>
<otherwise>
<logger level="INFO" doc:name="Logger - Do that"/>
</otherwise>
</choice>
Use Json to Object transformer before using JSON payload
Use (and , or) instead of (&&,||) for Logical operators in mule: DataWeaveLogicalOperators
xml config code,
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="json to obj"/>
<choice doc:name="Choice">
<when expression="#[payload.code != 101 and payload.code != 100]">
<logger level="INFO" doc:name="logger"/>
</when>
<otherwise>
<logger level="INFO" doc:name="default"/>
</otherwise>
</choice>
Related
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.
This is my ArrayList -
[
{
AccountNumber=123456,
Amount=257710.06
},
{
AccountNumber=845679,
Amount=3672351.06
}
]
Here, I want to check whether the account number 123456 is in the list or not.
I have used "Choice" component, because I want to create another list with searched account numbers. This is my code-
<choice doc:name="Choice">
<when expression="#[flowVars.investOneList.contains(123456)]">
<logger message="Account number is present" level="INFO" doc:name="Logger"/>
</when>
<otherwise>
<logger message="Account number is not present" level="INFO" doc:name="Logger"/>
</otherwise>
</choice>
Here, my logger prints "Account number is not present". My code is not able to find the account number, although it is there in the list.
Could anyone please help me out?
Thanks!
If you want to use List.contains(...) you will need to map the variable you have like this:
%dw 1.0
%output application/java
---
flowVars.investOneList map $.AccountNumber
Which will output [123456, 845679] as the payload (you can set to something else if you want). Then you can do this in your choice router:
<choice doc:name="Choice">
<when expression="#[payload.contains(123456)]">
<logger message="Account number is present" level="INFO" doc:name="Logger"/>
</when>
<otherwise>
<logger message="Account number is not present" level="INFO" doc:name="Logger"/>
</otherwise>
</choice>
But you could do the whole thing in MEL by using the dw() function like this:
...
<when expression="dw('(flowVars.investOneList map $.AccountNumber) contains 123456')">
...
And that will prevent you from needed an intermediate calculation just to get a list of the account numbers.
I am using Groovy inside Poll to check file existence at given location.
My flow is working fine, when there is a file. But If I delete that file, flow is not triggering.Below is my code
<flow name="monitor-dst-file-flow">
<poll doc:name="Poll">
<schedulers:cron-scheduler expression="0 0 23 ? * TUE-SAT"/>
<scripting:transformer doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[def endpointBuilder = muleContext.endpointFactory.getEndpointBuilder(
"sftp://${user}:${pwForGroovy}#${host}:${port}${inputpath}/?connector=SFTP")
endpointBuilder.addMessageProcessor(new org.mule.routing.MessageFilter(new org.mule.transport.file.filters.FilenameWildcardFilter('test.txt')))
def inboundEndpoint = endpointBuilder.buildInboundEndpoint()
inboundEndpoint.request(30000L)]]>
</scripting:transformer>
</poll>
<choice doc:name="Choice">
<when expression="#[message.inboundProperties.originalFilename =="test.txt"]">
<logger level="INFO" doc:name="Logger" message="File Exists..."/>
</when>
<otherwise>
<logger message="FILE EXISTS" level="ERROR" doc:name="Logger"/>
<flow-ref name="email-notification-sub-flow" doc:name="Flow Reference"/>
</otherwise>
</choice>
</flow>
Here, if there is no test.txt file, I am not able to debug Choice component.
It says -Polling of monitor-dst-file-flow returned null, the flow will not be invoked.
I am not able to identify the exact solution to run my flow. I have to handle that condition, where given file is not there.
You need to return something besides null from the poller's target for the flow to be invoked. I'd recommend doing this in a sub-flow:
<flow name="monitor-dst-file-flow">
<poll doc:name="Poll">
<schedulers:cron-scheduler expression="0 0 23 ? * TUE-SAT"/>
<flow-ref name="pollerProcessor" doc:name="pollerProcessor"/>
</poll>
<choice doc:name="Choice">
<when expression="#[payload == 'file not found']">
<logger level="INFO" doc:name="Logger" message="File Exists..."/>
</when>
<otherwise>
<logger message="FILE EXISTS" level="ERROR" doc:name="Logger"/>
<flow-ref name="email-notification-sub-flow" doc:name="Flow Reference"/>
</otherwise>
</choice>
</flow>
<sub-flow name="pollerProcessor">
<scripting:transformer doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[def endpointBuilder = muleContext.endpointFactory.getEndpointBuilder(
"sftp://${user}:${pwForGroovy}#${host}:${port}${inputpath}/?connector=SFTP")
endpointBuilder.addMessageProcessor(new org.mule.routing.MessageFilter(new org.mule.transport.file.filters.FilenameWildcardFilter('test.txt')))
def inboundEndpoint = endpointBuilder.buildInboundEndpoint() inboundEndpoint.request(30000L)]]>
</scripting:script>
</scripting:transformer>
<set-payload value="#[payload == null ? 'file not found' : payload]" doc:name="Set Payload"/>
</sub-flow>
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>
I have route choice depending on the payload. The payload can be either list, map or string. The payload has to be identified and routed depending on the payload type.
I think that you want something like that
<choice doc:name="Choice">
<when expression="#[payload is List]">
<logger level="INFO" message="i am list" doc:name="Logger"/>
</when>
<when expression="#[payload is Map]">
<logger level="INFO" message="i am map" doc:name="Logger"/>
</when>
<when expression="#[payload is String]">
<logger level="INFO" message="i am string" doc:name="Logger"/>
</when>
<otherwise>
<logger message="class doesnt match with [list, map, string]" level="INFO" doc:name="Logger"/>
</otherwise>
</choice>
I do agree with EddĂș response, except for that I would add an otherwise path. If you don't do that and get something different than a list map or string you would get the rather cryptic error:
org.mule.api.routing.RoutePathNotFoundException: Can't process message because no route has been found matching any filter and no default route is defined. Failed to route event via endpoint: ChoiceRouter [flow-construct=testNull, started=true]. Message payload is of type: NullPayload