From 92df09d1471f10f14f87a91945c07d42e2ca9733 Mon Sep 17 00:00:00 2001 From: uucoding <1311695042@qq.com> Date: Thu, 22 Jan 2026 22:56:57 +0800 Subject: [PATCH] Fix boundary event iterator desynchronization in ContinueProcessOperation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **The `executeBoundaryEvents` method had a critical iterator desynchronization bug. The `while` loop assumed that the `boundaryEvents` and `boundaryEventExecutions` lists contained matching elements in the same order, but they did not due to inconsistent filtering.** **For example:** - `createBoundaryEvents` returns only: `[TimerExec, ErrorExec]` (compensation events are skipped) - `executeBoundaryEvents` receives: `[Timer, Compensation, Error]` (all events) **Loop pairing comparison:** ``` Expected pairing: Actual incorrect pairing: Timer ↔ TimerExec ✓ Timer ↔ TimerExec ✓ Error ↔ ErrorExec ✓ Compensation ↔ ErrorExec ✗ ``` --- .../impl/agenda/ContinueProcessOperation.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/ContinueProcessOperation.java b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/ContinueProcessOperation.java index 3be9e830b77..52473bfd92e 100644 --- a/modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/ContinueProcessOperation.java +++ b/modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/ContinueProcessOperation.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; import org.flowable.bpmn.model.Activity; import org.flowable.bpmn.model.BoundaryEvent; @@ -360,11 +361,8 @@ protected List createBoundaryEvents(List boundar // The parent execution becomes a scope, and a child execution is created for each of the boundary events for (BoundaryEvent boundaryEvent : boundaryEvents) { - if (!(boundaryEvent.getBehavior() instanceof BoundaryEventRegistryEventActivityBehavior)) { - if (CollectionUtil.isEmpty(boundaryEvent.getEventDefinitions()) - || (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition)) { - continue; - } + if (!isExecutableBoundaryEvent(boundaryEvent)) { + continue; } // A Child execution of the current execution is created to represent the boundary event being active @@ -389,6 +387,7 @@ protected List createBoundaryEvents(List boundar protected void executeBoundaryEvents(List boundaryEvents, List boundaryEventExecutions) { if (!CollectionUtil.isEmpty(boundaryEventExecutions)) { + boundaryEvents = boundaryEvents.stream().filter(this::isExecutableBoundaryEvent).collect(Collectors.toList()); Iterator boundaryEventsIterator = boundaryEvents.iterator(); Iterator boundaryEventExecutionsIterator = boundaryEventExecutions.iterator(); @@ -401,4 +400,14 @@ protected void executeBoundaryEvents(List boundaryEvents, List