Skip to content

Commit

Permalink
merge: #10608
Browse files Browse the repository at this point in the history
10608: [Backport stable/8.1] Fix NPE during PI modification r=remcowesterhoud a=backport-action

# Description
Backport of #10601 to `stable/8.1`.

relates to #10537

Co-authored-by: Remco Westerhoud <remco@westerhoud.nl>
  • Loading branch information
zeebe-bors-camunda[bot] and remcowesterhoud committed Oct 5, 2022
2 parents 8b7ebd8 + 5289b6e commit cf40b6c
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ public void processRecord(
instruction -> {
final var elementInstance =
elementInstanceState.getInstance(instruction.getElementInstanceKey());
if (elementInstance == null) {
// at this point this element instance has already been terminated as a result of
// one of the previous terminate instructions. As a result we no longer need to
// terminate it.
return;
}
final var flowScopeKey = elementInstance.getValue().getFlowScopeKey();

terminateElement(elementInstance, sideEffectQueue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,94 @@ public void shouldTerminateSequentialMultiInstanceElement() {
tuple(BpmnElementType.PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATED));
}

@Test
public void shouldTerminateMultiInstanceBodyAndNestedElements() {
// given
ENGINE
.deployment()
.withXmlResource(
Bpmn.createExecutableProcess(PROCESS_ID)
.startEvent()
.subProcess(
"A",
s ->
s.embeddedSubProcess()
.startEvent()
.userTask("B")
.endEvent()
.subProcessDone()
.multiInstance()
.parallel()
.zeebeInputCollectionExpression("[1,2,3]")
.multiInstanceDone())
.endEvent()
.done())
.deploy();
final var processInstanceKey = ENGINE.processInstance().ofBpmnProcessId(PROCESS_ID).create();

final var multiInstanceElement =
RecordingExporter.processInstanceRecords(ProcessInstanceIntent.ELEMENT_ACTIVATED)
.withProcessInstanceKey(processInstanceKey)
.withElementId("A")
.withElementType(BpmnElementType.MULTI_INSTANCE_BODY)
.getFirst();
Assertions.assertThat(
RecordingExporter.processInstanceRecords(ProcessInstanceIntent.ELEMENT_ACTIVATED)
.withProcessInstanceKey(processInstanceKey)
.withElementId("B")
.withElementType(BpmnElementType.USER_TASK)
.limit(3))
.describedAs("Expect that all 3 user tasks are activated")
.hasSize(3);
final var elements =
RecordingExporter.processInstanceRecords(ProcessInstanceIntent.ELEMENT_ACTIVATED)
.withProcessInstanceKey(processInstanceKey)
.withElementType(BpmnElementType.SUB_PROCESS)
.limit(3)
.map(Record::getKey)
.toList();

// when
ENGINE
.processInstance()
.withInstanceKey(processInstanceKey)
.modification()
.terminateElement(multiInstanceElement.getKey())
.terminateElement(elements.get(0))
.terminateElement(elements.get(1))
.terminateElement(elements.get(2))
.modify();

// then
assertThatElementIsTerminated(processInstanceKey, "A");

Assertions.assertThat(
RecordingExporter.processInstanceRecords()
.onlyEvents()
.withProcessInstanceKey(processInstanceKey)
.skipUntil(r -> r.getIntent() == ProcessInstanceIntent.ELEMENT_TERMINATING)
.limitToProcessInstanceTerminated())
.extracting(r -> r.getValue().getBpmnElementType(), Record::getIntent)
.describedAs("Expect that all active instances of the multi-instance have been terminated")
.containsSequence(
tuple(BpmnElementType.MULTI_INSTANCE_BODY, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.USER_TASK, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.SUB_PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.MULTI_INSTANCE_BODY, ProcessInstanceIntent.ELEMENT_TERMINATED),
tuple(BpmnElementType.PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATING),
tuple(BpmnElementType.PROCESS, ProcessInstanceIntent.ELEMENT_TERMINATED));
}

private static long getElementInstanceKeyOfElement(
final long processInstanceKey, final String elementId) {
return RecordingExporter.processInstanceRecords(ProcessInstanceIntent.ELEMENT_ACTIVATED)
Expand Down

0 comments on commit cf40b6c

Please sign in to comment.