We would like to use error or signal boundary event to modelize user trigger to go back to previous user task. We are able to manage this principe on service task but we didn’t find a way to make it executing correctly in user task. Is it a reason ? Is it somewhere described how to use boundary events in user task ?
Thanks
Hi Michael,
Boundary events work the same on user tasks as they do on service tasks.
Can you attach a process that demonstrates the issue?
Also, if you are possibly revisiting past steps, you may want to consider modelling your process as a case, this sort of behavior is one of the reasons CMMN was created.
Hi Michel,
I’m not certain how you are throwing the BPMNError in the example you provided.
But the following simple process should demonstrate what you are looking for.
Task 2 includes a simple script TaskListener on the Complete event, the TaskListener tests for a variable “throwIt” and if set (the default) will throw a BPMNError.
This error is caught by an Error Boundary Event, diverts to a script task that unsets throwIt.
Task 1 is repeated, then Task 2.
On the second pass, on completion of Task 2 the process ends (since throwIt is now false).
<?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://flowable.org/test" exporter="Flowable Open Source Modeler" exporterVersion="6.7.3-SNAPSHOT">
<process id="demonstrateSignalAsBoundaryEvent" name="Demonstrate BPMNError as Boundary event" isExecutable="true">
<startEvent id="startnoneevent1" flowable:initiator="initiator" flowable:formFieldValidation="false"></startEvent>
<userTask id="formTask1" name="Task 1" flowable:assignee="$INITIATOR" flowable:formFieldValidation="false">
<extensionElements>
<modeler:activiti-idm-initiator xmlns:modeler="http://flowable.org/modeler"><![CDATA[true]]></modeler:activiti-idm-initiator>
</extensionElements>
</userTask>
<userTask id="formTask2" name="Task 2" flowable:assignee="$INITIATOR" flowable:formFieldValidation="false">
<extensionElements>
<flowable:taskListener event="complete" class="org.flowable.engine.impl.bpmn.listener.ScriptTaskListener">
<flowable:field name="script">
<flowable:string><![CDATA[var BpmnError = Packages.org.flowable.engine.delegate.BpmnError; if(task.getVariable("throwIt")) throw new BpmnError("throwIt");]]></flowable:string>
</flowable:field>
<flowable:field name="language">
<flowable:string><![CDATA[javascript]]></flowable:string>
</flowable:field>
<flowable:field name="resultVariable">
<flowable:string><![CDATA[listenerOutput]]></flowable:string>
</flowable:field>
</flowable:taskListener>
<modeler:activiti-idm-initiator xmlns:modeler="http://flowable.org/modeler"><![CDATA[true]]></modeler:activiti-idm-initiator>
</extensionElements>
</userTask>
<sequenceFlow id="sequenceFlow1" sourceRef="formTask1" targetRef="formTask2"></sequenceFlow>
<sequenceFlow id="sequenceFlow2" sourceRef="startnoneevent1" targetRef="scriptTask2"></sequenceFlow>
<endEvent id="endNoneEvent1"></endEvent>
<sequenceFlow id="sequenceFlow3" sourceRef="formTask2" targetRef="endNoneEvent1"></sequenceFlow>
<sequenceFlow id="sequenceFlow4" sourceRef="intermediateErrorEventBoundary1" targetRef="scriptTask1"></sequenceFlow>
<sequenceFlow id="sequenceFlow5" sourceRef="scriptTask1" targetRef="formTask1"></sequenceFlow>
<scriptTask id="scriptTask1" name="BPMNError Thrown" scriptFormat="javascript" flowable:autoStoreVariables="false">
<script><![CDATA[execution.setVariable("throwIt", false);]]></script>
</scriptTask>
<scriptTask id="scriptTask2" name="Set Variable to throw" scriptFormat="javascript" flowable:autoStoreVariables="false">
<script><![CDATA[execution.setVariable("throwIt", true)]]></script>
</scriptTask>
<sequenceFlow id="sequenceFlow6" sourceRef="scriptTask2" targetRef="formTask1"></sequenceFlow>
<boundaryEvent id="intermediateErrorEventBoundary1" attachedToRef="formTask2">
<errorEventDefinition errorRef="throwIt" flowable:errorVariableLocalScope="false" flowable:errorVariableTransient="false"></errorEventDefinition>
</boundaryEvent>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_demonstrateSignalAsBoundaryEvent">
<bpmndi:BPMNPlane bpmnElement="demonstrateSignalAsBoundaryEvent" id="BPMNPlane_demonstrateSignalAsBoundaryEvent">
<bpmndi:BPMNShape bpmnElement="startnoneevent1" id="BPMNShape_startnoneevent1">
<omgdc:Bounds height="30.0" width="30.0" x="117.0" y="248.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="formTask1" id="BPMNShape_formTask1">
<omgdc:Bounds height="80.0" width="100.0" x="386.0" y="223.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="formTask2" id="BPMNShape_formTask2">
<omgdc:Bounds height="80.0" width="100.0" x="611.0" y="223.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endNoneEvent1" id="BPMNShape_endNoneEvent1">
<omgdc:Bounds height="28.0" width="28.0" x="811.0" y="249.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="scriptTask1" id="BPMNShape_scriptTask1">
<omgdc:Bounds height="80.0" width="100.0" x="611.0" y="363.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="scriptTask2" id="BPMNShape_scriptTask2">
<omgdc:Bounds height="80.0" width="100.0" x="209.0" y="223.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="intermediateErrorEventBoundary1" id="BPMNShape_intermediateErrorEventBoundary1">
<omgdc:Bounds height="30.0" width="30.0" x="646.0" y="289.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow5" id="BPMNEdge_sequenceFlow5" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="611.0" y="403.0"></omgdi:waypoint>
<omgdi:waypoint x="436.0" y="403.0"></omgdi:waypoint>
<omgdi:waypoint x="436.0" y="302.95000000000005"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow6" id="BPMNEdge_sequenceFlow6" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="308.95000000000005" y="263.0"></omgdi:waypoint>
<omgdi:waypoint x="385.99999999993" y="263.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow3" id="BPMNEdge_sequenceFlow3" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="14.0" flowable:targetDockerY="14.0">
<omgdi:waypoint x="710.949999999981" y="263.0"></omgdi:waypoint>
<omgdi:waypoint x="811.0" y="263.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow4" id="BPMNEdge_sequenceFlow4" flowable:sourceDockerX="15.0" flowable:sourceDockerY="15.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="661.0" y="318.94999813604517"></omgdi:waypoint>
<omgdi:waypoint x="661.0" y="363.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow1" id="BPMNEdge_sequenceFlow1" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="485.94999999996566" y="263.0"></omgdi:waypoint>
<omgdi:waypoint x="611.0" y="263.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sequenceFlow2" id="BPMNEdge_sequenceFlow2" flowable:sourceDockerX="15.0" flowable:sourceDockerY="15.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.0">
<omgdi:waypoint x="146.9499988670233" y="263.0"></omgdi:waypoint>
<omgdi:waypoint x="208.99999999991246" y="263.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
Note, throwing BPMNError’s from TaskListeners is only available in the latest version of Flowable ( Releases · flowable/flowable-engine (github.com)) but the concept is the same.
Hope this helps,
Greg