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); } }