提交 3cef2b5f 编写于 作者: J Joram Barrez

Fix for ACT-1586: ExecutionQuery returns wrong results when using multi instance on a receive task

上级 efb6bf8e
......@@ -44,7 +44,9 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
protected String superProcessInstanceId;
protected String subProcessInstanceId;
protected SuspensionState suspensionState;
private String businessKey;
protected String businessKey;
protected boolean isActive;
public ExecutionQueryImpl() {
}
......@@ -103,6 +105,10 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
public ExecutionQueryImpl activityId(String activityId) {
this.activityId = activityId;
if (activityId != null) {
isActive = true;
}
return this;
}
......@@ -214,4 +220,8 @@ public class ExecutionQueryImpl extends AbstractVariableQueryImpl<ExecutionQuery
public void setEventSubscriptions(List<EventSubscriptionQueryValue> eventSubscriptions) {
this.eventSubscriptions = eventSubscriptions;
}
public boolean isActive() {
return isActive;
}
}
......@@ -82,6 +82,15 @@ public class ParallelMultiInstanceBehavior extends MultiInstanceActivityBehavior
executeOriginalBehavior(concurrentExecution, loopCounter);
}
}
// See ACT-1586: ExecutionQuery returns wrong results when using multi instance on a receive task
// The parent execution must be set to false, so it wouldn't show up in the execution query
// when using .activityId(something). Do not we cannot nullify the activityId (that would
// have been a better solution), as it would break boundary event behavior.
if (!concurrentExecutions.isEmpty()) {
ExecutionEntity executionEntity = (ExecutionEntity) execution;
executionEntity.setActive(false);
}
}
/**
......
......@@ -163,7 +163,7 @@
and RES.BUSINESS_KEY_ = #{businessKey}
</if>
<if test="activityId != null">
and RES.ACT_ID_ = #{activityId}
and RES.ACT_ID_ = #{activityId} and IS_ACTIVE_ = #{isActive}
</if>
<if test="superProcessInstanceId != null">
<!-- A sub process instance is stored under a certain *execution*, potentially nested.
......
......@@ -991,4 +991,68 @@ public class MultiInstanceTest extends PluggableActivitiTestCase {
assertEquals(0, processInstances.size());
assertProcessEnded(processInstance.getId());
}
@Deployment
public void testMultiInstanceParallelReceiveTask() {
runtimeService.startProcessInstanceByKey("multi-instance-receive");
List<Execution> executions = runtimeService.createExecutionQuery().activityId("theReceiveTask").list();
assertEquals(4, executions.size());
// Complete all four of the executions
for (Execution execution : executions) {
runtimeService.signal(execution.getId());
}
// There is one task after the task
Task task = taskService.createTaskQuery().singleResult();
assertNotNull(task);
taskService.complete(task.getId());
assertEquals(0, runtimeService.createExecutionQuery().count());
}
@Deployment
public void testMultiInstanceParalelReceiveTaskWithTimer() {
Date startTime = new Date();
ClockUtil.setCurrentTime(startTime);
runtimeService.startProcessInstanceByKey("multiInstanceReceiveWithTimer");
List<Execution> executions = runtimeService.createExecutionQuery().activityId("theReceiveTask").list();
assertEquals(3, executions.size());
// Signal only one execution. Then the timer will fire
runtimeService.signal(executions.get(1).getId());
ClockUtil.setCurrentTime(new Date(startTime.getTime() + 60000L));
waitForJobExecutorToProcessAllJobs(10000L, 1000L);
// The process should now be in the task after the timer
Task task = taskService.createTaskQuery().singleResult();
assertEquals("Task after timer", task.getName());
// Completing it should end the process
taskService.complete(task.getId());
assertEquals(0, runtimeService.createExecutionQuery().count());
}
@Deployment
public void testMultiInstanceSequentialReceiveTask() {
runtimeService.startProcessInstanceByKey("multi-instance-receive");
Execution execution = runtimeService.createExecutionQuery().activityId("theReceiveTask").singleResult();
assertNotNull(execution);
// Complete all four of the executions
while (execution != null) {
runtimeService.signal(execution.getId());
execution = runtimeService.createExecutionQuery().activityId("theReceiveTask").singleResult();
}
// There is one task after the task
Task task = taskService.createTaskQuery().singleResult();
assertNotNull(task);
taskService.complete(task.getId());
assertEquals(0, runtimeService.createExecutionQuery().count());
}
}
<?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:activiti="http://activiti.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.activiti.org/test">
<process id="multiInstanceReceiveWithTimer" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="theReceiveTask"></sequenceFlow>
<receiveTask id="theReceiveTask" name="The receive task">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>3</loopCardinality>
</multiInstanceLoopCharacteristics>
</receiveTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow2" sourceRef="theReceiveTask" targetRef="endevent1"></sequenceFlow>
<boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="theReceiveTask" cancelActivity="true">
<timerEventDefinition>
<timeDuration>PT10S</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<userTask id="usertask1" name="Task after timer"></userTask>
<sequenceFlow id="flow3" sourceRef="boundarytimer1" targetRef="usertask1"></sequenceFlow>
<endEvent id="endevent2" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="usertask1" targetRef="endevent2"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess">
<bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="190.0" y="480.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="receivetask1" id="BPMNShape_receivetask1">
<omgdc:Bounds height="55.0" width="105.0" x="270.0" y="470.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="boundarytimer1" id="BPMNShape_boundarytimer1">
<omgdc:Bounds height="30.0" width="30.0" x="340.0" y="520.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="430.0" y="480.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="400.0" y="590.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent2" id="BPMNShape_endevent2">
<omgdc:Bounds height="35.0" width="35.0" x="560.0" y="600.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="225.0" y="497.0"></omgdi:waypoint>
<omgdi:waypoint x="270.0" y="497.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="375.0" y="497.0"></omgdi:waypoint>
<omgdi:waypoint x="430.0" y="497.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="355.0" y="550.0"></omgdi:waypoint>
<omgdi:waypoint x="354.0" y="616.0"></omgdi:waypoint>
<omgdi:waypoint x="400.0" y="617.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="505.0" y="617.0"></omgdi:waypoint>
<omgdi:waypoint x="560.0" y="617.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
\ No newline at end of file
<?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:activiti="http://activiti.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.activiti.org/test">
<process id="multi-instance-receive" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="theReceiveTask"></sequenceFlow>
<receiveTask id="theReceiveTask" name="The receive task">
<multiInstanceLoopCharacteristics isSequential="false">
<loopCardinality>4</loopCardinality>
</multiInstanceLoopCharacteristics>
</receiveTask>
<userTask id="usertask1" name="Task after receive"></userTask>
<sequenceFlow id="flow2" sourceRef="theReceiveTask" targetRef="usertask1"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow3" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
</process>
</definitions>
\ No newline at end of file
<?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:activiti="http://activiti.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.activiti.org/test">
<process id="multi-instance-receive" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="theReceiveTask"></sequenceFlow>
<receiveTask id="theReceiveTask" name="The receive task">
<multiInstanceLoopCharacteristics isSequential="true">
<loopCardinality>7</loopCardinality>
</multiInstanceLoopCharacteristics>
</receiveTask>
<userTask id="usertask1" name="Task after receive"></userTask>
<sequenceFlow id="flow2" sourceRef="theReceiveTask" targetRef="usertask1"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow3" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
</process>
</definitions>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册