<foreach doc:name="For Each"
doc:id="119e4859"
collection="#[payload]"
counterVariableName="counter"
batchSize="1"
rootMessageVariableName="rootMessage" />
For Each (<foreach/>)
Process input in a pattern similar to for-each
or for
loop in other programming languages.
Component XML
This component supports the following XML structure:
For Each (<foreach/>
) attributes are configurable through the UI and XML.
Attribute Name | Attribute XML | Description |
---|---|---|
Foreach (default) |
|
Editable name for the component to display in the canvas. |
N/A |
|
Automatically generated identifier for the component. |
Collection |
|
A DataWeave expression that returns a Java collection, object, array, map, or DOM nodes. For Each automatically splits the collection into elements, such as the highest-level objects in a JSON array of objects. Each element becomes the |
Batch size |
|
Number that the scope uses to partition the collected elements from the input into sub-collections of a specified size. For example, if input to For Each is an array of 199 elements and you set the batch size to 50, the scope produces three arrays of 50 elements each and one array of 49 elements. Defaults to |
Root message variable name |
|
Configurable name of the variable that stores the complete, un-split Mule message from the original input to For Each. The message contains the payload and any attributes but does not contain any variables ( |
Counter variable name |
|
Name of the variable that assigns a number to each iteration over a given element. The sequence starts with |
Examples
The following example collects and splits an array of objects that it receives into separate objects. Components within the scope select a portion of each object, write a portion of that selected content into separate files, and log the new payload
that results within For Each.
Assume that For Each receives its input from a scheduled HTTP request for this JSON array of objects.
(1)
<foreach doc:name="For Each" collection="#[payload]">
(2)
<ee:transform doc:name="Transform Message" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
payload.company]]></ee:set-payload>
</ee:message>
</ee:transform>
(3)
<file:write doc:name="Write"
path='#[(payload.name replace " " with("-") ++ "-") ++ (now() as String {format: "uuuuMMddHHmmss"}) ++ ".json"]'
config-ref="File_Config" mode="CREATE_NEW"/>
(4)
<logger level="INFO" doc:name="Logger" message="#[payload]"/>
</foreach>
For Each processes the input array:
1 | For Each (<foreach /> ) collects the entire input payload and splits it into the ten top-level JSON objects within it, such as this one:
|
2 | As For Each iterates over each object, the DataWeave expression (payload.company ) in the Transform component (<ee:transform /> ) uses DataWeave selectors to extract the value of each "company" key and transform the payload to the value of each of those keys. As in a Mule flow, the next component within For Each receives the transformed payload as its input. |
3 | The File Write operation (<file:write /> ) uses payload.name within a larger DataWeave expression to select the name of each company from the transformed object. The name of each file follows the pattern specified in the expression, which hyphenates the extracted company name and appends a date-time stamp to make the file name unique. For example, the name of a file for Romaguera-Crona data looks like this:
By default, the operation also loads the payload received from Transform Message to each file. |
4 | The logs print the following message for the first object from the input array:
|
When processing Mule variables, execution within For Each begins with the values of Mule variables from the previous execution. New Mule variables or modifications to the values of existing variables that take place when processing one element are accessible during the processing other elements. Changes to Mule variables continue to be available outside the For Each scope.
<set-variable variableName="var1" value="var1-BeforeForEach"/>
<set-variable variableName="var2" value="var2-BeforeForEach"/>
<foreach collection="#[['apple', 'banana', 'orange']]">
<choice>
<when expression="#[payload == 'apple']">
<set-variable variableName="var2" value="var2-newValue"/>
<set-variable variableName="var3" value="var3-appleVal"/>
</when>
<when expression="#[payload == 'banana']">
<set-variable variableName="var3" value="#[vars.var3 ++ ' bananaVal']"/>
<!-- var3 will now have value 'var3-appleVal bananaVal'-->
</when>
<otherwise>
<set-variable variableName="var3" value="var3-otherVal"/>
<set-variable variableName="var4" value="var4-val4"/>
</otherwise>
</choice>
<logger level="INFO" doc:name="Logger After Choice"
message='#[ [vars.var1, vars.var2, vars.var3, vars.var4] as Array ]'/>
</foreach>
<logger level="INFO" doc:name="Logger After For Each"
message='#[[vars.var1, vars.var2, vars.var3, vars.var4] as Array]'/>
As the Choice router (<choice />
) executes the processors within each condition, the Logger (Logger After Choice
) prints the following variable values:
// Condition: when payload == 'apple'
.LoggerMessageProcessor:
[var1-BeforeForEach, var2-newValue, var3-appleVal, null]
// Condition: when payload == 'banana'
.LoggerMessageProcessor:
[var1-BeforeForEach, var2-newValue, var3-appleVal bananaVal, null]
// Condition: otherwise
.LoggerMessageProcessor:
[var1-BeforeForEach, var2-newValue, var3-otherVal, var4-val4]
The last values are propagated outside of For Each. The logger (Logger After For Each
) prints the same values as the ones printed after the final choice condition (otherwise
).
[var1-BeforeForEach, var2-newValue, var3-otherVal, var4-val4]