Alternate approach to implement While and Do While Loop in MuleSoft 4.0

Mazhar Ansari
4 min readSep 22, 2021

Note: While copy/paste the code snippet from blog please covert quotes and double quotes.

In my previous blog we discussed how to implement a while loop using a recursive flow call approach to implement a while loop and fetch all the data. In this blog we discuss how we can use for loop scope to implement the same.

Implementing Do While Loop in Mule 4.0

We will implement the Do While loop using the for each scope.

  • Go to Project
  • Import below xml as new Mule Configuration File
<?xml version=”1.0" encoding=”UTF-8"?><mule xmlns:ee=”http://www.mulesoft.org/schema/mule/ee/core" xmlns:http=”http://www.mulesoft.org/schema/mule/http"
xmlns=”http://www.mulesoft.org/schema/mule/core"
xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=”http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
<http:request-config name=”LocalHostService” doc:name=”HTTP Request configuration” doc:id=”81ce8454–039f-4dfa-9b5f-ec800fd69d64" >
<http:request-connection host=”localhost” port=”8081"/>
</http:request-config>
<flow name=”getAllData” doc:id=”424a7f40–3912–400b-a06a-6c4e6e8dc109">
<http:listener doc:name=”Listener” doc:id=”212465ea-f73f-4431–932e-b237651f3289" path=”/getAllData” allowedMethods=”GET” config-ref=”HTTP_Listener_config”/>
<flow-ref doc:name=”mainFlow” doc:id=”251d9282–69ac-4180-b425–54d091d24245" name=”mainFlowAlt” />
</flow>
<sub-flow name=”mainFlowAlt” doc:id=”37e488e2-f6a6–41cd-8bde-919bf58e8bee” >
<ee:transform doc:name=”init count” doc:id=”e26286a2–4390–4ec3–9d22–282f7e03d05f”>
<ee:message>
</ee:message>
<ee:variables>
<ee:set-variable variableName=”count”><![CDATA[%dw 2.0
output application/java
— -
0]]></ee:set-variable>
</ee:variables>
</ee:transform>
<try doc:name=”Try” doc:id=”01a7989f-dfb2–4633–8db9-deda05a2f7d3" >
<foreach doc:name=”For Each” doc:id=”1eb15624-d0cd-470e-919e-051fb9903514" collection=”#[1 to 1000]”>
<flow-ref doc:name=”getPaginatedData” doc:id=”94faa558-a3db-4396–8596–0840edbbfc88" name=”getPaginatedDataAlt” />
</foreach>
<error-handler >
<on-error-continue enableNotifications=”true” logException=”true” doc:name=”On Error Continue” doc:id=”a7f24583-eb95–4188-b47f-339bb2afb1ef” type=”APP:ALL-DATA-COLLECTED”>
<logger level=”INFO” doc:name=”Logger” doc:id=”c3ef72f3–09e9–4fd9–9b63-f017b0d7c7a7" message=”#[‘all data data received’]” />
</on-error-continue>
</error-handler>
</try>
<logger level=”INFO” doc:name=”Logger” doc:id=”0e302227-d955–4724-bf58–660bddd9c1fc” message=”#[payload]”/>
<ee:transform doc:name=”payload” doc:id=”b064eb87–4b8f-4142-bf7c-fdf72e81d87a”>
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output text/plain
— -
“Success”]]></ee:set-payload>
</ee:message>
</ee:transform>
</sub-flow>
<sub-flow name=”getPaginatedDataAlt” doc:id=”4f1aa8a8-c88a-4c08–87b7–03cfb0f626b9" >
<http:request method=”GET” doc:name=”getDataByPageNumber” doc:id=”10babd49–7dd1–4b79–97fb-9606d37a65f4" config-ref=”LocalHostService” path=”/getDataByPageNumber” targetValue=”#[read(payload,’application/json’)]”>
<http:query-params ><![CDATA[#[output application/java
— -
{
fromIndex: (vars.count * 200) + 1,
toIndex: (vars.count + 1) * 200
}]]]></http:query-params>
</http:request>
<ee:transform doc:name=”isDataPresent” doc:id=”9bcb01e0–398c-4cf6–9dee-d622622583fb”>
<ee:message>
</ee:message>
<ee:variables>
<ee:set-variable variableName=”isDataPresent”><![CDATA[%dw 2.0
output application/java
— -
isEmpty(payload..row)]]></ee:set-variable>
</ee:variables>
</ee:transform>
<choice doc:name=”Choice” doc:id=”1e05d24e-480a-4674-a03b-e424f5a23147" >
<when expression=”#[vars.isDataPresent == false]”>
<ee:transform doc:name=”updateCount and accPayload” doc:id=”fc529c7e-e3cf-4d32-a4ad-6d121bd08f53" >
<ee:message >
</ee:message>
<ee:variables >
<ee:set-variable variableName=”count” ><![CDATA[%dw 2.0
output application/java
— -
(vars.count default 0 as Number) + 1]]></ee:set-variable>
<ee:set-variable variableName=”accPayload” ><![CDATA[%dw 2.0
output application/json
— -
if (isEmpty(vars.accPayload))
(payload.response.result.Candidates.row) default []
else
(vars.accPayload default []) ++ payload.response.result.Candidates.row]]></ee:set-variable>
</ee:variables>
</ee:transform>

