提交 ea842503 编写于 作者: J Joram Barrez

Cmmn: fix human tasks not deleted on stage exit

上级 e4c4d0a6
......@@ -36,7 +36,7 @@ public abstract class AbstractChangePlanItemInstanceStateOperation extends Abstr
Object behavior = planItemInstanceEntity.getPlanItem().getBehavior();
if (behavior instanceof PlanItemActivityBehavior
&& StateTransition.isPossible(planItemInstanceEntity, getLifeCycleTransition())) {
((PlanItemActivityBehavior) behavior).onStateTransition(planItemInstanceEntity, getLifeCycleTransition());
((PlanItemActivityBehavior) behavior).onStateTransition(commandContext, planItemInstanceEntity, getLifeCycleTransition());
}
}
......
......@@ -14,6 +14,7 @@ package org.flowable.cmmn.engine.impl.behavior;
import org.flowable.cmmn.engine.delegate.DelegatePlanItemInstance;
import org.flowable.cmmn.model.PlanItemTransition;
import org.flowable.engine.common.impl.interceptor.CommandContext;
/**
* Behavior interface, like the {@link CmmnActivityBehavior} and {@link CmmnTriggerableActivityBehavior} interfaces,
......@@ -28,6 +29,6 @@ import org.flowable.cmmn.model.PlanItemTransition;
*/
public interface PlanItemActivityBehavior extends CmmnTriggerableActivityBehavior {
void onStateTransition(DelegatePlanItemInstance planItemInstance, String transition);
void onStateTransition(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition);
}
......@@ -79,10 +79,10 @@ public class CaseTaskActivityBehavior extends TaskActivityBehavior implements Pl
}
@Override
public void onStateTransition(DelegatePlanItemInstance planItemInstance, String transition) {
public void onStateTransition(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition) {
if (PlanItemTransition.TERMINATE.equals(transition) || PlanItemTransition.EXIT.equals(transition)) {
// The plan item will be deleted by the regular TerminatePlanItemOperation
CommandContextUtil.getAgenda().planTerminateCaseInstance(planItemInstance.getReferenceId(), true);
CommandContextUtil.getAgenda(commandContext).planTerminateCaseInstance(planItemInstance.getReferenceId(), true);
}
}
......
......@@ -18,10 +18,13 @@ import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.flowable.cmmn.engine.delegate.DelegatePlanItemInstance;
import org.flowable.cmmn.engine.impl.behavior.PlanItemActivityBehavior;
import org.flowable.cmmn.engine.impl.persistence.entity.PlanItemInstanceEntity;
import org.flowable.cmmn.engine.impl.util.CommandContextUtil;
import org.flowable.cmmn.engine.runtime.PlanItemInstanceState;
import org.flowable.cmmn.model.HumanTask;
import org.flowable.cmmn.model.PlanItemTransition;
import org.flowable.engine.common.api.FlowableException;
import org.flowable.engine.common.api.FlowableIllegalArgumentException;
import org.flowable.engine.common.api.delegate.Expression;
......@@ -38,7 +41,7 @@ import org.joda.time.Period;
/**
* @author Joram Barrez
*/
public class HumanTaskActivityBehavior extends TaskActivityBehavior {
public class HumanTaskActivityBehavior extends TaskActivityBehavior implements PlanItemActivityBehavior {
protected HumanTask humanTask;
......@@ -289,5 +292,16 @@ public class HumanTaskActivityBehavior extends TaskActivityBehavior {
CommandContextUtil.getAgenda(commandContext).planCompletePlanItemInstance((PlanItemInstanceEntity) planItemInstance);
}
@Override
public void onStateTransition(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition) {
if (PlanItemTransition.TERMINATE.equals(transition) || PlanItemTransition.EXIT.equals(transition)) {
TaskService taskService = CommandContextUtil.getTaskService(commandContext);
List<TaskEntity> taskEntities = taskService.findTasksBySubScopeIdScopeType(planItemInstance.getId(), VariableScopeType.CMMN);
for (TaskEntity taskEntity : taskEntities) {
taskService.deleteTask(taskEntity, true);
}
}
}
}
......@@ -93,18 +93,18 @@ public class ProcessTaskActivityBehavior extends TaskActivityBehavior implements
// Triggering the plan item (as opposed to a regular complete) terminates the process instance
CommandContextUtil.getAgenda(commandContext).planCompletePlanItemInstance(planItemInstance);
deleteProcessInstance(planItemInstance, commandContext);
deleteProcessInstance(commandContext, planItemInstance);
}
@Override
public void onStateTransition(DelegatePlanItemInstance planItemInstance, String transition) {
public void onStateTransition(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition) {
// The process task plan item will be deleted by the regular TerminatePlanItemOperation
if (PlanItemTransition.TERMINATE.equals(transition) || PlanItemTransition.EXIT.equals(transition)) {
deleteProcessInstance(planItemInstance, CommandContextUtil.getCommandContext());
deleteProcessInstance(commandContext, planItemInstance);
}
}
protected void deleteProcessInstance(DelegatePlanItemInstance planItemInstance, CommandContext commandContext) {
protected void deleteProcessInstance(CommandContext commandContext, DelegatePlanItemInstance planItemInstance) {
ProcessInstanceService processInstanceService = CommandContextUtil.getCmmnEngineConfiguration(commandContext).getProcessInstanceService();
processInstanceService.deleteProcessInstance(planItemInstance.getReferenceId());
}
......
......@@ -59,13 +59,13 @@ public class StageActivityBehavior extends CoreCmmnTriggerableActivityBehavior i
}
@Override
public void onStateTransition(DelegatePlanItemInstance planItemInstance, String transition) {
public void onStateTransition(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition) {
if (PlanItemTransition.TERMINATE.equals(transition) || PlanItemTransition.EXIT.equals(transition)) {
handleChildPlanItemInstances(planItemInstance, transition);
handleChildPlanItemInstances(commandContext, planItemInstance, transition);
}
}
protected void handleChildPlanItemInstances(DelegatePlanItemInstance planItemInstance, String transition) {
protected void handleChildPlanItemInstances(CommandContext commandContext, DelegatePlanItemInstance planItemInstance, String transition) {
// The stage plan item will be deleted by the regular TerminatePlanItemOperation
PlanItemInstanceEntity planItemInstanceEntity = (PlanItemInstanceEntity) planItemInstance;
List<PlanItemInstanceEntity> childPlanItemInstances = planItemInstanceEntity.getChildren();
......@@ -73,9 +73,9 @@ public class StageActivityBehavior extends CoreCmmnTriggerableActivityBehavior i
for (PlanItemInstanceEntity childPlanItemInstance : childPlanItemInstances) {
if (StateTransition.isPossible(planItemInstance, transition)) {
if (PlanItemTransition.TERMINATE.equals(transition)) {
CommandContextUtil.getAgenda().planTerminatePlanItemInstance(childPlanItemInstance);
CommandContextUtil.getAgenda(commandContext).planTerminatePlanItemInstance(childPlanItemInstance);
} else if (PlanItemTransition.EXIT.equals(transition)) {
CommandContextUtil.getAgenda().planExitPlanItemInstance(childPlanItemInstance);
CommandContextUtil.getAgenda(commandContext).planExitPlanItemInstance(childPlanItemInstance);
}
}
}
......
......@@ -16,6 +16,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.List;
import org.flowable.cmmn.engine.runtime.CaseInstance;
import org.flowable.cmmn.engine.test.CmmnDeployment;
import org.flowable.cmmn.engine.test.FlowableCmmnTestCase;
......@@ -25,6 +27,7 @@ import org.junit.Test;
/**
* @author Tijs Rademakers
* @author Joram Barrez
*/
public class HumanTaskTest extends FlowableCmmnTestCase {
......@@ -66,4 +69,37 @@ public class HumanTaskTest extends FlowableCmmnTestCase {
Authentication.setAuthenticatedUserId(null);
}
@Test
@CmmnDeployment
public void testTaskCompletionExitsStage() {
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("humanTaskCompletionExits")
.start();
assertNotNull(caseInstance);
List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).orderByTaskName().asc().list();
assertEquals("A", tasks.get(0).getName());
assertEquals("B", tasks.get(1).getName());
assertEquals("C", tasks.get(2).getName());
// Completing A should delete B and C
cmmnTaskService.complete(tasks.get(0).getId());
assertEquals(0, cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).count());
assertCaseInstanceEnded(caseInstance);
// Completing C should delete B
CaseInstance caseInstance2 = cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("humanTaskCompletionExits")
.start();
assertNotNull(caseInstance2);
tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance2.getId()).orderByTaskName().asc().list();
cmmnTaskService.complete(tasks.get(2).getId());
Task taskA = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance2.getId()).orderByTaskName().asc().singleResult();
assertNotNull(taskA);
cmmnTaskService.complete(taskA.getId());
assertCaseInstanceEnded(caseInstance2);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flowable="http://flowable.org/cmmn" xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC" xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI" targetNamespace="http://www.flowable.org/casedef">
<case id="humanTaskCompletionExits" name="humanTaskCompletionExits" flowable:initiatorVariableName="initiator">
<casePlanModel id="casePlanModel" name="myCase">
<planItem id="planItem3" definitionRef="sid-39D53051-D4D4-4735-91B6-83740B56171D">
<exitCriterion id="sid-52541DFF-0625-46E0-A967-231ED430DE71" sentryRef="sentry1"></exitCriterion>
</planItem>
<planItem id="planItem4" name="A" definitionRef="sid-D590B655-0731-4A6E-9786-AFBE672B85C9"></planItem>
<sentry id="sentry1">
<planItemOnPart id="sentryOnPart1" sourceRef="planItem2">
<standardEvent>complete</standardEvent>
</planItemOnPart>
</sentry>
<sentry id="sentry2">
<planItemOnPart id="sentryOnPart2" sourceRef="planItem4">
<standardEvent>complete</standardEvent>
</planItemOnPart>
</sentry>
<stage id="sid-39D53051-D4D4-4735-91B6-83740B56171D">
<planItem id="planItem1" name="B" definitionRef="sid-23003DF4-7C09-4F81-9FE6-482F0C1D3350"></planItem>
<planItem id="planItem2" name="C" definitionRef="sid-FAF29B35-382C-4D26-90C3-9BB9F90E6D38"></planItem>
<humanTask id="sid-23003DF4-7C09-4F81-9FE6-482F0C1D3350" name="B"></humanTask>
<humanTask id="sid-FAF29B35-382C-4D26-90C3-9BB9F90E6D38" name="C"></humanTask>
</stage>
<humanTask id="sid-D590B655-0731-4A6E-9786-AFBE672B85C9" name="A"></humanTask>
<exitCriterion id="sid-8E5791DC-04B9-456B-B386-B22484E746DA" sentryRef="sentry2"></exitCriterion>
</casePlanModel>
</case>
<cmmndi:CMMNDI>
<cmmndi:CMMNDiagram id="CMMNDiagram_humanTaskCompletionExits">
<cmmndi:CMMNShape id="CMMNShape_casePlanModel" cmmnElementRef="casePlanModel">
<dc:Bounds height="717.0" width="893.0" x="40.0" y="40.0"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_sid-8E5791DC-04B9-456B-B386-B22484E746DA" cmmnElementRef="sid-8E5791DC-04B9-456B-B386-B22484E746DA">
<dc:Bounds height="22.0" width="14.0" x="926.5272117006105" y="267.45561393657766"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_planItem3" cmmnElementRef="planItem3">
<dc:Bounds height="362.0" width="381.0" x="75.0" y="195.0"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_sid-52541DFF-0625-46E0-A967-231ED430DE71" cmmnElementRef="sid-52541DFF-0625-46E0-A967-231ED430DE71">
<dc:Bounds height="22.0" width="14.0" x="449.49503719021" y="345.900496280979"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_planItem1" cmmnElementRef="planItem1">
<dc:Bounds height="80.0" width="100.0" x="135.0" y="270.0"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_planItem2" cmmnElementRef="planItem2">
<dc:Bounds height="80.0" width="100.0" x="285.0" y="317.90568545227956"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNShape id="CMMNShape_planItem4" cmmnElementRef="planItem4">
<dc:Bounds height="80.0" width="100.0" x="570.0" y="234.56415445308113"></dc:Bounds>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNShape>
<cmmndi:CMMNEdge id="CMMNEdge_sid-AC849C20-AD1F-4A94-BF4B-CB001A78E47E" cmmnElementRef="sid-FAF29B35-382C-4D26-90C3-9BB9F90E6D38" targetCMMNElementRef="sid-FAF29B35-382C-4D26-90C3-9BB9F90E6D38">
<di:waypoint x="335.0" y="357.90568545227956"></di:waypoint>
<di:waypoint x="335.0" y="357.90568545227956"></di:waypoint>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNEdge>
<cmmndi:CMMNEdge id="CMMNEdge_sid-F08681D6-BBFA-4040-BEAB-109CF5D5163F" cmmnElementRef="sid-52541DFF-0625-46E0-A967-231ED430DE71" targetCMMNElementRef="planItem2">
<di:waypoint x="450.05388643998714" y="356.0223046027577"></di:waypoint>
<di:waypoint x="385.0" y="357.08720773379576"></di:waypoint>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNEdge>
<cmmndi:CMMNEdge id="CMMNEdge_sid-3859A9C0-7E37-4379-B4A2-43311319A25C" cmmnElementRef="sid-8E5791DC-04B9-456B-B386-B22484E746DA" targetCMMNElementRef="planItem4">
<di:waypoint x="927.2064028943755" y="277.3883134892326"></di:waypoint>
<di:waypoint x="670.0" y="275.0238061741298"></di:waypoint>
<cmmndi:CMMNLabel></cmmndi:CMMNLabel>
</cmmndi:CMMNEdge>
</cmmndi:CMMNDiagram>
</cmmndi:CMMNDI>
</definitions>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册