Simulate while loop in Mule 3.4

匿名 (未验证) 提交于 2019-12-03 08:48:34

问题:

I need a while loop in my Mule Flow to load data in chunks from a custom DAO (I use an Expression Transformer to access the DAO) until he does not provide any more items. (I don't know the total amount of items the DAO provides.) There is no build-in while loop in Mule 3.4.

My first Idea was to use a recursive backreference in a SubFlow. The SubFlow calls itself until the work is done. But I ge a springframework exception for an "unresolvable circular reference". A Flow cannot call itself.

My next Idea was to write a Custom Transformer and inject the SubFlow to call in a loop. I use some techics David Dossot described in his answer for this question: https://stackoverflow.com/a/16532977/2629741

The Problem I have is not only that the flowVars from the original Flow are not accessable in the SubFlow but also that I get an exception if I try to set a flowVar (and I use flowVars for the communication between the original Flow and the SubFlow):

org.mule.api.transformer.TransformerMessagingException: null (java.lang.NullPointerException). Message payload is of type: NullPayload 

My Question ist: How do I make the flowVars from the original Flow accessable in the SubFlow (and vice versa) I called inside a Custom Transformer (see class Loop below)?

The Mule flow:

<flow name="test_loopFlow1" doc:name="test_loopFlow1">     <vm:inbound-endpoint exchange-pattern="request-response" path="test_loop" doc:name="VM"/>     <custom-transformer class="com.example.transformer.Loop" doc:name="Java">         <spring:property name="flow" ref="loopTask"/>     </custom-transformer> </flow> <sub-flow name="loopTask" doc:name="loopTask">     <logger message="loop" level="WARN" doc:name="Logger"/>     <set-variable variableName="stop" value="true" doc:name="set flowVar"/> </sub-flow> 

Loop Transformer:

public class Loop extends AbstractMessageTransformer implements FlowConstructAware {    private InterceptingChainLifecycleWrapper _flow = null;     public void setFlow(       final Object value    ) {       this._flow = InterceptingChainLifecycleWrapper.class.cast(value);    }     @Override    public Object transformMessage(       final MuleMessage message,       final String outputEncoding    ) throws TransformerException    {       try {          final MuleEvent muleEvent = new DefaultMuleEvent(             message,             MessageExchangePattern.REQUEST_RESPONSE,             this.flowConstruct          );          message.setInvocationProperty("stop", "false");          do {             /*final MuleEvent resultEvent =*/ this._flow.process(muleEvent);          } while(             ((String) message.getInvocationProperty("stop")).equals("false")          );        } catch (final MuleException e) {          throw new TransformerException(             MessageFactory.createStaticMessage("SubFlow exception."),             this          );       }       return message;    }     FlowConstruct flowConstruct;    @Override    public void setFlowConstruct(final FlowConstruct flowConstruct)    {       this.flowConstruct = flowConstruct;    } } 

Unit Test:

public class LoopTest    extends FunctionalTestCase {    private LocalMuleClient _muleClient = null;     public LoopTest(    ) throws Exception    {       super.setUpMuleContext();       this._muleClient = new DefaultLocalMuleClient(          AbstractMuleContextTestCase.muleContext       );    }     @Override    protected String getConfigResources(    ) {       return "src/main/app/test_loop.xml";    }     @Test    public void testVm(    ) throws Exception    {       this._muleClient.send("vm://test_loop", null, null);    } } 

回答1:

A much simple approach that does not require any java code would be:

<flow name="stackoverflowFlow1" doc:name="stackoverflowFlow1">         <vm:inbound-endpoint exchange-pattern="one-way" path="in" doc:name="VM"/>         <set-variable variableName="#['counter']" value="#[0]" doc:name="Variable"/>         <flow-ref name="stackoverflowFlow2" doc:name="Flow Reference"/>     </flow>     <flow name="stackoverflowFlow2" doc:name="stackoverflowFlow2">         <logger level="INFO" doc:name="Logger"/>         <set-variable variableName="counter" value="#[flowVars['counter']+1]" doc:name="Variable"/>         <choice doc:name="Choice">             <when expression="#[flowVars['counter']==10]">                 <logger level="INFO" doc:name="Logger"/>             </when>             <otherwise>                 <flow-ref name="stackoverflowFlow2" doc:name="Flow Reference"/>             </otherwise>         </choice>     </flow> 

In this case I'm stopping the the while after 10 iterations



回答2:

Recursively calling the Flow will eventually end up with StackOverflowError. Tried it and it was thrown on he 70th+ iteration.

One of the alternatives was to place a loop inside a Custom-transformer then call the Flow/Endpoint programatically.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!