【问题标题】:Simulate while loop in Mule 3.4在 Mule 3.4 中模拟 while 循环
【发布时间】:2013-11-08 19:10:23
【问题描述】:

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

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

我的下一个想法是编写一个自定义转换器并注入 SubFlow 以循环调用。我使用了 David Dossot 在他对这个问题的回答中描述的一些技术:https://stackoverflow.com/a/16532977/2629741

我遇到的问题不仅是原始 Flow 中的 flowVar 在 SubFlow 中不可访问,而且如果我尝试设置 flowVar(并且我使用 flowVars 进行原始 Flow 和子流):

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

我的问题是:如何使来自原始 Flow 的 flowVars 可在我在自定义 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>

循环变压器:

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 loops while-loop mule


    【解决方案1】:

    不需要任何 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

    【讨论】:

    • 那行不通,因为他不知道需要多少次迭代。
    • @genjosanzo 你是对的,SubFlow 不能调用自己,但 Flow 可以!
    • @Andrew Jones 您可以更改条件以使用任何中断条件,而不仅仅是计数器。
    【解决方案2】:

    递归调用 Flow 最终会以 StackOverflowError 告终。试了一下,它在第 70 次以上的迭代中被抛出。

    其中一种选择是在自定义转换器中放置一个循环,然后以编程方式调用流/端点。

    【讨论】:

      猜你喜欢
      • 2013-05-05
      • 2016-02-03
      • 2015-10-10
      • 2015-05-11
      • 2017-04-16
      • 2012-12-03
      • 1970-01-01
      • 2010-10-19
      相关资源
      最近更新 更多