This is an automated email from the ASF dual-hosted git repository.

pefernan pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/incubator-kie-kogito-runtimes.git


The following commit(s) were added to refs/heads/main by this push:
     new aafb1339d3 [incubator-kie-issues#2239] Process compilation fails if 
process has event subprocess with TimerStartEvent (#4184)
aafb1339d3 is described below

commit aafb1339d3c7fd885a0ad4ab034344bd74588e50
Author: Abhiram Gundala <[email protected]>
AuthorDate: Mon Feb 9 09:08:40 2026 -0500

    [incubator-kie-issues#2239] Process compilation fails if process has event 
subprocess with TimerStartEvent (#4184)
    
    * Added trigger and migrated testEventSubprocessTimer
    
    * Added null check
    
    * Migrated testEventSubprocessTimerCycle
---
 .../canonical/EventSubProcessNodeVisitor.java      | 15 +++++
 .../jbpm/compiler/canonical/StartNodeVisitor.java  |  8 +++
 .../core/factory/EventSubProcessNodeFactory.java   | 13 ++++
 .../instance/node/StateBasedNodeInstance.java      |  5 +-
 .../java/org/jbpm/bpmn2/IntermediateEventTest.java | 76 ++++++++++++----------
 5 files changed, 82 insertions(+), 35 deletions(-)

diff --git 
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/EventSubProcessNodeVisitor.java
 
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/EventSubProcessNodeVisitor.java
index 5c468afc3c..4be279cb82 100644
--- 
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/EventSubProcessNodeVisitor.java
+++ 
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/EventSubProcessNodeVisitor.java
@@ -23,15 +23,19 @@ import java.util.Collection;
 import java.util.stream.Stream;
 
 import org.jbpm.process.core.context.variable.VariableScope;
+import org.jbpm.process.core.timer.Timer;
 import org.jbpm.ruleflow.core.factory.EventSubProcessNodeFactory;
 import org.jbpm.workflow.core.node.EventSubProcessNode;
+import org.jbpm.workflow.core.node.StartNode;
 
 import com.github.javaparser.ast.expr.BooleanLiteralExpr;
+import com.github.javaparser.ast.expr.IntegerLiteralExpr;
 import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.StringLiteralExpr;
 
 import static 
org.jbpm.ruleflow.core.factory.EventSubProcessNodeFactory.METHOD_EVENT;
 import static 
org.jbpm.ruleflow.core.factory.EventSubProcessNodeFactory.METHOD_KEEP_ACTIVE;
+import static 
org.jbpm.ruleflow.core.factory.EventSubProcessNodeFactory.METHOD_TIMER;
 
 public class EventSubProcessNodeVisitor extends 
CompositeContextNodeVisitor<EventSubProcessNode> {
 
@@ -60,6 +64,17 @@ public class EventSubProcessNodeVisitor extends 
CompositeContextNodeVisitor<Even
         methods.add(getFactoryMethod(getNodeId(node), METHOD_KEEP_ACTIVE, new 
BooleanLiteralExpr(node.isKeepActive())));
         node.getEvents()
                 .forEach(e -> methods.add(getFactoryMethod(getNodeId(node), 
METHOD_EVENT, new StringLiteralExpr(e))));
+
+        StartNode startNode = node.findStartNode();
+        if (startNode != null && startNode.getTimer() != null) {
+            Timer timer = startNode.getTimer();
+            methods.add(getFactoryMethod(getNodeId(node), METHOD_TIMER,
+                    getOrNullExpr(timer.getDelay()),
+                    getOrNullExpr(timer.getPeriod()),
+                    getOrNullExpr(timer.getDate()),
+                    new 
IntegerLiteralExpr(String.valueOf(timer.getTimeType())).asIntegerLiteralExpr()));
+        }
+
         return methods.stream();
     }
 }
diff --git 
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/StartNodeVisitor.java
 
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/StartNodeVisitor.java
index 42c0ceb3c8..1fb76d74e1 100644
--- 
a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/StartNodeVisitor.java
+++ 
b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/StartNodeVisitor.java
@@ -18,6 +18,7 @@
  */
 package org.jbpm.compiler.canonical;
 
+import java.util.Collections;
 import java.util.Map;
 import java.util.Optional;
 
@@ -27,6 +28,7 @@ import org.jbpm.process.core.context.variable.VariableScope;
 import org.jbpm.process.core.timer.Timer;
 import org.jbpm.ruleflow.core.Metadata;
 import org.jbpm.ruleflow.core.factory.StartNodeFactory;
+import org.jbpm.workflow.core.node.EventSubProcessNode;
 import org.jbpm.workflow.core.node.StartNode;
 
 import com.github.javaparser.ast.NodeList;
@@ -74,6 +76,12 @@ public class StartNodeVisitor extends 
AbstractNodeVisitor<StartNode> {
                         getOrNullExpr(timer.getPeriod()),
                         getOrNullExpr(timer.getDate()),
                         new 
IntegerLiteralExpr(startNode.getTimer().getTimeType())));
+                if (startNode.getParentContainer() instanceof 
EventSubProcessNode eventSubProcess) {
+                    String triggerEventType = "Timer-" + 
eventSubProcess.getId().toExternalFormat();
+                    body.addStatement(getFactoryMethod(getNodeId(startNode), 
METHOD_TRIGGER,
+                            new StringLiteralExpr(triggerEventType),
+                            buildDataAssociationsExpression(startNode, 
Collections.emptyList())));
+                }
                 break;
             }
             case Metadata.EVENT_TYPE_SIGNAL:
diff --git 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/EventSubProcessNodeFactory.java
 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/EventSubProcessNodeFactory.java
index 46aad92e26..8ce12af6c2 100644
--- 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/EventSubProcessNodeFactory.java
+++ 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/factory/EventSubProcessNodeFactory.java
@@ -19,9 +19,11 @@
 package org.jbpm.ruleflow.core.factory;
 
 import org.jbpm.process.core.event.EventTypeFilter;
+import org.jbpm.process.core.timer.Timer;
 import org.jbpm.ruleflow.core.RuleFlowNodeContainerFactory;
 import org.jbpm.ruleflow.core.RuleFlowProcess;
 import org.jbpm.workflow.core.NodeContainer;
+import org.jbpm.workflow.core.impl.DroolsConsequenceAction;
 import org.jbpm.workflow.core.node.EventSubProcessNode;
 import org.kie.api.definition.process.WorkflowElementIdentifier;
 
@@ -31,6 +33,7 @@ public class EventSubProcessNodeFactory<T extends 
RuleFlowNodeContainerFactory<T
 
     public static final String METHOD_KEEP_ACTIVE = "keepActive";
     public static final String METHOD_EVENT = "event";
+    public static final String METHOD_TIMER = "timer";
 
     public EventSubProcessNodeFactory(T nodeContainerFactory, NodeContainer 
nodeContainer, WorkflowElementIdentifier id) {
         super(nodeContainerFactory, nodeContainer, new EventSubProcessNode(), 
id);
@@ -49,4 +52,14 @@ public class EventSubProcessNodeFactory<T extends 
RuleFlowNodeContainerFactory<T
         ((EventSubProcessNode) getCompositeNode()).addEvent(filter);
         return this;
     }
+
+    public EventSubProcessNodeFactory<T> timer(String delay, String period, 
String date, int timeType) {
+        Timer timer = new Timer();
+        timer.setDate(date);
+        timer.setDelay(delay);
+        timer.setPeriod(period);
+        timer.setTimeType(timeType);
+        ((EventSubProcessNode) getCompositeNode()).addTimer(timer, new 
DroolsConsequenceAction("java", ""));
+        return this;
+    }
 }
