我需要在我的Mule Flow中使用while循环来从自定义DAO(我使用Expression Transformer访问DAO)加载数据块,直到他不再提供任何项目。 (我不知道DAO提供的项目总数。)Mule 3.4中没有内置while循环。
我的第一个想法是在SubFlow中使用递归反向引用。 SubFlow调用自己直到工作完成。但我认为一个“无法解决的循环引用”的springframework异常。流不能自称。
我的下一个想法是编写一个Custom Transformer并注入SubFlow以循环调用。我使用了David Dossot在他的回答中描述的一些技术:https://stackoverflow.com/a/16532977/2629741
我遇到的问题不仅是原始Flow中的flowVars在SubFlow中无法访问,而且如果我尝试设置一个flowVar,我会得到一个异常(我使用flowVars进行原始Flow之间的通信) SubFlow):
org.mule.api.transformer.TransformerMessagingException: null (java.lang.NullPointerException). Message payload is of type: NullPayload
我的问题是:我如何使SubFlow中的原始Flow可访问的flowVars(反之亦然)我在Custom Transformer中调用(参见下面的类循环)?
骡子流:
<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;
}
}
单元测试:
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);
}
}
答案 0 :(得分:9)
一个不需要任何Java代码的简单方法是:
<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>
在这种情况下,我在10次迭代后停止了
答案 1 :(得分:5)
递归调用Flow最终将以StackOverflowError结束。尝试了它,并且在第70次+迭代时被抛出。
其中一个替代方法是在Custom-transformer中放置一个循环,然后以编程方式调用Flow / Endpoint。