How to retrieve elements in foreach loop in Mule4? - mule

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]]"/>

Related

How to retrieve elements in foreach loop in Mule4?

I have defined a variable to keep application/json collection.
<set-variable value="#[payload.'IntegrationEntities'.'amendmentId']" 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
you need to access the payload only in foreach scope:
<foreach doc:name="For Each" collection="#[vars.amendmentids]">
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
</foreach>
As in foreach each element of your collection will be the payload.

Access Json element in Flow Variable - Mule 3.7

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

Exception Logging in Batch in Mulesoft

I have a case, where I have to log the exception error in an object in Salesforce, where I have to also take the payload (the record) for which error is there. The error here will be the record level error and I am using a batch process for this. In the screenshot there is how we are processing the exception.
Following is the xml
<batch:step name="HandleFailedRecords_AccountSF-360" accept-policy="ONLY_FAILURES">
<set-payload value="#[getStepExceptions()]" doc:name="Set Payload"/>
<foreach doc:name="For Each" collection="#[payload.values()]">
<set-variable variableName="Record_level_error" value="#[payload]" doc:name="Record_level_error"/>
<dw:transform-message doc:name="Transform Message" metadata:id="9c2e408a-f530-4ffd-a205-a787c8bc94b2">
<dw:set-payload><![CDATA[%dw 1.0
%output application/java
---
payload map
{
SF_Object_Type__c: "Account"
}]]></dw:set-payload>
</dw:transform-message>
<sfdc:create config-ref="Salesforce__Basic_Authentication" type="Exception__c" doc:name="Salesforce">
<sfdc:objects ref="#[payload]"/>
</sfdc:create>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<!-- <flow-ref name="HandleRecordFailure" doc:name="HandleRecordFailure"/> -->
</foreach>
</batch:step>
</batch:process-records>
Here I am able to get what exception I am getting, but what else I need is for which value it is getting errored out.
Bast way to handle properly exception handling in batch processing is to do a flow-ref to a normal flow with his proper exception handling, there you will be able to handle your exception in a standard mule way and do what you need in the exception catch flow.
Hope this helps
Regards

Initializing a Map using Mule Expression Language

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

How can I overwrite the payload in mule

I've a Soap request coming into mule flow. Am tasked with getting information out of payload and depending on outcome, push the original request to different jms queues.
To get the desired information out of payload, I'm using XSLT tranformer (not XPath, because I need to get IDREF attribute from an element, based on IDREF, get the element and then a child element out of the IDREF object).
Based on the outcome of the of XSLT tranformation, I use choice element to push original payload. Am storing original payload in a Session (can do it in Inbound as well). After XSLT tansformation, apply choice router to find out appropriate queue, and then want to push the original payload into queue(original payload in stored in a session variable). I am using <expression-component> element. Below is the snippet of mule-flow:
<flow name="ProcessXML121Order">
<jms:inbound-endpoint queue="mviq.121.order" exchange-pattern="one-way" />
<logger message="121 order payload is #[payload]" level="INFO" />
<message-properties-transformer scope="session">
<add-message-property key="mviPayload" value="#[payload]"/>
</message-properties-transformer>
<xm:xslt-transformer xsl-file="chooseVendor.xslt" />
<logger message="After xsl file payload is #[payload]" level="INFO" />
<choice>
<when expression="'EMSI'">
<logger message="Vendor is EMSI" level="INFO" />
<expression-component>payload=#[header:SESSION:mviPayload]</expression-component>
<jms:outbound-endpoint queue="mviq.121.order.emsi" />
</when>
<when expression="'PRMD'">
<logger message="Vendor is PRMD" level="INFO" />
<jms:outbound-endpoint queue="mviq.121.order.prmd" />
</when>
<when expression="'RSA'">
<logger message="Vendor is RSA" level="INFO" />
<logger message="RSA payload is #[payload]" level="INFO" />
<jms:outbound-endpoint queue="mviq.121.order.rsa" />
</when>
<otherwise>
<logger message="Vendor is Error" level="INFO" />
<logger message="Vendor error payload is #[payload]" level="INFO" />
<jms:outbound-endpoint queue="mviq.error" />
</otherwise>
</choice>
</flow>
Following exception is thrown when evaluating payload=#[header:SESSION:mviPayload]
[ProcessXML121Order.stage1.02] exception.AbstractExceptionListener (AbstractExceptionListener.java:296) -
********************************************************************************
Message : Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[]
Code : MULE_ERROR-29999
--------------------------------------------------------------------------------
Exception stack is:
1. [Error: illegal use of operator: +]
[Near : {... Unknown ....}]
^
[Line: 1, Column: 0] (org.mvel2.CompileException)
org.mvel2.ast.OperatorNode:46 (null)
2. Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException)
org.mule.el.mvel.MVELExpressionLanguage:211 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/expression/ExpressionRuntimeException.html)
3. Execution of the expression "payload=#[header:SESSION:mviPayload]" failed. (org.mule.api.expression.ExpressionRuntimeException). Message payload is of type: byte[] (org.mule.api.MessagingException)
org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor:35 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
[Error: illegal use of operator: +]
[Near : {... Unknown ....}]
^
[Line: 1, Column: 0]
at org.mvel2.ast.OperatorNode.getReducedValueAccelerated(OperatorNode.java:46)
at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:105)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
I've 2 questions:
How can I overwrite the original payload? (Not saying this is the best way to go)
What is the better approach in this scenario? Is it advisable to keep original payload intact (in this case) and store XSLT output in other variable? How can I do that? What is the path (mule component) I can use to achieve that? I'm very new to Mule and seek community advice.
Thanks for your time looking into this.
Before answering your questions, let's rewrite this broken expression:
<expression-component>payload=#[header:SESSION:mviPayload]</expression-component>
as:
<set-payload value="#[sessionVars.mviPayload]" />
The following would work too but would be more complex for no good reason:
<expression-component>payload=sessionVars.mviPayload</expression-component>
Also this:
<message-properties-transformer scope="session">
<add-message-property key="mviPayload" value="#[payload]"/>
</message-properties-transformer>
would be better written:
<set-session-variable variableName="mviPayload" value="#[message.payload]" />
Now to your questions:
Use set-payload
What you are doing is the best: transformers, like XSL-T, applies naturally to the current message payload so saving the original in a property then transforming the main payload is OK. Just one thing: prefer a flow variable instead of a session variable. Indeed, in your case, I don't think you need the original payload outside this flow, so storing in session is overkill.
So I suggest you use:
<set-variable variableName="mviPayload" value="#[message.payload]" />
to store the original payload and the following to re-establish it:
<set-payload value="#[mviPayload]" />
Use Set-Payload and provide the data to be overwritten.
You could do this with lot of ways.
Use set-payload
Use expression, #[payload='']
Use an transformer/component
You can keep the payload intact and store the value of the xslt transformation in a variable using message enricher. Use the variable inside choice to determine which queue to go to. Below is a code snippet
<enricher doc:name="Message Enricher" target="#[flowVars.transformResultVar]">
<!--perform transformation logic here-->
</enricher>
Reference: https://dzone.com/articles/content-enrichment-using-mule-message-enricher-com