diff --git 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java
 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java
index fab2a6bf67..b6a4c21197 100755
--- 
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java
+++ 
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/StateBasedNodeInstance.java
@@ -311,7 +311,10 @@ public abstract class StateBasedNodeInstance extends 
ExtendedNodeInstanceImpl im
                         timerInstancesReference.remove(timerInstance.getId());
                     }
                 }
-                executeAction((Action) entry.getValue().getMetaData("Action"));
+                Action action = (Action) 
entry.getValue().getMetaData("Action");
+                if (action != null) {
+                    executeAction(action);
+                }
                 return;
             }
         }
diff --git 
a/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/IntermediateEventTest.java 
b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/IntermediateEventTest.java
index c175c0c388..e37982d5aa 100755
--- a/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/IntermediateEventTest.java
+++ b/jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/IntermediateEventTest.java
@@ -110,10 +110,7 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
-import org.kie.api.event.process.ProcessCompletedEvent;
-import org.kie.api.event.process.ProcessNodeLeftEvent;
-import org.kie.api.event.process.ProcessNodeTriggeredEvent;
-import org.kie.api.event.process.ProcessStartedEvent;
+import org.kie.api.event.process.*;
 import org.kie.api.runtime.rule.FactHandle;
 import org.kie.kogito.Application;
 import org.kie.kogito.event.impl.MessageProducer;
