malteser
malteser

Reputation: 485

Do while in Mule 4.0

I need to create a 'do while' loop in Mule 4.0. I need a loop which will terminate on a given condition.

Unfortunately, I cannot seem how to do this in Mule 4.0.

Using recursive loops, although not ideal, used to work in Mule 3, but no longer in Mule 4.

I also used to use the until-successful scope to be able to loop until a particular condition is met, however there is no failure expression in Mule 4.0 so I'm not able to check the condition to terminate.

What is the way forward in Mule 4.0 to create a simple do-while loop.

TIA

Upvotes: 1

Views: 8083

Answers (5)

Alex
Alex

Reputation: 4473

I hope there is a hope. I saw DO in some answers but I could not figure out how to add condition. At least it works and does not throw syntax error

%dw 2.0
output application/json
---
do {
     {
      n: 1
     } 
} 

Mule does not have do-while concept. However it could be imitated with a little trick. The only one iterative (to emulate do) function is reduce but it has only one accumulator which is passed from itration to iteration. This only one variable should be used to accumulate results and to indicate end of iterations (to emulate while). Simplest way is to use value as accumulator and sign as indicator. While accumulating summary value negative result indicates end of cycles.

%dw 2.0
var x=[1,2,3,4,5]
output application/json
---
-(x reduce (item, acc=0) -> if (item <4 and acc >= 0) acc + item else if (acc>0) -acc else acc) 

Some complex object could be used to collect results and also have indicator of the end of cycle as part of the object

%dw 2.0
var x=[1,2,3,4,5]
output application/json
---
(x reduce (item, acc={sum:0}) -> if (item < 4 and acc.end==null ) (acc - 'sum' ++ {sum: acc.sum+item}) else ( acc ++ {end:true} )).sum

https://simpleflatservice.com/mule4/DoWhileImitation.html

Upvotes: 0

zdenekca
zdenekca

Reputation: 1172

The following solution mimics "loop" in Mule loop using foreach component without delays or triggering error:

            <set-variable value="#[1 to 100]" doc:name="loopArray"  variableName="loopArray"/>
            <foreach doc:name="For Each" collection="#[vars.loopArray]">
                <choice doc:name="Choice" >
                    <when expression="#[vars.hasNextPage &gt; 0]">                          
                        <flow-ref doc:name="getNextPage" name="getNextPage" />
                    </when>
                    <otherwise >
                        <logger level="DEBUG" doc:name="Logger" message="noop" />
                    </otherwise>
                </choice>
            </foreach>

Upvotes: -1

Johnson
Johnson

Reputation: 461

If you are waiting on a job running on a server to complete before continuing, you could achieve this sort of orchestration with queues - I've used this approach.

After triggering the task place the message on a VM queue. In another flow poll the VM queue with a sensible poll frequency depending on how long you expect the task to complete. Call the server to determine the task status and if not yet complete place the message back on the queue. If the task has completed, proceed with whatever else you need to do.

This approach prevents the stack overflow issue, but isn't viable if the entire process needs to be synchronous for some reason.

Upvotes: 0

Ryan Carter
Ryan Carter

Reputation: 11606

I think until-successful is still the best solution as it gives you a way of breaking out of the loop after X attempts. Just, unfortunately, needs to be controlled with errors. You can use a simple choice and raise-error processor:

       <until-successful  maxRetries="5">
            <http:request method="GET" url="http://something" doc:name="Request" />
            <choice>
                <when expression="#[payload.status !='OK']">
                    <raise-error type="APP:REQUEST_NOT_FINISHED"/>
                </when>
            </choice>
        </until-successful>

Upvotes: 3

aled
aled

Reputation: 25872

Mule flows are not meant to work as a programming language. You have a foreach scope to iterate over things and DataWeave has a functional map() operation.

Calling recursively flows is considered a bad practice and should be avoided. It is possible but it is restricted in Mule 4 because it can easily led to stack overflow errors.

If you absolutely need to do that you should do it in Java or a scripting language.

Perhaps you could describe more in depth the use case you are trying to solve, in case there are other options better suited to the problem.

Upvotes: 1

Related Questions