</when>
<otherwise >
<ee:transform doc:name=”payload” doc:id=”fb7967df-83d4–44f0–8136–10e5bd7455c9">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
— -
if (isEmpty(vars.accPayload))
[]
else
vars.accPayload]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level=”INFO” doc:name=”Logger” doc:id=”d95f3af1-cfc1–4c15-ae63–4d0fea3c2075" message=”#[‘data not found after iteration: ‘ ++ (vars.count default &quot;&quot;)]”/>
<raise-error doc:name=”Raise error” doc:id=”2250bd9e-6d5c-4a8b-8b50–7edc22b3a0bf” type=”APP:ALL-DATA-COLLECTED” />

</otherwise>
</choice>
</sub-flow>
<flow name=”getDataByPageNumber” doc:id=”f34c8326–551e-47c7-bdf6–030eacebb4ec” >
<http:listener doc:name=”Listener” doc:id=”70716b68–07dd-4db1-af92–677659d84cac” config-ref=”HTTP_Listener_config” path=”/getDataByPageNumber”/>
<choice doc:name=”Choice” doc:id=”28db3180–3a6f-4fa1–947d-604063aacef2" >
<when expression=”#[attributes.queryParams.fromIndex as Number &gt; 1000]”>
<ee:transform doc:name=”null Payload” doc:id=”713c1c24–291d-41f2–8763–1c28ca905e52" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
— -
[]]]></ee:set-payload>
</ee:message>
</ee:transform>
</when>
<otherwise >
<ee:transform doc:name=”dummy Payload” doc:id=”fe9cd98f-b3f6–4a91–9771–0c777bf9ad54" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
— -
[
{
“row”: {
“message”: “Hello world!”
}
},
{
“row”: {
“message”: “Hello world!”
}
}
]]]></ee:set-payload>
</ee:message>
</ee:transform>
</otherwise>
</choice>
</flow>
</mule>
  • Get All Data Flow: This Flow Call the mainFlowAlt Flow.
  • Main Flow: This Flow initiates pageNumber (count) variable and calls the getPaginatedDataAlt flow in for each scope. Ideally the looping is put for a higher number so we can fetch the data in all worst case scenarios. I.e. in this example it executes for each for 1000 times. Also It handles a custom exception which is only raised in case all data are fetched and conditions are met for successful execution. This will help break the loop.
  • Get Paginated Data Flow: Is flow which “getDataByPageNumber”, check if data is present, accumulate the output and call the getPaginatedData Flow in case “getDataByPageNumber” max accepted record else it will terminate the Flow by raising a custom exception and return all the data to Main Flow. Custom Exception will be handled by parent flow.
  • To implement the same in your project just replace “getDataByPageNumber” with your service call. And update “isDataPresent”, “updateCount and accPayload” as per your requirement.

Limitation of this approach

  • Need to consider a value for for loop so it ideally should have more value than the number of times it needs to fetch the data.

Scenarios where this can be implemented

This approach can be used when we don’t know how many records we need to fetch.

--

--

Mazhar Ansari

I am seasoned Integration Architect with around 18+ yrs of exp. I have extensively worked on TIBCO and Mulesoft. Mainly in EAI, ESB, SOA, API and BPM projects.