我需要在我的 Mule Flow 中使用 while 循环来从自定义 DAO(我使用表达式转换器访问 DAO)以块的形式加载数据,直到他不再提供任何项目。 (我不知道 DAO 提供的项目总数。)在 Mule 3.4 中没有内置的 while 循环。

我的第一个想法是在 SubFlow 中使用递归反向引用。 SubFlow 调用自身直到工作完成。但是对于“无法解析的循环引用”,我遇到了 springframework 异常。 Flow 不能调用自己。

我的下一个想法是编写一个 Custom Transformer 并注入(inject) 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

我的问题是:如何使原始 Flow 中的 flowVars 可在我在 Custom Transformer 中调用的 SubFlow 中访问(反之亦然)(参见下面的 Loop 类)?

骡子流:
<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>

环路变压器:
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);
   }
}

最佳答案

一种不需要任何 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 次迭代后停止了 while

10-05 19:17