工具 | 版本 |
---|---|
mule-standalone | 3.9.0 |
Anypoint-Studio | 6.4.0 |
写在前面
不久之前简单地写过一篇博客MULE异常处理的简单使用例子来介绍MULE的异常捕捉的简单使用。经过一段时间学习,发现MULE的确是有异常捕捉机制,但是它的异常捕捉后并不会返回到之前执行的Flow中。如果出现异常后不需要往下继续流程那是没问题的,但是假如在一个循环里面出现异常后并捕捉后想要继续执行下一次循环,那么简单地异常使用就不行了。下面以一个简单的例子说明这个问题。
简单的测试程序弄好后,先预测一下结果:(1)出现异常后仍能正常输出三次循环信息及一次异常捕捉的输出,证明异常捕捉后还能回到触发异常的flow中执行;(2)出现异常后只输出第一次循环的信息及一次异常捕捉的输出,证明异常捕捉后不能返回触发异常的flow中执行。
测试结果
从结果图中可以看到,可以看到只输出一次循环信息及一次异常捕捉后的logger信息,因此证明即使捕捉了异常,异常后面仍有的组件并不会被执行,因为控制权没有返回到我们的测试Flow中。当然在异常捕捉的flow里是可以继续往下走的,但是正如开头假设,是出现异常后处理了不影响主流程使用,而不是出现异常后走异常处理流程。
解决方法
在网上查阅资料后,找到了博客最后参考资料里面社区ferdypruis的回答,刚开始看他的回答不是很明白,后来经过实践终于明白了他的做法是利用一个新的flow(注意不是sub flow)
来包含可能出现异常的流程(或者组件),然后在你的主flow里面通过Flow Reference
来引用这个新的flow,异常捕捉移动到新的flow中。这样子做便能使得新的flow出现异常后触发异常捕捉后仍能不影响主flow后面的组件执行。下面改造上面的例子来演示这种做法:
运行这个改造后的程序观察结果
控制台结果
可以看到改造后的运行结果立刻就输出了三次循环的信息,同时异常捕捉也被触发输出了设置好的信息。符合上面说的第(1)中情况,证明对可能出现异常的流程(或某几个组件)可以将其放置在单独的flow中被引用,这样子便能使得异常触发后仍能不影响后面的流程执行。
最后贴出改造后的示例xml代码
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
<flow name="exception_testFlow">
<poll doc:name="Poll">
<fixed-frequency-scheduler frequency="100000"/>
<logger message="#['开行进行测试.......']" level="INFO" doc:name="Logger"/>
</poll>
<foreach collection="#[[1,2,3]]" doc:name="For Each">
<flow-ref name="call_flow" doc:name="Flow Reference"/>
<logger message="#['第'+flowVars.counter+'循环......']" level="INFO" doc:name="Logger"/>
</foreach>
</flow>
<choice-exception-strategy name="exception_testChoice_Exception_Strategy">
<catch-exception-strategy when="#[exception.causedBy(java.lang.ArithmeticException)]" doc:name="Catch Exception Strategy">
<logger message="#['出现了异常']" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</choice-exception-strategy>
<flow name="call_flow">
<custom-transformer class="cn.cgydawn.test.exception.ThrowAnException" doc:name="Java"/>
<exception-strategy ref="exception_testChoice_Exception_Strategy" doc:name="Reference Exception Strategy"/>
</flow>
</mule>
参考资料
Mule社区ferdypruis的回答