Skip to content

Commit 2035dfc

Browse files
Fix issue with multiple case reactivations with a parent case instance
1 parent 1ac7673 commit 2035dfc

4 files changed

Lines changed: 106 additions & 0 deletions

File tree

modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ReactivateHistoricCaseInstanceCmd.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.flowable.cmmn.api.history.HistoricCaseInstance;
2020
import org.flowable.cmmn.api.runtime.CaseInstance;
2121
import org.flowable.cmmn.api.runtime.CaseInstanceState;
22+
import org.flowable.cmmn.api.runtime.PlanItemInstance;
2223
import org.flowable.cmmn.api.runtime.PlanItemInstanceState;
2324
import org.flowable.cmmn.engine.CmmnEngineConfiguration;
2425
import org.flowable.cmmn.engine.impl.persistence.entity.CaseInstanceEntity;
@@ -34,6 +35,7 @@
3435
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
3536
import org.flowable.common.engine.api.FlowableIllegalStateException;
3637
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
38+
import org.flowable.common.engine.api.constant.ReferenceTypes;
3739
import org.flowable.common.engine.impl.identity.Authentication;
3840
import org.flowable.common.engine.impl.interceptor.Command;
3941
import org.flowable.common.engine.impl.interceptor.CommandContext;
@@ -106,6 +108,30 @@ public CaseInstance execute(CommandContext commandContext) {
106108
+ " cannot be reactivated, as the available condition of its reactivate event listener did not evaluate to true.");
107109
}
108110
}
111+
112+
if (StringUtils.isNotEmpty(instance.getCallbackId()) && ReferenceTypes.PLAN_ITEM_CHILD_CASE.equals(instance.getCallbackType())) {
113+
PlanItemInstanceEntityManager planItemInstanceEntityManager = cmmnEngineConfiguration.getPlanItemInstanceEntityManager();
114+
PlanItemInstance parentPlanItemInstance = planItemInstanceEntityManager.findById(instance.getCallbackId());
115+
if (parentPlanItemInstance != null) {
116+
Case parentCase = CaseDefinitionUtil.getCase(parentPlanItemInstance.getCaseDefinitionId());
117+
PlanItem planItem = parentCase.getPlanModel().findPlanItemForPlanItemDefinitionInPlanFragmentOrDownwards(parentPlanItemInstance.getPlanItemDefinitionId());
118+
PlanItemInstanceEntity toActivateParentPlanItemInstance = planItemInstanceEntityManager
119+
.createPlanItemInstanceEntityBuilder()
120+
.planItem(planItem)
121+
.caseDefinitionId(parentPlanItemInstance.getCaseDefinitionId())
122+
.caseInstanceId(parentPlanItemInstance.getCaseInstanceId())
123+
.tenantId(parentPlanItemInstance.getTenantId())
124+
.create();
125+
126+
toActivateParentPlanItemInstance.setState(PlanItemInstanceState.ACTIVE);
127+
toActivateParentPlanItemInstance.setReferenceId(caseInstanceEntity.getId());
128+
toActivateParentPlanItemInstance.setReferenceType(ReferenceTypes.PLAN_ITEM_CHILD_CASE);
129+
130+
cmmnEngineConfiguration.getCmmnHistoryManager().recordPlanItemInstanceCreated(toActivateParentPlanItemInstance);
131+
132+
caseInstanceEntity.setCallbackId(toActivateParentPlanItemInstance.getId());
133+
}
134+
}
109135

