This is an automated email from the ASF dual-hosted git repository.
mariofusco pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/main by this push:
new 2c194c0644 [incubator-kie-issues-2105] Conditional named consequence
with break doesn't break (#6461)
2c194c0644 is described below
commit 2c194c0644d51ac475b1f874e0dc580eab31201a
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Mon Sep 29 18:14:10 2025 +0900
[incubator-kie-issues-2105] Conditional named consequence with break
doesn't break (#6461)
---
.../org/drools/core/phreak/PhreakBranchNode.java | 7 +--
.../model/codegen/execmodel/BaseModelTest.java | 4 ++
.../codegen/execmodel/NamedConsequencesTest.java | 65 ++++++++++++++++++++++
3 files changed, 71 insertions(+), 5 deletions(-)
diff --git
a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
index bcae6a1009..6787080c6b 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
@@ -166,11 +166,8 @@ public class PhreakBranchNode {
if (branchTuples.mainLeftTuple != null) {
normalizeStagedTuples( stagedLeftTuples,
branchTuples.mainLeftTuple );
- if (breaking &&
!NodeTypeEnums.isTerminalNode(branchTuples.mainLeftTuple.getSink())) {
- // child exist, new one does not, so delete
- trgLeftTuples.addDelete(branchTuples.mainLeftTuple);
- } else {
- // child exist, new one does, so update
+ if (!breaking) {
+ // default consequence will also be executed
trgLeftTuples.addUpdate(branchTuples.mainLeftTuple);
}
} else if (!breaking) {
diff --git
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/BaseModelTest.java
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/BaseModelTest.java
index a69cdd9a77..f7521b02f9 100644
---
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/BaseModelTest.java
+++
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/BaseModelTest.java
@@ -83,6 +83,10 @@ public abstract class BaseModelTest {
}
}
+ public static Stream<RUN_TYPE> parametersStandardOnly() {
+ return Stream.of(RUN_TYPE.STANDARD_FROM_DRL);
+ }
+
public BaseModelTest() {
}
diff --git
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NamedConsequencesTest.java
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NamedConsequencesTest.java
index 83b8b971c5..f64ad9d270 100644
---
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NamedConsequencesTest.java
+++
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NamedConsequencesTest.java
@@ -625,4 +625,69 @@ public class NamedConsequencesTest extends BaseModelTest {
assertThat(result.size()).isEqualTo(2);
assertThat(result.containsAll(asList("main", "t1"))).isTrue();
}
+
+ @ParameterizedTest
+ @MethodSource("parametersStandardOnly") // fails to build with exec model.
Filed as incubator-kie-drools/issues/6459
+ void testConditionalBreak_defaultBreakDefault(RUN_TYPE runType) {
+ String str = """
+ package com.example.reproducer;
+
+ import org.drools.model.codegen.execmodel.domain.Person;
+
+ global java.util.List result;
+
+ rule R1
+ when
+ Person( $age : age > 10 )
+ if( $age == 21 ) break [ Do2 ]
+ then
+ result.add("R1 Default Consequence: $age = " + $age);
+ then[ Do2 ]
+ result.add("R1 Do2 Consequence: $age = " + $age);
+ end
+
+ rule R2
+ when
+ $p : Person( age == 20 )
+ then
+ result.add("R2");
+ $p.setAge(21);
+ update($p);
+ end
+
+ rule R3
+ when
+ $p : Person( age == 21 )
+ then
+ result.add("R3");
+ $p.setAge(22);
+ update($p);
+ end
+ """;
+
+ // incubator-kie-issues/issues/2105
+ // The expected flow is:
+ // 1. R1 fires, goes to default consequence
+ // 2. R2 fires, sets age to 21
+ // 3. R1 fires, goes to Do2 consequence
+ // 4. R3 fires, sets age to 22
+ // 5. R1 fires, goes to default consequence
+ // The original issue is that the step 3 executes both Do2 and default
consequences.
+ // If we fix PhreakBranchNode.doLeftUpdates to call
`trgLeftTuples.addDelete(branchTuples.mainLeftTuple);` even if
branchTuples.mainLeftTuple.getSink() is TerminalNode,
+ // then next issue arises. The step 5 fails with NPE because the
deletion breaks dormantMatches LinkedList.
+ // The issue reproduces when conditional branch results in "default",
"break", "default" order
+
+ KieSession ksession = getKieSession(runType, str);
+ List<String> result = new ArrayList<>();
+ ksession.setGlobal( "result", result );
+
+ ksession.insert(new Person("John", 20));
+ ksession.fireAllRules();
+
+ assertThat(result).containsExactly("R1 Default Consequence: $age = 20",
+ "R2",
+ "R1 Do2 Consequence: $age = 21",
+ "R3",
+ "R1 Default Consequence: $age =
22");
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]