简体   繁体   中英

Recursively invoke a Mule flow

Trying to figure out the proper way to recursively invoke a Mule flow.

We have a flow that builds an array of work to do as it runs, then recursively calls itself using a "Flow Reference" inside a "For Each" block. Problem is, we haven't figured out the correct way to pass parameters to this recursive flow, so we're not getting the results we expect.

We tried passing parameters using flow properties (setInvocationParameter() in Groovy), but it seems that these are shared across multiple instances of the flow. For an example, we have the ForEach array iterating through an array containing [2. 3. 4], but depending on timing, some of these values are lost (we typically see 2, then 4 twice - skipping 3).

We've tried different Mule processing strategies without any luck. Mule's default queued-asynchronous has the issues described above. Synchronous doesn't seem to work at all (makes sense since our recursive model probably requires two instances to run at minimum).

Here's the relevant part of the configuration XML (the entire flow is quite large). At the end of the flow is this:

<foreach collection="#[sessionVars['actionArray']]"
         counterVariableName="actionIndex" 
         rootMessageVariableName="actionVar" doc:name="For Each">
   <scripting:component doc:name="Run Each Action">
    <scripting:script engine="Groovy">
         <![CDATA[def aa = message.getSessionProperty('actionArray')
         def this_item = aa.get(message.getInvocationProperty('actionIndex'))
         // Pass the desired action for the recursive call
         message.setInvocationProperty('FlowAction', this_item)
         log.info "Running $this_item" // <- Shows the correct item 
         return]]>
    </scripting:script>
   </scripting:component>
   <flow-ref name="DoAction" doc:name="Do Action"/>
</foreach>

At the front of the flow, there's a logger that displays the "FlowAction" flow variable. When we test with my [2, 3, 4] array, this logger statement is driven three times (as expected), but usually with values 2, 4 and 4.

We're getting the same results on Mule 3.7 and an older 3.4 system we have (both are the Community Edition).

Thanks for any suggestions from the Mule mavens out there...

I'm not sure this is 100% correct, but here's what we did...

After spending a lot of time trying to get the "For Each" and "Flow reference" approach to work reliably, we gave up and switched to a different technique. Our alternative was to delete the For Each block and drive the flow recursively from a short Groovy script:

     . . .

     // Invoke the flow recursively for every item in the array

     Flow flow = muleContext.getRegistry().lookupFlowConstruct("flow name") 
     actions.each   // actions is an array of integers built earlier 
     { item->
          MuleMessage msg = message.createInboundMessage()
          DefaultMuleSession sess = new DefaultMuleSession(flow, muleContext) 
          DefaultMuleEvent  event = new DefaultMuleEvent(msg, MessageExchangePattern.ONE_WAY, sess)

          // Copy the current inbound properties to the new message

          message.getInboundPropertyNames().each
          {
             event.getMessage().setProperty(it, message.getInboundProperty(it), PropertyScope.INBOUND)
          }

          // Copy the current session variables to the new message too

          message.getSessionPropertyNames().each
          {
             event.setSessionVariable(it, message.getSessionProperty(it))
          }

          // Now set the item we want processed as a flow variable

          event.setFlowVariable("Action", item.toString())

          // Finally, trigger the flow (which runs asynchronously)

          flow.process(event).getMessage()
    }

This is working properly in our environment now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM