Flowable中ExecutionListener实现JavaDelegate接口时流程运行异常
Flowable 6.7.2 执行监听器接口误用导致流程流转异常
使用Flowable 6.7.2版本开发工作流时可稳定复现以下异常:
- 为序列流(sequenceFlow)配置的执行监听器(ExecutionListener)采用实现
JavaDelegate接口的方式编写时,流程运行结果不符合预期:直接跳过Production Manager用户任务节点,Station Manager用户任务被重复触发两次 - 将该监听器改为实现
ExecutionListener接口后,流程运行完全正常
问题复现相关材料
流程定义配置
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef" exporter="Flowable Open Source Modeler" exporterVersion="6.7.2"> <process id="MyFlow" name="MyFlow" isExecutable="true"> <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent> <userTask id="sid-5C3D68E7-1D85-43C6-8395-EC625DB7DE07" name="Production Manager" flowable:candidateUsers="ProductionManager,StationManager" flowable:formFieldValidation="true"> <extensionElements> <flowable:taskListener event="create" class="com.sealinetech.demo.listener.MyTaskListener"> <flowable:field name="action"> <flowable:string><![CDATA[notify1]]></flowable:string> </flowable:field> </flowable:taskListener> <modeler:user-info-email-ProductionManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[ProductionManager@foxmail.com]]></modeler:user-info-email-ProductionManager> <modeler:user-info-firstname-ProductionManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[production]]></modeler:user-info-firstname-ProductionManager> <modeler:user-info-lastname-ProductionManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[sealine]]></modeler:user-info-lastname-ProductionManager> <modeler:user-info-email-StationManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[StationManager@foxmail.com]]></modeler:user-info-email-StationManager> <modeler:user-info-firstname-StationManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[station]]></modeler:user-info-firstname-StationManager> <modeler:user-info-lastname-StationManager xmlns:modeler="http://flowable.org/modeler"><![CDATA[sealine]]></modeler:user-info-lastname-StationManager> <modeler:activiti-idm-candidate-user xmlns:modeler="http://flowable.org/modeler"><![CDATA[true]]></modeler:activiti-idm-candidate-user> <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <userTask id="sid-5228C746-FE0B-407A-AE17-7DA540271C46" name="Station Manager" flowable:assignee="StationManager" flowable:formFieldValidation="true"> <extensionElements> <flowable:taskListener event="create" class="com.sealinetech.demo.listener.MyTaskListener"> <flowable:field name="action"> <flowable:string><![CDATA[notify2]]></flowable:string> </flowable:field> </flowable:taskListener> <modeler:activiti-idm-assignee xmlns:modeler="http://flowable.org/modeler"><![CDATA[true]]></modeler:activiti-idm-assignee> <modeler:assignee-info-email xmlns:modeler="http://flowable.org/modeler"><![CDATA[StationManager@foxmail.com]]></modeler:assignee-info-email> <modeler:assignee-info-firstname xmlns:modeler="http://flowable.org/modeler"><![CDATA[station]]></modeler:assignee-info-firstname> <modeler:assignee-info-lastname xmlns:modeler="http://flowable.org/modeler"><![CDATA[sealine]]></modeler:assignee-info-lastname> <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <endEvent id="sid-A46C569A-2C8D-448B-9F98-BBB6C13061E0"></endEvent> <sequenceFlow id="sid-5D648E6B-705D-40C9-B911-1880865A22D3" sourceRef="sid-5C3D68E7-1D85-43C6-8395-EC625DB7DE07" targetRef="sid-5228C746-FE0B-407A-AE17-7DA540271C46"></sequenceFlow> <sequenceFlow id="sid-BED0F7CD-0089-42DA-88F1-9FBE29745F85" sourceRef="sid-5228C746-FE0B-407A-AE17-7DA540271C46" targetRef="sid-A46C569A-2C8D-448B-9F98-BBB6C13061E0"></sequenceFlow> <sequenceFlow id="sid-BBE08CC4-2B4E-415B-ADCE-8B15A2FE55E8" sourceRef="startEvent1" targetRef="sid-5C3D68E7-1D85-43C6-8395-EC625DB7DE07"> <extensionElements> <flowable:executionListener event="take" class="com.sealinetech.demo.listener.MyExecutionListener"> <flowable:field name="action"> <flowable:string><![CDATA[start]]></flowable:string> </flowable:field> </flowable:executionListener> </extensionElements> </sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_MyFlow"> <bpmndi:BPMNPlane bpmnElement="MyFlow" id="BPMNPlane_MyFlow"> <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1"> <omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="sid-5C3D68E7-1D85-43C6-8395-EC625DB7DE07" id="BPMNShape_sid-5C3D68E7-1D85-43C6-8395-EC625DB7DE07"> <omgdc:Bounds height="80.0" width="100.0" x="175.0" y="138.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="sid-5228C746-FE0B-407A-AE17-7DA540271C46" id="BPMNShape_sid-5228C746-FE0B-407A-AE17-7DA540271C46"> <omgdc:Bounds height="79.0" width="98.0" x="315.0" y="138.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="sid-A46C569A-2C8D-448B-9F98-BBB6C13061E0" id="BPMNShape_sid-A46C569A-2C8D-448B-9F98-BBB6C13061E0"> <omgdc:Bounds height="28.0" width="28.0" x="465.0" y="163.5"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sid-BBE08CC4-2B4E-415B-ADCE-8B15A2FE55E8" id="BPMNEdge_sid-BBE08CC4-2B4E-415B-ADCE-8B15A2FE55E8" flowable:sourceDockerX="15.0" flowable:sourceDockerY="15.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0"> <omgdi:waypoint x="129.9499984899576" y="178.0"></omgdi:waypoint> <omgdi:waypoint x="174.9999999999917" y="178.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-BED0F7CD-0089-42DA-88F1-9FBE29745F85" id="BPMNEdge_sid-BED0F7CD-0089-42DA-88F1-9FBE29745F85" flowable:sourceDockerX="35.5" flowable:sourceDockerY="40.0" flowable:targetDockerX="14.0" flowable:targetDockerY="14.0"> <omgdi:waypoint x="412.94999999999476" y="177.7568093385214"></omgdi:waypoint> <omgdi:waypoint x="465.00010099159215" y="177.554279921789"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-5D648E6B-705D-40C9-B911-1880865A22D3" id="BPMNEdge_sid-5D648E6B-705D-40C9-B911-1880865A22D3" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="49.0" flowable:targetDockerY="39.5"> <omgdi:waypoint x="274.94999999999277" y="177.8201438848921"></omgdi:waypoint> <omgdi:waypoint x="315.0" y="177.67607913669062"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
执行监听器实现
MyExecutionListener实现JavaDelegate接口时触发异常,改为实现ExecutionListener接口后流程运行正常:
public class MyExecutionListener implements JavaDelegate /* ExecutionListener */ { private FixedValue action; @Override public void execute(DelegateExecution execution) { System.out.println("Hello ExecutionListener --- " + action.getExpressionText()); } }
任务监听器实现
public class MyTaskListener implements TaskListener { private FixedValue action; @Override public void notify(DelegateTask delegateTask) { System.out.println("Hello TaskListener --- " + action.getExpressionText()); } }
流程启动代码
public String index() { runtimeService.startProcessInstanceByKey("MyFlow"); return "Hello flowable"; }
异常运行表现
- 控制台输出日志:
Hello ExecutionListener --- start Hello TaskListener --- notify2 Hello TaskListener --- notify2
- 流程运行轨迹:无Production Manager节点的执行记录,节点被直接跳过,Station Manager节点重复生成2条待办任务。
问题根因
JavaDelegate是Flowable专门为**服务任务(ServiceTask)**设计的实现接口,框架对该接口的实现类内置了默认的流程向后推进逻辑。当把实现JavaDelegate的类作为执行监听器挂载到序列流的take事件上时,监听器执行完自定义逻辑后,会错误触发内置的流程转发逻辑,导致当前序列流的目标节点(Production Manager)被跳过,执行流直接落到后续节点,同时触发重复的用户任务创建逻辑。ExecutionListener是框架专门为执行监听器场景设计的接口,框架不会为其附加额外的流程流转逻辑,仅执行用户自定义的监听器代码后按正常流程规则推进,因此不会出现异常。
修复方案
所有挂载在序列流、节点上的执行监听器,统一实现org.flowable.engine.delegate.ExecutionListener接口,重写notify方法编写业务逻辑,禁止在监听器场景下使用JavaDelegate接口实现。
内容的提问来源于stack exchange,提问作者Rhett
相关产品推荐
相关产品推荐

