1

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

malteser
  • 485
  • 2
  • 10
  • 27

5 Answers5

3

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>
Ryan Carter
  • 11,441
  • 2
  • 20
  • 27
  • thanks, wasn't aware of the raise-error processor - I was going to throw exception inside Groovy instead. Yes this seems to be the only option as you posted. I find it weird though that there's no way to carry this out without throwing errors – malteser Jul 23 '19 at 14:45
  • This solution has a major drawback - ERROR is logged by the app which is not good for monitoring logs and troubleshooting errors. – zdenekca Aug 20 '20 at 13:12
1

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.

aled
  • 21,330
  • 3
  • 27
  • 34
  • For each won't suffice as I do not have a collection to iterate over. I have a status flag which is changing and I am checking that flag to make sure the job on the server side has completed before continuing my flow. Previously i could check the flag in the until successful and now this is no longer an option. Recursion used to be an option and now isn't either although this isn't my preferred solution. The only option there is is to check the flag and stay throwing an exception using a groovy script how I see it, so that I can trigger the until-successful loop – malteser Jul 23 '19 at 11:55
0

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.

Johnson
  • 451
  • 2
  • 13
0

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

Alex
  • 4,457
  • 2
  • 20
  • 59
0

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>
zdenekca
  • 1,174
  • 8
  • 8