Skip to content

Commit

Permalink
[incubator-kie-issues-1286] Adhoc functionality missing in kogito jBP…
Browse files Browse the repository at this point in the history
…M engine
  • Loading branch information
elguardian committed Jun 3, 2024
1 parent 7e2a311 commit b9a38c2
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ public void nodeInstanceCompleted(NodeInstance nodeInstance, String outType) {
}

private boolean canComplete() {
if (nodeInstances.isEmpty()) {
if (nodeInstances.isEmpty() || nodeInstances.stream().anyMatch(Predicate.not(NodeInstance::isCancelled))) {
return true;
} else {
int eventSubprocessCounter = 0;
Expand Down Expand Up @@ -1228,4 +1228,5 @@ public final void wrap(ProcessInstance<?> kogitoProcessInstance) {
public final ProcessInstance<?> unwrap() {
return this.kogitoProcessInstance;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ private boolean canActivate() {
return getDynamicNode().canActivate(ContextFactory.fromNode(this));
}

private boolean canComplete() {

public boolean canComplete() {
return getNodeInstances(false).isEmpty() && getDynamicNode().canComplete(ContextFactory.fromNode(this));
}

Expand Down Expand Up @@ -113,9 +112,9 @@ public void nodeInstanceCompleted(org.jbpm.workflow.instance.NodeInstance nodeIn
return;
}
}
// TODO what if we reach the end of one branch but others might still need to be created ?
// TODO are we sure there will always be node instances left if we are not done yet?

if (isTerminated(nodeInstance) || canComplete()) {
this.cancelType = CancelType.OBSOLETE;
triggerCompleted(CONNECTION_DEFAULT_TYPE);
}
if (!canComplete()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:tns="http://www.jboss.org/drools">

<process processType="Private" isExecutable="true" id="AdHocSubProcess" name="AdHoc SubProcess" >
<process processType="Private" isExecutable="true" id="AdHocSubProcessAutoComplete" name="AdHoc SubProcess" tns:packageName="org.jbpm.bpmn2.adhoc" >

<!-- nodes -->
<startEvent id="_1" name="StartProcess" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
xmlns:tns="http://www.jboss.org/drools">

<itemDefinition id="_testItem" structureRef="Integer" />
<process processType="Private" isExecutable="true" id="AdHocSubProcess" name="AdHoc SubProcess" >
<process processType="Private" isExecutable="true" id="AdHocSubProcessAutoCompleteExpression" name="AdHoc SubProcess" tns:packageName="org.jbpm.bpmn2.adhoc" >
<!-- process variables -->
<property id="counter" itemSubjectRef="_testItem"/>
<!-- nodes -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
xmlns:tns="http://www.jboss.org/drools">

<itemDefinition id="_testItem" structureRef="Integer" />
<process processType="Private" isExecutable="true" id="AdHocSubProcess" name="AdHoc SubProcess" >
<process processType="Private" isExecutable="true" id="AdHocSubProcessEmptyCompleteExpression" name="AdHoc SubProcess" tns:packageName="org.jbpm.bpmn2.adhoc">
<!-- process variables -->
<property id="counter" itemSubjectRef="_testItem"/>
<!-- nodes -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.omg.org/bpmn20" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:bpsim="http://www.bpsim.org/schemas/1.0" xmlns:color="http://www.omg.org/spec/BPMN/non-normative/color" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:drools="http://www.jboss.org/drools" id="_3hd3Ef_IEeWMZ6FeMZgh_w" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www.jboss.org/drools drools.xsd http://www.bpsim.org/schemas/1.0 bpsim.xsd" exporter="jBPM Designer" exporterVersion="6.2.0" expressionLanguage="http://www.mvel.org/2.0" targetNamespace="http://www.omg.org/bpmn20" typeLanguage="http://www.java.com/javaTypes">
<bpmn2:itemDefinition id="_testItem" structureRef="Boolean" />
<bpmn2:process id="AdHocWithTerminateEnd" drools:packageName="org.jbpm" drools:version="1.0" name="AdHocWithTerminateEnd" isExecutable="true">
<bpmn2:process id="AdHocTerminateEndEvent" drools:packageName="org.jbpm.bpmn2.adhoc" drools:version="1.0" name="AdHocWithTerminateEnd" isExecutable="true">
<bpmn2:property id="complete" itemSubjectRef="_testItem"/>
<bpmn2:startEvent id="processStartEvent" drools:selectable="true" color:background-color="#9acd32" color:border-color="#000000" color:color="#000000" name="">
<bpmn2:extensionElements>
Expand Down
10 changes: 0 additions & 10 deletions jbpm/jbpm-tests/src/test/java/org/jbpm/bpmn2/ActivityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1318,16 +1318,6 @@ public void testInvalidSubProcessNoOutgoingSF() throws Exception {
}
}

@Test
public void testAdHocSubProcessEmptyCompleteExpression() throws Exception {
try {
createKogitoProcessRuntime("BPMN2-AdHocSubProcessEmptyCompleteExpression.bpmn2");
fail("Process should be invalid, there should be build errors");
} catch (RuntimeException e) {
// there should be build errors
}
}

@Test
public void testSubProcessWithTypeVariable() throws Exception {
kruntime = createKogitoProcessRuntime("org/jbpm/bpmn2/subprocess/BPMN2-SubProcessWithTypeVariable.bpmn2");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,20 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;

import org.jbpm.bpmn2.adhoc.AdHocSubProcessAutoCompleteExpressionModel;
import org.jbpm.bpmn2.adhoc.AdHocSubProcessAutoCompleteExpressionProcess;
import org.jbpm.bpmn2.adhoc.AdHocSubProcessAutoCompleteModel;
import org.jbpm.bpmn2.adhoc.AdHocSubProcessAutoCompleteProcess;
import org.jbpm.bpmn2.adhoc.AdHocSubProcessEmptyCompleteExpressionProcess;
import org.jbpm.bpmn2.adhoc.AdHocTerminateEndEventModel;
import org.jbpm.bpmn2.adhoc.AdHocTerminateEndEventProcess;
import org.jbpm.bpmn2.handler.ReceiveTaskHandler;
import org.jbpm.bpmn2.handler.SendTaskHandler;
import org.jbpm.bpmn2.handler.ServiceTaskHandler;
Expand All @@ -42,12 +50,14 @@
import org.jbpm.process.instance.impl.humantask.InternalHumanTaskWorkItem;
import org.jbpm.test.util.NodeLeftCountDownProcessEventListener;
import org.jbpm.test.util.ProcessCompletedCountDownProcessEventListener;
import org.jbpm.test.utils.ProcessTestHelper;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.kie.api.event.process.ProcessStartedEvent;
import org.kie.api.io.Resource;
import org.kie.internal.io.ResourceFactory;
import org.kie.kogito.Application;
import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
Expand All @@ -56,6 +66,7 @@
import org.w3c.dom.Document;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

public class StandaloneBPMNProcessTest extends JbpmBpmn2TestCase {

Expand Down Expand Up @@ -506,24 +517,70 @@ public void testAdHocSubProcess() throws Exception {
}

@Test
@Disabled("Process does not complete.")
public void testAdHocSubProcessAutoComplete() throws Exception {
kruntime = createKogitoProcessRuntime("BPMN2-AdHocSubProcessAutoComplete.bpmn2");
// this autocomplete when we detect
// getActivityInstanceAttribute("numberOfActiveInstances") == 0
Application app = ProcessTestHelper.newApplication();
org.kie.kogito.process.Process<AdHocSubProcessAutoCompleteModel> definition = AdHocSubProcessAutoCompleteProcess.newProcess(app);

TestWorkItemHandler workItemHandler = new TestWorkItemHandler();
kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human Task", workItemHandler);
KogitoProcessInstance processInstance = kruntime.startProcess("AdHocSubProcess");
assertThat(processInstance.getState()).isEqualTo(KogitoProcessInstance.STATE_ACTIVE);
org.kie.kogito.process.ProcessInstance<AdHocSubProcessAutoCompleteModel> instance = definition.createInstance(definition.createModel());
instance.start();
assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_ACTIVE);

KogitoWorkItem workItem = workItemHandler.getWorkItem();
assertThat(workItem).isNull();
kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human Task", workItemHandler);
kruntime.getKieSession().fireAllRules();
workItem = workItemHandler.getWorkItem();
assertThat(workItem).withFailMessage("KogitoWorkItem should not be null.").isNotNull();
kruntime.getKogitoWorkItemManager().registerWorkItemHandler("Human Task", workItemHandler);
kruntime.getKogitoWorkItemManager().completeWorkItem(workItem.getStringId(), null);
assertProcessInstanceCompleted(processInstance.getStringId(), kruntime);
// adhoc we need to trigger the human task
instance.triggerNode("_2-1");
ProcessTestHelper.completeWorkItem(instance, "john", Collections.emptyMap());

assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_COMPLETED);
}

@Test
public void testAdHocSubProcessAutoCompleteExpression() throws Exception {
// this autocomplete when we detect
// getActivityInstanceAttribute("numberOfActiveInstances") == 0
Application app = ProcessTestHelper.newApplication();
org.kie.kogito.process.Process<AdHocSubProcessAutoCompleteExpressionModel> definition = AdHocSubProcessAutoCompleteExpressionProcess.newProcess(app);
AdHocSubProcessAutoCompleteExpressionModel model = definition.createModel();
model.setCounter(3);
org.kie.kogito.process.ProcessInstance<AdHocSubProcessAutoCompleteExpressionModel> instance = definition.createInstance(model);
instance.start();
assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_ACTIVE);

// adhoc we need to trigger the human task
instance.triggerNode("_2-1");
ProcessTestHelper.completeWorkItem(instance, "john", Collections.singletonMap("testHT", 0));

assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_COMPLETED);
}

@Test
public void testAdHocTerminateEndEvent() throws Exception {
// this autocomplete when we detect
// terminate end event within adhoc process the adhoc should finish
Application app = ProcessTestHelper.newApplication();
org.kie.kogito.process.Process<AdHocTerminateEndEventModel> definition = AdHocTerminateEndEventProcess.newProcess(app);
AdHocTerminateEndEventModel model = definition.createModel();
model.setComplete(false);
org.kie.kogito.process.ProcessInstance<AdHocTerminateEndEventModel> instance = definition.createInstance(model);
instance.start();
assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_ACTIVE);

// adhoc we need to trigger the human task
instance.triggerNode("_560E157E-3173-4CFD-9CC6-26676D8B0A02");
ProcessTestHelper.completeWorkItem(instance, "john", Collections.emptyMap());

assertThat(instance.status()).isEqualTo(KogitoProcessInstance.STATE_COMPLETED);
}

@Test
public void testAdHocSubProcessEmptyCompleteExpression() throws Exception {
try {
Application app = ProcessTestHelper.newApplication();
AdHocSubProcessEmptyCompleteExpressionProcess.newProcess(app);
fail("Process should be invalid, there should be build errors");
} catch (RuntimeException e) {
// there should be build errors
}
}

@Test
Expand Down

0 comments on commit b9a38c2

Please sign in to comment.