110136
// invoke the identity link interceptor to record the reactivation user
111137
if (cmmnEngineConfiguration.getIdentityLinkInterceptor() != null) {

modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/reactivation/SimpleCaseReactivationTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,39 @@ public void simpleCaseReactivationWithoutAuthenticatedUser() {
405405
tuple(null, "frogs", IdentityLinkType.OWNER)
406406
);
407407
}
408+
409+
@Test
410+
@CmmnDeployment(resources = {
411+
"org/flowable/cmmn/test/reactivation/Parent_Case_Reactivation.cmmn.xml",
412+
"org/flowable/cmmn/test/reactivation/Reactivation_With_Exit_Criterion_Test_Case.cmmn.xml"
413+
})
414+
public void reactivationWithParentCase() {
415+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
416+
.caseDefinitionKey("parentReactivationTestCase")
417+
.start();
418+
419+
CaseInstance childCaseInstance = cmmnRuntimeService.createCaseInstanceQuery().parentCaseInstanceId(caseInstance.getId()).singleResult();
420+
421+
Task task = cmmnTaskService.createTaskQuery().caseInstanceId(childCaseInstance.getId()).singleResult();
422+
cmmnTaskService.complete(task.getId());
423+
424+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(childCaseInstance.getId()).count()).isZero();
425+
426+
CaseInstance reactivatedChildCase = cmmnHistoryService.createCaseReactivationBuilder(childCaseInstance.getId()).reactivate();
427+
task = cmmnTaskService.createTaskQuery().caseInstanceId(reactivatedChildCase.getId()).singleResult();
428+
cmmnTaskService.complete(task.getId());
429+
430+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(reactivatedChildCase.getId()).count()).isZero();
431+
432+
reactivatedChildCase = cmmnHistoryService.createCaseReactivationBuilder(childCaseInstance.getId()).reactivate();
433+
task = cmmnTaskService.createTaskQuery().caseInstanceId(reactivatedChildCase.getId()).singleResult();
434+
cmmnTaskService.complete(task.getId());
435+
436+
Task parentTask = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
437+
cmmnTaskService.complete(parentTask.getId());
438+
439+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();
440+
}
408441

409442
protected HistoricCaseInstance createAndFinishSimpleCase(String caseDefinitionKey) {
410443
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:flowable="http://flowable.org/cmmn"
3+
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
4+
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI" xmlns:design="http://flowable.org/design" targetNamespace="http://flowable.org/cmmn">
5+
<case id="parentReactivationTestCase" name="Parent Reactivation Test Case" flowable:initiatorVariableName="initiator">
6+
<casePlanModel id="onecaseplanmodel1" name="Case plan model" flowable:formFieldValidation="false">
7+
<planItem id="planItem1" name="Parent task" definitionRef="humanTask1" />
8+
<planItem id="planItem2" name="Child Case" definitionRef="childTask" />
9+
10+
<humanTask id="humanTask1" name="Parent task" />
11+
<caseTask id="childTask" name="Child Case">
12+
<caseRefExpression><![CDATA[simpleReactivationTestCase]]></caseRefExpression>
13+
</caseTask>
14+
</casePlanModel>
15+
</case>
16+
</definitions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:flowable="http://flowable.org/cmmn"
3+
xmlns:cmmndi="http://www.omg.org/spec/CMMN/20151109/CMMNDI" xmlns:dc="http://www.omg.org/spec/CMMN/20151109/DC"
4+
xmlns:di="http://www.omg.org/spec/CMMN/20151109/DI" xmlns:design="http://flowable.org/design" targetNamespace="http://flowable.org/cmmn">
5+
<case id="simpleReactivationTestCase" name="Simple Reactivation Test Case" flowable:initiatorVariableName="initiator">
6+
<casePlanModel id="onecaseplanmodel1" name="Case plan model" flowable:formFieldValidation="false">
7+
<planItem id="planItem1" name="Reactivate case" definitionRef="reactivateEventListener1" />
8+
<planItem id="planItem2" name="Task A" definitionRef="humanTask1">
9+
<itemControl>
10+
<repetitionRule flowable:counterVariable="repetitionCounter" flowable:maxInstanceCount="1" />
11+
</itemControl>
12+
</planItem>
13+
14+
<sentry id="sentrycmmnExitSentry">
15+
<planItemOnPart id="sentryOnPartcmmnExitSentry" sourceRef="planItem2">
16+
<standardEvent>complete</standardEvent>
17+
</planItemOnPart>
18+
</sentry>
19+
20+
<eventListener id="reactivateEventListener1" name="Reactivate case" flowable:eventType="reactivate">
21+
<extensionElements>
22+
<flowable:defaultReactivationRule defaultCondition="true"/>
23+
</extensionElements>
24+
</eventListener>
25+
26+
<humanTask id="humanTask1" name="Task A" />
27+
28+
<exitCriterion id="cmmnExitSentry" sentryRef="sentrycmmnExitSentry" flowable:exitEventType="forceComplete" />
29+
</casePlanModel>
30+
</case>
31+
</definitions>

0 commit comments

Comments
 (0)