Can we access a json element inside flow variables in Mule?
Eg: My flowVar value is {
"Input1": {
"Value1": "UNITED STATES"
}
}
How can I access the element 'Value1' using MEL in mule?
Thanks,
ROA
try the below expression,
#[json:/Input1/Value1]
You can use dw function or json path expression to achieve this.
examples:
[dw('payload.Request.name')]
[json:Request/name]
Right answer is
#[flowVars.theVariable.Input1.Value1]
but get here you need a lot what to do. You have to create variable appropriately to match your description. Also name of the variable is missed but you need it anyway. Here is code
<flow name="AccessFlowVariable">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="10000000"/>
<logger message="Flow started" level="INFO" doc:name="Logger"/>
</poll>
<dw:transform-message doc:name="Transform Message">
<dw:set-variable variableName="theVariable"><![CDATA[%dw 1.0
%output application/java
---
{ "Input1": { "Value1": "UNITED STATES" } }]]></dw:set-variable>
</dw:transform-message>
<logger message="#[flowVars.theVariable.Input1.Value1]" level="INFO" doc:name="Logger"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
and here is result
"Can we access a json element inside flow variables in Mule?": Yes we can access json element inside flow variable.
"How can I access the element 'Value1' using MEL in mule?"
Let says if you have stored this json in flow variable (xyz) then you can access it using the bellow syntax:
flowVars.xyz.Input1.Value1
Related
I have defined a variable to keep application/json collection.
My original payload contain following json block;
"amendments": {
"amendmentId": ["8a9a84b76b5a5a59016b687bae35012e",
"8a9a84b76b5a5a59016b6888e90e0144"]
}
<set-variable value="#[payload..amendmentId[1]]" doc:name="AmendmentIds" doc:id="03b6c46a-fc7b-43d4-b23a-502146ef0b13" variableName="amendmentids"/>
<logger level="INFO" doc:name="Logger" doc:id="6a1ad892-65f9-4dd2-9891-bdf3ad64c908" message="#[vars.amendmentids]" />
It prints as;
[
"8a9a84b76b5a5a59016b687bae35012e",
"8a9a84b76b5a5a59016b6888e90e0144"
]
Then I use ForEach loop to define few process logic for each Id,
Within foreach loop how I can get, each above id?
I used,vars.amendmentids[vars.counter]], but getting following error[1]
<foreach doc:name="For Each" doc:id="7b741315-aa28-4704-82f0-629c21d93853" collection="#[vars.amendmentids]">
<logger level="INFO" doc:name="Logger" doc:id="049c3137-2f92-4077-8e3f-b26516cc5528" message="#[vars.amendmentids[vars.counter]]"/>
</foreach>
[1]
Message : "Internal execution exception while executing the script, this is most probably a bug, file an issue with the script and the input data.
Caused by:
java.lang.RuntimeException: Unable to infer a output media type as more than one is being used: application/json,application/java please specify using: output <your mime-type> --- <expr>
at org.mule.weave.v2.el.MuleDataWeaveHelper$.inferImplicitOutput(MuleDataWeaveHelper.scala:69)
.............
" evaluating expression: "vars.amendmentids[vars.counter]".
Error type : MULE:EXPRESSION
I fixed it by defining output mime type like;
<logger level="INFO" doc:name="Logger" doc:id="049c3137-2f92-4077-8e3f-b26516cc5528" message="#[output application/java --- vars.amendmentids[vars.counter - 1]]"/>
Based on Boolean variable I want to get output. If variable is true null parameters should not visible in output and if false null parameters should be visible. How to make skipNullOn dynamic in mule dataweave script?
#swamy Thota not sure if you can do it in dataweave.
Alternate option i can think off is, use choice and 2 dataweaves, one will skip null and other will allow null.
Please use a flow variable , the use a choice and create two different mapping one for true condition and one for false.
It will be something as below
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:encryption="http://www.mulesoft.org/schema/mule/encryption" xmlns:http="http://www.mulesoft.org/schema/mule/http"
<flow name="file2fileFlow">
<file:inbound-endpoint path="D:\Tushar\Training\DataWeave\in" moveToDirectory="D:\Tushar\Training\DataWeave\out" responseTimeout="10000" doc:name="File"/>
<set-variable variableName="test" value="#['a']" doc:name="Variable"/>
<choice tracking:enable-default-events="true" doc:name="Choice">
<when expression="#[flowVars.test] == 'a'">
<dw:transform-message doc:name="If Value True">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
{
}]]></dw:set-payload>
</dw:transform-message>
</when>
<otherwise>
<dw:transform-message doc:name="If Value false">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
{
}]]></dw:set-payload>
</dw:transform-message>
</otherwise>
</choice>
<logger level="INFO" doc:name="Logger"/>
<file:outbound-endpoint outputPattern="output.txt" responseTimeout="10000" doc:name="File"/>
</flow>
</mule>
You can load dw script from file and dynamic replace in text script skipNullOn value. Then, call the MEL function #[dw(<script>, [<output type>] ]
More examles you can see there: https://support.mulesoft.com/s/article/ka4340000004GbvAAE/Dynamic-DataWeave-Script
We want to process all of the exceptions we catch with the same process in our exception strategy. It is the one generated by apikit. We first send a lot with a custom component and then we generate json response. In the response with DataWeave we want to set the same statusCode. However, the statusCode do not seem to be a variable that is retrievable. Am I correct, or there is a good way to retrieve it?
<apikit:mapping-exception-strategy xmlns:apikit="http://www.mulesoft.org/schema/mule/apikit" name="svc0031_hotel-apiKitGlobalExceptionMapping">
<apikit:mapping statusCode="504">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
<apikit:mapping statusCode="404">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
</apikit:mapping-exception-strategy>
<sub-flow name="svc0031_manageErrors">
<set-payload value="#[groovy:message.exceptionPayload.rootException.message]" doc:name="Set BIP Payload"/>
<custom-transformer class="se.zystems.baseline.BaselineLogging" doc:name="Log BIP Outgoing">
<spring:property name="Level" value="ERROR"/>
<spring:property name="ObjectId" value="CatchErrors"/>
<spring:property name="TransactionStatus" value="failed"/>
</custom-transformer>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : 400,
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
<logger level="INFO" doc:name="Logger"/>
</sub-flow>
Good,
If you create a variable with the http.status then you can use it in the mapper:
<flow name="test">
<set-variable variableName="httpStatus" value="#[message.inboundProperties['http.status']" doc:name="Variable"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : flowVars.httpStatus,
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
</flow>
I found out where the statusCode value is stored thanks to the answer by Jesús Pablo Fernández
He was almost right in his answer, however, the statusCode is stored not in message.inboundProperties['http.status'], but in message.outboundProperties['http.status']. No need to even extract a variable, one can just access it in data transformer directly like this:
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
{
status : outboundProperties['http.status'],
message : payload,
code : 42,
more_info :"https://anypoint.mulesoft.com/apiplatform/nordic-choice-hotels"
}]]></dw:set-payload>
</dw:transform-message>
Status codes defined in the APIKitExceptionStrategy will be those sent back in the response header as http.status given the corresponding exception to be raised.
For instance,
<apikit:mapping statusCode="504">
<apikit:exception value="org.mule.api.transformer.TransformerMessagingException"/>
<flow-ref name="svc0031_manageErrors" doc:name="Manage Error"/>
</apikit:mapping>
means that when a org.mule.api.transformer.TransformerMessagingException exception is thrown and caught by this exception block, then a 504 status code is sent back as a response header.
If you want to bypass the statusCode attribute in the APIKit exception block, you should have another exceptionStrategy block to catch your desired exception, and then you could set your status code like that
<set-property name="http.status" value="<the_desired_status, e.g. 401>" />
Hope it helps.
/Tony
Good Stanislav Ivanov,
I have a flow implemented with the APIKit, which is the code that I attach and whether there is property in the inboundProperties http.status, review it because if it should contain the value, if you do not have your flow may modify the value in a previous step.
I pointed him to directly access the outboundProperties in the mapper, I was not aware, thank you very much.
I'm trying to initialize a map with the following in a mule expression-component:
#[message.payload = [ 'changeSet' : #[payload], 'sourceAndConnectionMap' : #[flowVars['sourceAndConnectionMap']]]]
Based on the following page, this looks okay, but does not work.
https://developer.mulesoft.com/docs/display/current/Mule+Expression+Language+Reference
Only the first key is set ('changeSet'), and for some reason the payload, which is a map, becomes an ArrayList containing a map... I can also initialize this with just the second key and valy, so I know there isn't an issue resolving the flowVar.
Is there something basic about how I am initializing this map that is incorrect?
In MEL a map should be created like:
#[{'key':'value', 'key1':'value1'}]
If you do
#[[]]
That's just a list of elements.
The other comments, if you're already inside a:
#[]
You need not to add it again. In your example you have it several times.
Please run this through the Mule debugger (put brakepoints in the logs)and you'll see the difference.
<flow name="test>
<set-payload value="#[{'key':'value', 'key1':'value1'}]" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
<set-payload value="#[{'key':'value', 'key1':payload}]" doc:name="Copy_of_Set Payload"/>
<logger level="INFO" doc:name="Copy_of_Logger"/>
<set-payload value="#[['key','value', 'key1','value1']]" doc:name="Copy_of_Set Payload"/> <logger level="INFO" doc:name="Logger"/>
</flow>
HTH
I'm using Mule 3.4 CE and I have a JSON data coming through HTTP in the following format:
{
"People" : [
{
"Details" :
{
"Name" : "John Smith",
"Email" : "abc#mail.com"
}
},
{
"Details" :
{
"Name" : "Tim Smith",
"Email" : "def#mail.com"
}
},
{
"Details" :
{
"Name" : "Ken Smith",
"Email" : "ghi#mail.com"
}
},
}
I need to extract the emails and lookup the Salesforce contact with these emails and at the same time I want to retain the JSON payload. So my question is how do I extract the emails through MEL? (for e.g. something like "People/Details/*/Email" - I know this is not a valid, but I'm looking for the right syntax.
Edit: I want to extract the emails in one shot rather than indexing (for e.g. People/Details[0].Email, possibly using MEL.
There best way to query json is to transform it to a Map.
<json:json-to-object-transformer returnClass="java.util.HashMap" />
And then query it using MEL like standard MVEL or Java syntax
<logger message="#[payload.People[0].Details.email]" level="INFO" />
If you want to keep the original json payload intact, you can store the map in a variable using an enricher:
<enricher target="#[flowVars.myJsonMap]">
<json:json-to-object-transformer returnClass="java.util.HashMap" />
</enricher>
And query the variable instead of the payload:
<logger message="#[flowVars.myJsonMap.People[0].Details.email]" level="INFO" />
You could also map the json to a custom class using Jackson and change the returnClass attribute to your class.
This MEL cheat sheet detail JSON processing with MEL and also how to handle Maps, arrays etc: http://www.mulesoft.org/documentation/display/current/MEL+Cheat+Sheet
Note: You may come across a #[json:] evaluator, but this is deprecated in favour of the approach above.
UPDATE:
If you want to grab all the emails at once you can use MVEL projections:
<enricher target="#[flowVars.myJsonMap]" source="#[(Details.email in payload.People)]">
<json:json-to-object-transformer returnClass="java.util.HashMap" />
</enricher>
Mvel projections: http://mvel.codehaus.org/MVEL+2.0+Projections+and+Folds
If you want to get the particular email in the details use the below MEL expression.
#[json:People[0]/Details/Email]
If you want to get all the emails, pass the json path of repeatable in ForEach Collections then pass the path to get Email as shown below.
<flow name="parsingjsonFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<foreach collection="#[json:People]" doc:name="For Each">
<logger message="#[json:/Details/Email]" level="INFO" doc:name="Logger"/>
</foreach>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger message="#[exception.getClass()]" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</flow>