@@ -136,7 +133,7 @@ import 
org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatIterable;
 import static 
org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.*;
 
 public class IntermediateEventTest extends JbpmBpmn2TestCase {
 
@@ -873,60 +870,69 @@ public class IntermediateEventTest extends 
JbpmBpmn2TestCase {
     }
 
     @Test
+    @Timeout(10)
     public void testEventSubprocessTimer() throws Exception {
+        Application app = ProcessTestHelper.newApplication();
         NodeLeftCountDownProcessEventListener countDownListener = new 
NodeLeftCountDownProcessEventListener(
                 "Script Task 1", 1);
-        kruntime = 
createKogitoProcessRuntime("org/jbpm/bpmn2/intermediate/BPMN2-EventSubprocessTimer.bpmn2");
-
-        kruntime.getProcessEventManager().addEventListener(countDownListener);
-
+        EventTrackerProcessListener nodeTriggeredProcessEventListener = new 
EventTrackerProcessListener();
         TestWorkItemHandler workItemHandler = new TestWorkItemHandler();
-        kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human 
Task", workItemHandler);
-        KogitoProcessInstance processInstance = 
kruntime.startProcess("EventSubprocessTimer");
-        assertProcessInstanceActive(processInstance);
+        ProcessTestHelper.registerHandler(app, "Human Task", workItemHandler);
+        ProcessTestHelper.registerProcessEventListener(app, countDownListener);
+        ProcessTestHelper.registerProcessEventListener(app, 
nodeTriggeredProcessEventListener);
 
-        Set<EventDescription<?>> eventDescriptions = 
processInstance.getEventDescriptions();
+        org.kie.kogito.process.Process<EventSubprocessTimerModel> definition = 
EventSubprocessTimerProcess.newProcess(app);
+        org.kie.kogito.process.ProcessInstance<EventSubprocessTimerModel> 
instance = definition.createInstance(definition.createModel());
+        instance.start();
+
+        
assertThat(instance.status()).isEqualTo(org.kie.kogito.process.ProcessInstance.STATE_ACTIVE);
+        Set<EventDescription<?>> eventDescriptions = instance.events();
         
assertThat(eventDescriptions).hasSize(2).extracting("event").contains("workItemCompleted",
                 TIMER_TRIGGERED_EVENT);
         
assertThat(eventDescriptions).extracting("eventType").contains("workItem", 
"timer");
-        
assertThat(eventDescriptions).extracting("processInstanceId").contains(processInstance.getStringId());
+        
assertThat(eventDescriptions).extracting("processInstanceId").contains(instance.id());
         assertThat(eventDescriptions).filteredOn("eventType", 
"timer").hasSize(1).extracting("properties", Map.class)
                 .anyMatch(m -> m.containsKey("TimerID") && 
m.containsKey("Delay"));
+
         countDownListener.waitTillCompleted();
 
-        eventDescriptions = processInstance.getEventDescriptions();
+        eventDescriptions = instance.events();
         
assertThat(eventDescriptions).hasSize(1).extracting("event").contains("workItemCompleted");
         
assertThat(eventDescriptions).extracting("eventType").contains("workItem");
-        
assertThat(eventDescriptions).extracting("processInstanceId").contains(processInstance.getStringId());
+        
assertThat(eventDescriptions).extracting("processInstanceId").contains(instance.id());
 
         KogitoWorkItem workItem = workItemHandler.getWorkItem();
         assertThat(workItem).isNotNull();
-        
kruntime.getKogitoWorkItemManager().completeWorkItem(workItem.getStringId(), 
null);
-        assertProcessInstanceFinished(processInstance, kruntime);
-        assertNodeTriggered(processInstance.getStringId(), "start", "User Task 
1", "end", "Sub Process 1", "start-sub",
-                "Script Task 1", "end-sub");
+        ProcessTestHelper.completeWorkItem(instance, Collections.emptyMap(), 
"john");
 
+        
assertThat(instance.status()).isEqualTo(org.kie.kogito.process.ProcessInstance.STATE_COMPLETED);
+        List<String> trackedNodes = 
nodeTriggeredProcessEventListener.tracked().stream()
+                .map(node -> node.getNodeInstance().getNodeName()).toList();
+        assertTrue(trackedNodes.containsAll(List.of("start", "User Task 1", 
"end", "Sub Process 1", "start-sub",
+                "Script Task 1", "end-sub")));
     }
 
     @Test
-    @RequirePersistence
     public void testEventSubprocessTimerCycle() throws Exception {
+        Application app = ProcessTestHelper.newApplication();
         NodeLeftCountDownProcessEventListener countDownListener = new 
NodeLeftCountDownProcessEventListener(
                 "Script Task 1", 4);
-
-        kruntime = 
createKogitoProcessRuntime("org/jbpm/bpmn2/intermediate/BPMN2-EventSubprocessTimerCycle.bpmn2");
-        kruntime.getProcessEventManager().addEventListener(countDownListener);
-
+        EventTrackerProcessListener nodeTriggeredProcessEventListener = new 
EventTrackerProcessListener();
         TestWorkItemHandler workItemHandler = new TestWorkItemHandler();
-        kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human 
Task", workItemHandler);
-        KogitoProcessInstance processInstance = 
kruntime.startProcess("EventSubprocessTimerCycle");
-        assertProcessInstanceActive(processInstance);
+        ProcessTestHelper.registerHandler(app, "Human Task", workItemHandler);
+        ProcessTestHelper.registerProcessEventListener(app, countDownListener);
+        ProcessTestHelper.registerProcessEventListener(app, 
nodeTriggeredProcessEventListener);
 
-        Set<EventDescription<?>> eventDescriptions = 
processInstance.getEventDescriptions();
+        org.kie.kogito.process.Process<EventSubprocessTimerCycleModel> 
definition = EventSubprocessTimerCycleProcess.newProcess(app);
+        org.kie.kogito.process.ProcessInstance<EventSubprocessTimerCycleModel> 
instance = definition.createInstance(definition.createModel());
+        instance.start();
+
+        
assertThat(instance.status()).isEqualTo(org.kie.kogito.process.ProcessInstance.STATE_ACTIVE);
+        Set<EventDescription<?>> eventDescriptions = instance.events();
         
assertThat(eventDescriptions).hasSize(2).extracting("event").contains("workItemCompleted",
                 TIMER_TRIGGERED_EVENT);
         
assertThat(eventDescriptions).extracting("eventType").contains("workItem", 
"timer");
-        
assertThat(eventDescriptions).extracting("processInstanceId").contains(processInstance.getStringId());
+        
assertThat(eventDescriptions).extracting("processInstanceId").contains(instance.id());
         assertThat(eventDescriptions).filteredOn("eventType", 
"timer").hasSize(1).extracting("properties", Map.class)
                 .anyMatch(m -> m.containsKey("TimerID") && 
m.containsKey("Period"));
 
@@ -934,11 +940,13 @@ public class IntermediateEventTest extends 
JbpmBpmn2TestCase {
 
         KogitoWorkItem workItem = workItemHandler.getWorkItem();
         assertThat(workItem).isNotNull();
-        
kruntime.getKogitoWorkItemManager().completeWorkItem(workItem.getStringId(), 
null);
-        assertProcessInstanceFinished(processInstance, kruntime);
-        assertNodeTriggered(processInstance.getStringId(), "start", "User Task 
1", "end", "start-sub", "Script Task 1",
-                "end-sub");
+        ProcessTestHelper.completeWorkItem(instance, Collections.emptyMap(), 
"john");
 
+        
assertThat(instance.status()).isEqualTo(org.kie.kogito.process.ProcessInstance.STATE_COMPLETED);
+        List<String> trackedNodes = 
nodeTriggeredProcessEventListener.tracked().stream()
+                .map(node -> node.getNodeInstance().getNodeName()).toList();
+        assertTrue(trackedNodes.containsAll(List.of("start", "User Task 1", 
"end", "Sub Process 1", "start-sub",
+                "Script Task 1", "end-sub")));
     }
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to