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 3e79d5ddae [incubator-kie-issues#1975] Provide mechanism to fetch the
list of timers associated to a Process Instance. (#3933)
3e79d5ddae is described below
commit 3e79d5ddae315719ac675623b0b4b3996b195356
Author: Pere Fernández <[email protected]>
AuthorDate: Tue May 27 09:27:35 2025 +0200
[incubator-kie-issues#1975] Provide mechanism to fetch the list of timers
associated to a Process Instance. (#3933)
* [incubator-kie-issues#1975] Provide mechanism to fetch the list of timers
associated to a Process Instance.
* - fixes
* - fixes
* - IT test fix
* - Fixed validations & improved testing
* - moving timers to default implementation
---
.../BaseProcessInstanceManagementResource.java | 22 ++-
.../management/ProcessInstanceManagement.java | 4 +
.../BaseProcessInstanceManagementResourceTest.java | 17 ++
.../process/runtime/KogitoNodeInstance.java | 14 +-
.../runtime/KogitoWorkflowProcessInstance.java | 8 +
.../main/java/org/kie/kogito/jobs/JobsService.java | 3 +-
.../java/org/kie/kogito/jobs/TimerDescription.java | 103 ++++++++++++
.../org/kie/kogito/process/ProcessInstance.java | 3 +
.../java/org/jbpm/bpmn2/xml/ProcessHandler.java | 11 ++
.../java/org/jbpm/process/core/timer/Timer.java | 14 +-
.../jbpm/ruleflow/core/RuleFlowProcessFactory.java | 11 ++
.../workflow/core/node/AsyncEventNodeInstance.java | 21 +++
.../workflow/instance/impl/NodeInstanceImpl.java | 7 +-
.../instance/impl/WorkflowProcessInstanceImpl.java | 26 +++
.../workflow/instance/node/EventNodeInstance.java | 27 +++-
.../instance/node/StateBasedNodeInstance.java | 51 ++++--
.../workflow/instance/node/TimerNodeInstance.java | 24 ++-
.../process/impl/AbstractProcessInstance.java | 12 +-
.../src/main/resources/timers.bpmn | 178 +++++++++++++++++++++
.../quarkus/workflows/ProcessManagementIT.java | 109 +++++++++++++
.../ProcessInstanceManagementResource.java | 16 ++
.../ProcessInstanceManagementRestController.java | 13 ++
.../src/main/resources/timers.bpmn | 178 +++++++++++++++++++++
.../springboot/ManagementAddOnTest.java | 76 ++++++++-
.../integrationtests/springboot/TaskTest.java | 2 +-
25 files changed, 902 insertions(+), 48 deletions(-)
diff --git
a/addons/common/process-management/src/main/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResource.java
b/addons/common/process-management/src/main/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResource.java
index 727ccebfb9..5501fc494f 100644
---
a/addons/common/process-management/src/main/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResource.java
+++
b/addons/common/process-management/src/main/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResource.java
@@ -18,10 +18,7 @@
*/
package org.kie.kogito.process.management;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -31,6 +28,7 @@ import org.jbpm.workflow.core.Node;
import org.jbpm.workflow.core.WorkflowProcess;
import org.kie.kogito.Application;
import org.kie.kogito.Model;
+import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
import org.kie.kogito.process.Process;
import org.kie.kogito.process.ProcessError;
@@ -227,6 +225,22 @@ public abstract class
BaseProcessInstanceManagementResource<T> implements Proces
});
}
+ public T doGetProcessInstanceTimers(String processId, String
processInstanceId) {
+ return executeOnProcessInstance(processId, processInstanceId,
processInstance -> buildOkResponse(processInstance.timers()));
+ }
+
+ public T doGetNodeInstanceTimers(String processId, String
processInstanceId, String nodeInstanceId) {
+ return executeOnProcessInstance(processId, processInstanceId,
processInstance -> {
+ Collection<KogitoNodeInstance> nodeInstances =
processInstance.findNodes(nodeInstance ->
nodeInstance.getId().equals(nodeInstanceId));
+
+ if (nodeInstances.isEmpty()) {
+ return badRequestResponse(String.format("Failure getting
timers for node instance '%s' from proces instance '%s', node instance couldn't
be found", nodeInstanceId, processInstanceId));
+ }
+
+ return buildOkResponse(nodeInstances.iterator().next().timers());
+ });
+ }
+
public T doCancelProcessInstanceId(String processId, String
processInstanceId) {
return executeOnProcessInstance(processId, processInstanceId,
processInstance -> {
diff --git
a/addons/common/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagement.java
b/addons/common/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagement.java
index 7aa1a5210b..77ae708789 100644
---
a/addons/common/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagement.java
+++
b/addons/common/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagement.java
@@ -30,6 +30,8 @@ public interface ProcessInstanceManagement<T> {
T getWorkItemsInProcessInstance(String processId, String
processInstanceId);
+ T getProcessInstanceTimers(String processId, String processInstanceId);
+
T retriggerInstanceInError(String processId, String processInstanceId);
T skipInstanceInError(String processId, String processInstanceId);
@@ -40,6 +42,8 @@ public interface ProcessInstanceManagement<T> {
T cancelNodeInstanceId(String processId, String processInstanceId, String
nodeInstanceId);
+ T getNodeInstanceTimers(String processId, String processInstanceId, String
nodeInstanceId);
+
T cancelProcessInstanceId(String processId, String processInstanceId);
T migrateAllInstances(String processId, ProcessMigrationSpec
migrationSpec);
diff --git
a/addons/common/process-management/src/test/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResourceTest.java
b/addons/common/process-management/src/test/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResourceTest.java
index 154bb46308..199d33bd27 100644
---
a/addons/common/process-management/src/test/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResourceTest.java
+++
b/addons/common/process-management/src/test/java/org/kie/kogito/process/management/BaseProcessInstanceManagementResourceTest.java
@@ -125,6 +125,7 @@ class BaseProcessInstanceManagementResourceTest {
lenient().when(processInstance.variables()).thenReturn(variables);
lenient().when(processInstance.id()).thenReturn(PROCESS_INSTANCE_ID);
lenient().when(processInstance.status()).thenReturn(ProcessInstance.STATE_ERROR);
+ lenient().when(processInstance.timers()).thenReturn(List.of());
lenient().when(error.failedNodeId()).thenReturn(NODE_ID_ERROR);
lenient().when(error.errorMessage()).thenReturn("Test error message");
lenient().when(application.unitOfWorkManager()).thenReturn(new
DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory()));
@@ -161,6 +162,11 @@ class BaseProcessInstanceManagementResourceTest {
return null;
}
+ @Override
+ public Object getProcessInstanceTimers(String processId, String
processInstanceId) {
+ return null;
+ }
+
@Override
public Object retriggerInstanceInError(String processId, String
processInstanceId) {
return null;
@@ -181,6 +187,11 @@ class BaseProcessInstanceManagementResourceTest {
return null;
}
+ @Override
+ public Object getNodeInstanceTimers(String processId, String
processInstanceId, String nodeInstanceId) {
+ return null;
+ }
+
@Override
public Object cancelNodeInstanceId(String processId, String
processInstanceId, String nodeInstanceId) {
return null;
@@ -339,4 +350,10 @@ class BaseProcessInstanceManagementResourceTest {
verify(processInstance, times(1)).abort();
assertResultOk(response);
}
+
+ @Test
+ void testGetProcessInstanceTimers() {
+ Object response = tested.doGetProcessInstanceTimers(PROCESS_ID,
PROCESS_INSTANCE_ID);
+ verify(processInstance, times(1)).timers();
+ }
}
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java
b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java
index fc6e46a190..3af349fef7 100644
---
a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java
+++
b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoNodeInstance.java
@@ -18,11 +18,10 @@
*/
package org.kie.kogito.internal.process.runtime;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Map;
+import java.util.*;
import org.kie.api.runtime.process.NodeInstance;
+import org.kie.kogito.jobs.TimerDescription;
public interface KogitoNodeInstance extends NodeInstance {
@@ -82,4 +81,13 @@ public interface KogitoNodeInstance extends NodeInstance {
* @return true if this a retrigger node (see above), false otherwise
*/
boolean isRetrigger();
+
+ /**
+ * Returns the timers associated with this node instance.
+ *
+ * @return a collection of {@link TimerDescription} instances, never null.
+ */
+ default Collection<TimerDescription> timers() {
+ return new ArrayList<>();
+ }
}
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoWorkflowProcessInstance.java
b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoWorkflowProcessInstance.java
index 7023cb2890..c4676f2a1c 100644
---
a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoWorkflowProcessInstance.java
+++
b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/runtime/KogitoWorkflowProcessInstance.java
@@ -23,6 +23,7 @@ import java.util.Date;
import java.util.Optional;
import org.kie.api.runtime.process.WorkflowProcessInstance;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.process.flexible.AdHocFragment;
import org.kie.kogito.process.flexible.Milestone;
@@ -85,6 +86,13 @@ public interface KogitoWorkflowProcessInstance extends
WorkflowProcessInstance,
*/
Collection<Milestone> milestones();
+ /**
+ * Returns the timers associated with the process instance.
+ *
+ * @return a collection of {@link TimerDescription} instances representing
the timers for the process instance, never null.
+ */
+ Collection<TimerDescription> timers();
+
/**
* @return AdHocFragments from the process instances
*/
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/jobs/JobsService.java
b/api/kogito-api/src/main/java/org/kie/kogito/jobs/JobsService.java
index f953c9a79b..1271afcc54 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/jobs/JobsService.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/jobs/JobsService.java
@@ -28,8 +28,7 @@ public interface JobsService {
/**
* Schedules process job that is responsible for starting new process
instances
* based on the given description.
- *
- * @param context of the job
+ *
* @param description defines what kind of process should be started upon
expiration time
* @return returns unique id of the job
*/
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/jobs/TimerDescription.java
b/api/kogito-api/src/main/java/org/kie/kogito/jobs/TimerDescription.java
new file mode 100644
index 0000000000..ee26484c26
--- /dev/null
+++ b/api/kogito-api/src/main/java/org/kie/kogito/jobs/TimerDescription.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.jobs;
+
+import org.kie.api.runtime.process.NodeInstance;
+import org.kie.api.runtime.process.ProcessInstance;
+
+/**
+ * A description of a timer scheduled either by a ProcessInstance or a
NodeInstance.
+ */
+public class TimerDescription {
+
+ private final String processId;
+ private final String processInstanceId;
+ private final String nodeInstanceId;
+ private final String timerId;
+ private final String description;
+
+ private TimerDescription(String processId, String processInstanceId,
String nodeInstanceId, String timerId, String description) {
+ this.processId = processId;
+ this.processInstanceId = processInstanceId;
+ this.nodeInstanceId = nodeInstanceId;
+ this.timerId = timerId;
+ this.description = description;
+ }
+
+ public String getProcessId() {
+ return processId;
+ }
+
+ public String getProcessInstanceId() {
+ return processInstanceId;
+ }
+
+ public String getNodeInstanceId() {
+ return nodeInstanceId;
+ }
+
+ public String getTimerId() {
+ return timerId;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public static class Builder {
+ private final String processId;
+ private final String processInstanceId;
+ private String nodeInstanceId;
+ private String timerId;
+ private String timerDescription;
+
+ private Builder(String processId, String processInstanceId) {
+ this.processId = processId;
+ this.processInstanceId = processInstanceId;
+ }
+
+ private Builder(String processId, String processInstanceId, String
nodeInstanceId) {
+ this(processId, processInstanceId);
+ this.nodeInstanceId = nodeInstanceId;
+ }
+
+ public static Builder ofProcessInstance(ProcessInstance
processInstance) {
+ return new Builder(processInstance.getProcessId(),
processInstance.getId());
+ }
+
+ public static Builder ofNodeInstance(NodeInstance nodeInstance) {
+ return new
Builder(nodeInstance.getProcessInstance().getProcessId(),
nodeInstance.getProcessInstance().getId(), nodeInstance.getId());
+ }
+
+ public Builder timerId(String timerId) {
+ this.timerId = timerId;
+ return this;
+ }
+
+ public Builder timerDescription(String timerDescription) {
+ this.timerDescription = timerDescription;
+ return this;
+ }
+
+ public TimerDescription build() {
+ return new TimerDescription(processId, processInstanceId,
nodeInstanceId, timerId, timerDescription);
+ }
+
+ }
+}
diff --git
a/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessInstance.java
b/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessInstance.java
index 384efbb98e..9c5cad75ed 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessInstance.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/process/ProcessInstance.java
@@ -32,6 +32,7 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
import org.kie.kogito.internal.process.workitem.Policy;
import org.kie.kogito.internal.process.workitem.WorkItemTransition;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.process.flexible.AdHocFragment;
import org.kie.kogito.process.flexible.Milestone;
@@ -276,6 +277,8 @@ public interface ProcessInstance<T> {
*/
Collection<Milestone> milestones();
+ Collection<TimerDescription> timers();
+
/**
* Returns the process adHocFragments
*
diff --git
a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
index 72180a45c1..9bd9b04357 100755
--- a/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
+++ b/jbpm/jbpm-bpmn2/src/main/java/org/jbpm/bpmn2/xml/ProcessHandler.java
@@ -542,6 +542,7 @@ public class ProcessHandler extends BaseAbstractHandler
implements Handler {
String timeCycle = (String) node.getMetaData().get("TimeCycle");
String timeDate = (String) node.getMetaData().get("TimeDate");
Timer timer = new Timer();
+ timer.setName(concatName(compositeNode.getName(), node.getName()));
if (timeDuration != null) {
timer.setDelay(timeDuration);
timer.setTimeType(Timer.TIME_DURATION);
@@ -584,6 +585,16 @@ public class ProcessHandler extends BaseAbstractHandler
implements Handler {
}
}
+ public static String concatName(String prefix, String suffix) {
+ if (prefix == null) {
+ return suffix;
+ } else if (suffix == null) {
+ return prefix;
+ } else {
+ return prefix.concat('-' + suffix);
+ }
+ }
+
private static void linkBoundaryCompensationEvent(Node node) {
/**
* BPMN2 Spec, p. 264:
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/Timer.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/Timer.java
index a39c59c6c1..e2c0f21fa4 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/Timer.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/core/timer/Timer.java
@@ -35,6 +35,7 @@ public class Timer implements Serializable {
private String period;
private String date;
private int timeType;
+ private String name;
public long getId() {
return id;
@@ -68,6 +69,14 @@ public class Timer implements Serializable {
this.date = date;
}
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
@Override
public String toString() {
return "Timer{" +
@@ -76,6 +85,7 @@ public class Timer implements Serializable {
", period='" + period + '\'' +
", date='" + date + '\'' +
", timeType=" + timeType +
+ ", name='" + name + '\'' +
'}';
}
@@ -108,11 +118,11 @@ public class Timer implements Serializable {
}
Timer timer = (Timer) o;
return timeType == timer.timeType && id == timer.id &&
Objects.equals(delay, timer.delay) && Objects.equals(period,
- timer.period) && Objects.equals(date, timer.date);
+ timer.period) && Objects.equals(date, timer.date) &&
Objects.equals(name, timer.name);
}
@Override
public int hashCode() {
- return Objects.hash(id, delay, period, date, timeType);
+ return Objects.hash(id, delay, period, date, timeType, name);
}
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java
index 2234646210..d9d614e9ca 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/ruleflow/core/RuleFlowProcessFactory.java
@@ -322,6 +322,7 @@ public class RuleFlowProcessFactory extends
RuleFlowNodeContainerFactory<RuleFlo
String timeCycle = (String) node.getMetaData().get(TIME_CYCLE);
String timeDate = (String) node.getMetaData().get(TIME_DATE);
Timer timer = new Timer();
+ timer.setName(concatName(compositeNode.getName(), node.getName()));
if (timeDuration != null) {
timer.setDelay(timeDuration);
timer.setTimeType(Timer.TIME_DURATION);
@@ -355,6 +356,16 @@ public class RuleFlowProcessFactory extends
RuleFlowNodeContainerFactory<RuleFlo
}
}
+ public static String concatName(String prefix, String suffix) {
+ if (prefix == null) {
+ return suffix;
+ } else if (suffix == null) {
+ return prefix;
+ } else {
+ return prefix.concat('-' + suffix);
+ }
+ }
+
protected void linkBoundarySignalEvent(Node node, String attachedTo) {
boolean cancelActivity = (Boolean)
node.getMetaData().get(CANCEL_ACTIVITY);
if (cancelActivity) {
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java
index 59cc4263c8..c21b4f91fd 100644
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/AsyncEventNodeInstance.java
@@ -20,6 +20,7 @@ package org.jbpm.workflow.core.node;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
+import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
@@ -33,6 +34,7 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.jobs.ExactExpirationTime;
import org.kie.kogito.jobs.ExpirationTime;
import org.kie.kogito.jobs.JobsService;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import org.kie.kogito.process.ProcessInstance;
import org.kie.kogito.services.uow.BaseWorkUnit;
@@ -41,6 +43,7 @@ import org.kie.kogito.uow.WorkUnit;
import static org.jbpm.ruleflow.core.Metadata.ASYNC_WAITING;
import static
org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;
+import static org.kie.kogito.internal.utils.ConversionUtils.isEmpty;
/**
* Runtime counterpart of an event node.
@@ -162,6 +165,24 @@ public class AsyncEventNodeInstance extends
EventNodeInstance {
this.jobId = jobId;
}
+ @Override
+ public Collection<TimerDescription> timers() {
+ if (isEmpty(jobId)) {
+ return super.timers();
+ }
+
+ Collection<TimerDescription> toReturn = super.timers();
+
+ TimerDescription timerDescription =
TimerDescription.Builder.ofNodeInstance(this)
+ .timerId(this.jobId)
+ .timerDescription(resolveExpression(getNodeName()))
+ .build();
+
+ toReturn.add(timerDescription);
+
+ return toReturn;
+ }
+
@Override
public void triggerCompleted() {
getProcessInstance().removeEventListener(getEventType(),
getEventListener(), true);
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
index b9698aacc2..90083bf58c 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/NodeInstanceImpl.java
@@ -19,12 +19,7 @@
package org.jbpm.workflow.instance.impl;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.regex.Matcher;
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
index 8dc6e80822..106cf6abae 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/impl/WorkflowProcessInstanceImpl.java
@@ -95,6 +95,7 @@ import
org.kie.kogito.internal.process.runtime.KogitoWorkflowProcess;
import org.kie.kogito.internal.process.runtime.MessageException;
import org.kie.kogito.jobs.DurationExpirationTime;
import org.kie.kogito.jobs.JobsService;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import org.kie.kogito.process.BaseEventDescription;
import org.kie.kogito.process.EventDescription;
@@ -120,6 +121,7 @@ import static
org.jbpm.ruleflow.core.Metadata.EVENT_TYPE_SIGNAL;
import static org.jbpm.ruleflow.core.Metadata.IS_FOR_COMPENSATION;
import static
org.jbpm.workflow.instance.impl.DummyEventListener.EMPTY_EVENT_LISTENER;
import static
org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;
+import static org.kie.kogito.internal.utils.ConversionUtils.isNotEmpty;
import static org.kie.kogito.process.flexible.ItemDescription.Status.ACTIVE;
import static org.kie.kogito.process.flexible.ItemDescription.Status.AVAILABLE;
import static org.kie.kogito.process.flexible.ItemDescription.Status.COMPLETED;
@@ -1368,6 +1370,30 @@ public abstract class WorkflowProcessInstanceImpl
extends ProcessInstanceImpl im
.collect(Collectors.toSet());
}
+ @Override
+ public Collection<TimerDescription> timers() {
+
+ List<TimerDescription> toReturn = new ArrayList<>();
+
+ if (isNotEmpty(this.slaTimerId)) {
+ toReturn.add(TimerDescription.Builder.ofProcessInstance(this)
+ .timerId(slaTimerId)
+ .timerDescription("[SLA-Process] " + getProcessName())
+ .build());
+ }
+ if (isNotEmpty(this.cancelTimerId)) {
+ toReturn.add(TimerDescription.Builder.ofProcessInstance(this)
+ .timerId(cancelTimerId)
+ .timerDescription("[CANCEL-Process] " + getProcessName())
+ .build());
+ }
+ getNodeInstances().stream().map(nodeInstance -> (KogitoNodeInstance)
nodeInstance)
+ .flatMap(nodeInstance -> nodeInstance.timers().stream())
+ .forEach(toReturn::add);
+
+ return toReturn;
+ }
+
private <N extends org.kie.api.definition.process.Node> Stream<N>
getNodesByType(Class<N> nodeClass) {
return
getWorkflowProcess().getNodesRecursively().stream().filter(nodeClass::isInstance).map(nodeClass::cast);
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java
index 8506251a30..72961609f1 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/EventNodeInstance.java
@@ -19,11 +19,7 @@
package org.jbpm.workflow.instance.node;
import java.io.Serializable;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
@@ -40,6 +36,7 @@ import
org.kie.kogito.internal.process.event.KogitoEventListener;
import org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.jobs.JobsService;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.process.BaseEventDescription;
import org.kie.kogito.process.EventDescription;
import org.kie.kogito.process.NamedDataType;
@@ -47,6 +44,8 @@ import org.kie.kogito.timer.TimerInstance;
import static
org.jbpm.workflow.instance.impl.DummyEventListener.EMPTY_EVENT_LISTENER;
import static
org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;
+import static org.kie.kogito.internal.utils.ConversionUtils.isEmpty;
+import static org.kie.kogito.internal.utils.ConversionUtils.isNotEmpty;
/**
* Runtime counterpart of an event node.
@@ -115,7 +114,7 @@ public class EventNodeInstance extends
ExtendedNodeInstanceImpl implements Kogit
}
private void cancelSlaTimer() {
- if (this.slaTimerId != null && !this.slaTimerId.trim().isEmpty()) {
+ if (isNotEmpty(this.slaTimerId)) {
JobsService jobService = ((InternalProcessRuntime)
getProcessInstance().getKnowledgeRuntime().getProcessRuntime()).getJobsService();
jobService.cancelJob(this.slaTimerId);
logger.debug("SLA Timer {} has been canceled", this.slaTimerId);
@@ -229,7 +228,7 @@ public class EventNodeInstance extends
ExtendedNodeInstanceImpl implements Kogit
} else {
getProcessInstance().addEventListener(eventType,
getEventListener(), true);
}
- if (this.slaTimerId != null && !this.slaTimerId.trim().isEmpty()) {
+ if (isNotEmpty(this.slaTimerId)) {
addTimerListener();
}
}
@@ -279,4 +278,18 @@ public class EventNodeInstance extends
ExtendedNodeInstanceImpl implements Kogit
return Collections.singleton(new BaseEventDescription(getEventType(),
getNodeDefinitionId(), getNodeName(), "signal", getStringId(),
getProcessInstance().getStringId(), dataType));
}
+ @Override
+ public Collection<TimerDescription> timers() {
+ if (isEmpty(slaTimerId)) {
+ return super.timers();
+ }
+
+ Collection<TimerDescription> toReturn = super.timers();
+ TimerDescription slaTimer =
TimerDescription.Builder.ofNodeInstance(this)
+ .timerId(slaTimerId)
+ .timerDescription("[SLA] " + resolveExpression(getNodeName()))
+ .build();
+ toReturn.add(slaTimer);
+ return toReturn;
+ }
}
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 1489004472..2aee1f690e 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
@@ -18,12 +18,7 @@
*/
package org.jbpm.workflow.instance.node;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import org.drools.core.common.InternalAgenda;
import org.drools.core.common.ReteEvaluator;
@@ -48,10 +43,7 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessContext;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
import org.kie.kogito.internal.process.runtime.KogitoProcessRuntime;
-import org.kie.kogito.jobs.DurationExpirationTime;
-import org.kie.kogito.jobs.ExactExpirationTime;
-import org.kie.kogito.jobs.ExpirationTime;
-import org.kie.kogito.jobs.JobsService;
+import org.kie.kogito.jobs.*;
import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import org.kie.kogito.process.expr.Expression;
import org.kie.kogito.process.expr.ExpressionHandlerFactory;
@@ -62,6 +54,7 @@ import org.slf4j.LoggerFactory;
import static
org.jbpm.process.core.constants.CalendarConstants.BUSINESS_CALENDAR_ENVIRONMENT_KEY;
import static org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE;
import static
org.jbpm.workflow.instance.node.TimerNodeInstance.TIMER_TRIGGERED_EVENT;
+import static org.kie.kogito.internal.utils.ConversionUtils.isNotEmpty;
public abstract class StateBasedNodeInstance extends ExtendedNodeInstanceImpl
implements EventBasedNodeInstanceInterface, KogitoEventListener {
@@ -332,7 +325,7 @@ public abstract class StateBasedNodeInstance extends
ExtendedNodeInstanceImpl im
@Override
public void addEventListeners() {
- if (timerInstances != null && (!timerInstances.isEmpty()) ||
(this.slaTimerId != null && !this.slaTimerId.trim().isEmpty())) {
+ if (timerInstances != null && (!timerInstances.isEmpty()) ||
isNotEmpty(this.slaTimerId)) {
addTimerListener();
}
if (slaCompliance == KogitoProcessInstance.SLA_PENDING) {
@@ -417,7 +410,7 @@ public abstract class StateBasedNodeInstance extends
ExtendedNodeInstanceImpl im
}
private void cancelSlaTimer() {
- if (this.slaTimerId != null && !this.slaTimerId.trim().isEmpty()) {
+ if (isNotEmpty(this.slaTimerId)) {
JobsService jobService = ((InternalProcessRuntime)
getProcessInstance().getKnowledgeRuntime().getProcessRuntime()).getJobsService();
jobService.cancelJob(this.slaTimerId);
logger.debug("SLA Timer {} has been canceled", this.slaTimerId);
@@ -467,4 +460,38 @@ public abstract class StateBasedNodeInstance extends
ExtendedNodeInstanceImpl im
context.getContextData().put("Exception", e);
return context;
}
+
+ @Override
+ public Collection<TimerDescription> timers() {
+ Collection<TimerDescription> toReturn = super.timers();
+
+ if (isNotEmpty(slaTimerId)) {
+ TimerDescription slaTimer =
TimerDescription.Builder.ofNodeInstance(this)
+ .timerId(slaTimerId)
+ .timerDescription("[SLA] " +
resolveExpression(getNodeName()))
+ .build();
+ toReturn.add(slaTimer);
+ }
+
+ if (timerInstancesReference != null) {
+ Set<Timer> nodeTimers = getEventBasedNode().getTimers().keySet();
+ for (Timer timer : nodeTimers) {
+ Optional<String> jobIdOptional =
timerInstancesReference.entrySet()
+ .stream()
+ .filter(entry ->
String.valueOf(timer.getId()).equals(entry.getValue()))
+ .findFirst()
+ .map(Map.Entry::getKey);
+
+ jobIdOptional.ifPresent(jobId -> {
+ TimerDescription timerDescription =
TimerDescription.Builder.ofNodeInstance(this)
+ .timerId(jobId)
+
.timerDescription(resolveExpression(timer.getName()))
+ .build();
+ toReturn.add(timerDescription);
+ });
+ }
+ }
+
+ return toReturn;
+ }
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java
index 5ca0c76a28..788aecc725 100755
---
a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/TimerNodeInstance.java
@@ -18,13 +18,7 @@
*/
package org.jbpm.workflow.instance.node;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import org.jbpm.process.core.context.exception.ExceptionScope;
import org.jbpm.process.instance.InternalProcessRuntime;
@@ -36,6 +30,7 @@ import
org.kie.kogito.internal.process.runtime.KogitoNodeInstance;
import org.kie.kogito.internal.process.workitem.WorkItemExecutionException;
import org.kie.kogito.jobs.ExpirationTime;
import org.kie.kogito.jobs.JobsService;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.jobs.descriptors.ProcessInstanceJobDescription;
import org.kie.kogito.process.BaseEventDescription;
import org.kie.kogito.process.EventDescription;
@@ -157,4 +152,19 @@ public class TimerNodeInstance extends
StateBasedNodeInstance implements EventLi
return Collections
.singleton(new BaseEventDescription(TIMER_TRIGGERED_EVENT,
getNodeDefinitionId(), getNodeName(), "timer", getStringId(),
getProcessInstance().getStringId(), null, properties));
}
+
+ @Override
+ public Collection<TimerDescription> timers() {
+ if (this.timerId == null) {
+ return super.timers();
+ }
+
+ Collection<TimerDescription> toReturn = super.timers();
+ TimerDescription timerDescription =
TimerDescription.Builder.ofNodeInstance(this)
+ .timerId(timerId)
+ .timerDescription(resolveExpression(getNodeName()))
+ .build();
+ toReturn.add(timerDescription);
+ return toReturn;
+ }
}
diff --git
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
index 81c2275048..df5ccb715f 100644
---
a/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
+++
b/jbpm/jbpm-flow/src/main/java/org/kie/kogito/process/impl/AbstractProcessInstance.java
@@ -59,6 +59,7 @@ import
org.kie.kogito.internal.process.workitem.KogitoWorkItem;
import org.kie.kogito.internal.process.workitem.Policy;
import org.kie.kogito.internal.process.workitem.WorkItemNotFoundException;
import org.kie.kogito.internal.process.workitem.WorkItemTransition;
+import org.kie.kogito.jobs.TimerDescription;
import org.kie.kogito.process.EventDescription;
import org.kie.kogito.process.MutableProcessInstances;
import org.kie.kogito.process.NodeInstanceNotFoundException;
@@ -652,14 +653,21 @@ public abstract class AbstractProcessInstance<T extends
Model> implements Proces
@Override
public Collection<Milestone> milestones() {
return processInstanceLockStrategy.executeOperation(id, () -> {
- return processInstance.milestones();
+ return processInstance().milestones();
+ });
+ }
+
+ @Override
+ public Collection<TimerDescription> timers() {
+ return processInstanceLockStrategy.executeOperation(id, () -> {
+ return processInstance().timers();
});
}
@Override
public Collection<AdHocFragment> adHocFragments() {
return processInstanceLockStrategy.executeOperation(id, () -> {
- return processInstance.adHocFragments();
+ return processInstance().adHocFragments();
});
}
diff --git
a/quarkus/addons/process-management/integration-tests/src/main/resources/timers.bpmn
b/quarkus/addons/process-management/integration-tests/src/main/resources/timers.bpmn
new file mode 100644
index 0000000000..63b3bac089
--- /dev/null
+++
b/quarkus/addons/process-management/integration-tests/src/main/resources/timers.bpmn
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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: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="_FbQn4Bn5ED6qPL2RHaehww"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd
http://www. [...]
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_PriorityInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_CommentInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_DescriptionInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_CreatedByInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_GroupIdInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_ContentInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotStartedReassignInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotCompletedReassignInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotStartedNotifyInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotCompletedNotifyInputXItem"
structureRef="Object"/>
+ <bpmn2:collaboration id="_11F36E9B-11DF-499D-896C-0D73277FBCB5"
name="Default Collaboration">
+ <bpmn2:participant id="_3CC3D518-96F1-4246-B77A-BD69EA62333A" name="Pool
Participant" processRef="timers"/>
+ </bpmn2:collaboration>
+ <bpmn2:process id="timers" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="timers" isExecutable="true"
processType="Public">
+ <bpmn2:extensionElements>
+ <drools:metaData name="customSLADueDate">
+ <drools:metaValue><![CDATA[200m]]></drools:metaValue>
+ </drools:metaData>
+ <drools:metaData name="processDuration">
+ <drools:metaValue><![CDATA[PT1M]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:sequenceFlow id="_2CCE6D96-07C9-4196-A3DA-2FA12675606B"
sourceRef="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
targetRef="_A2B595B9-3809-487E-B354-677DE3EB9B83"/>
+ <bpmn2:sequenceFlow id="_217C7B88-D29D-479F-9DDA-49C505B55DB3"
sourceRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490"
targetRef="_66215F0B-D52C-4DEF-8BAE-3524FD59A246"/>
+ <bpmn2:sequenceFlow id="_BB186F29-4721-4C71-BFAA-D816C47ED670"
sourceRef="_F35EC805-22D5-4833-B56D-9DE16B4B258B"
targetRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490"/>
+ <bpmn2:endEvent id="_A2B595B9-3809-487E-B354-677DE3EB9B83">
+ <bpmn2:incoming>_2CCE6D96-07C9-4196-A3DA-2FA12675606B</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:endEvent id="_66215F0B-D52C-4DEF-8BAE-3524FD59A246">
+ <bpmn2:incoming>_217C7B88-D29D-479F-9DDA-49C505B55DB3</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:userTask id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490" name="Task">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Task]]></drools:metaValue>
+ </drools:metaData>
+ <drools:metaData name="customSLADueDate">
+ <drools:metaValue><![CDATA[150m]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_BB186F29-4721-4C71-BFAA-D816C47ED670</bpmn2:incoming>
+ <bpmn2:outgoing>_217C7B88-D29D-479F-9DDA-49C505B55DB3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput
id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX" drools:dtype="Object"
itemSubjectRef="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputXItem"
name="TaskName"/>
+ <bpmn2:dataInput
id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX"
drools:dtype="Object"
itemSubjectRef="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputXItem"
name="Skippable"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:potentialOwner id="_FbR2ABn5ED6qPL2RHaehww">
+ <bpmn2:resourceAssignmentExpression id="_FbR2ARn5ED6qPL2RHaehww">
+ <bpmn2:formalExpression>jdoe</bpmn2:formalExpression>
+ </bpmn2:resourceAssignmentExpression>
+ </bpmn2:potentialOwner>
+ </bpmn2:userTask>
+ <bpmn2:startEvent id="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <bpmn2:outgoing>_BB186F29-4721-4C71-BFAA-D816C47ED670</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:boundaryEvent id="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
drools:dockerinfo="70.42^74|" drools:boundaryca="true" name="Boundary Timer"
attachedToRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Boundary Timer]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:outgoing>_2CCE6D96-07C9-4196-A3DA-2FA12675606B</bpmn2:outgoing>
+ <bpmn2:timerEventDefinition>
+ <bpmn2:timeDuration
xsi:type="bpmn2:tFormalExpression">PT180S</bpmn2:timeDuration>
+ </bpmn2:timerEventDefinition>
+ </bpmn2:boundaryEvent>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="timers">
+ <bpmndi:BPMNShape id="shape__F35EC805-22D5-4833-B56D-9DE16B4B258B"
bpmnElement="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <dc:Bounds height="56" width="56" x="325" y="97"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490"
bpmnElement="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <dc:Bounds height="102" width="154" x="448" y="74"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__66215F0B-D52C-4DEF-8BAE-3524FD59A246"
bpmnElement="_66215F0B-D52C-4DEF-8BAE-3524FD59A246">
+ <dc:Bounds height="56" width="56" x="682" y="97"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
bpmnElement="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3">
+ <dc:Bounds height="56" width="56" x="518.42" y="148"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__A2B595B9-3809-487E-B354-677DE3EB9B83"
bpmnElement="_A2B595B9-3809-487E-B354-677DE3EB9B83">
+ <dc:Bounds height="56" width="56" x="682" y="246"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge
id="edge_shape__F35EC805-22D5-4833-B56D-9DE16B4B258B_to_shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490"
bpmnElement="_BB186F29-4721-4C71-BFAA-D816C47ED670">
+ <di:waypoint x="353" y="125"/>
+ <di:waypoint x="525" y="125"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="edge_shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490_to_shape__66215F0B-D52C-4DEF-8BAE-3524FD59A246"
bpmnElement="_217C7B88-D29D-479F-9DDA-49C505B55DB3">
+ <di:waypoint x="525" y="125"/>
+ <di:waypoint x="710" y="125"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="edge_shape__C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3_to_shape__A2B595B9-3809-487E-B354-677DE3EB9B83"
bpmnElement="_2CCE6D96-07C9-4196-A3DA-2FA12675606B">
+ <di:waypoint x="546.42" y="176"/>
+ <di:waypoint x="546.42" y="274"/>
+ <di:waypoint x="682" y="274"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+ <bpmn2:relationship type="BPSimData">
+ <bpmn2:extensionElements>
+ <bpsim:BPSimData>
+ <bpsim:Scenario id="default" name="Simulationscenario">
+ <bpsim:ScenarioParameters/>
+ <bpsim:ElementParameters
elementRef="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <bpsim:TimeParameters>
+ <bpsim:ProcessingTime>
+ <bpsim:NormalDistribution mean="0" standardDeviation="0"/>
+ </bpsim:ProcessingTime>
+ </bpsim:TimeParameters>
+ </bpsim:ElementParameters>
+ <bpsim:ElementParameters
elementRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <bpsim:TimeParameters>
+ <bpsim:ProcessingTime>
+ <bpsim:NormalDistribution mean="0" standardDeviation="0"/>
+ </bpsim:ProcessingTime>
+ </bpsim:TimeParameters>
+ <bpsim:ResourceParameters>
+ <bpsim:Availability>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:Availability>
+ <bpsim:Quantity>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:Quantity>
+ </bpsim:ResourceParameters>
+ <bpsim:CostParameters>
+ <bpsim:UnitCost>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:UnitCost>
+ </bpsim:CostParameters>
+ </bpsim:ElementParameters>
+ </bpsim:Scenario>
+ </bpsim:BPSimData>
+ </bpmn2:extensionElements>
+ <bpmn2:source>_FbQn4Bn5ED6qPL2RHaehww</bpmn2:source>
+ <bpmn2:target>_FbQn4Bn5ED6qPL2RHaehww</bpmn2:target>
+ </bpmn2:relationship>
+</bpmn2:definitions>
\ No newline at end of file
diff --git
a/quarkus/addons/process-management/integration-tests/src/test/java/org/kie/kogito/quarkus/workflows/ProcessManagementIT.java
b/quarkus/addons/process-management/integration-tests/src/test/java/org/kie/kogito/quarkus/workflows/ProcessManagementIT.java
new file mode 100644
index 0000000000..9d83bbc17e
--- /dev/null
+++
b/quarkus/addons/process-management/integration-tests/src/test/java/org/kie/kogito/quarkus/workflows/ProcessManagementIT.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.kogito.quarkus.workflows;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+
+@QuarkusIntegrationTest
+public class ProcessManagementIT {
+
+ static {
+ RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
+ }
+
+ @Test
+ void testManagementTimersEndpoint() {
+ String processInstanceId = given()
+ .body(Map.of())
+ .contentType(ContentType.JSON)
+ .when()
+ .post("/timers")
+ .then()
+ .statusCode(201)
+ .body("id", notNullValue())
+ .extract().path("id");
+
+ String nodeInstanceId = given()
+ .when()
+
.get("/management/processes/timers/instances/{processInstanceId}/nodeInstances",
processInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(1))
+ .extract().path("[0].nodeInstanceId");
+
+ given()
+ .when()
+
.get("/management/processes/timers/instances/{processInstanceId}/timers",
processInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(4))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA-Process] timers"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[CANCEL-Process] timers"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA] Task"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "Task-Boundary Timer"))));
+
+ given()
+ .when()
+
.get("/management/processes/timers/instances/{processInstanceId}/nodeInstances/{nodeInstanceId}/timers",
processInstanceId, nodeInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(2))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA] Task"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "Task-Boundary Timer"))));
+ }
+}
diff --git
a/quarkus/addons/process-management/runtime/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementResource.java
b/quarkus/addons/process-management/runtime/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementResource.java
index c2b9bf1cc5..6bf8433f63 100644
---
a/quarkus/addons/process-management/runtime/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementResource.java
+++
b/quarkus/addons/process-management/runtime/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementResource.java
@@ -126,6 +126,14 @@ public class ProcessInstanceManagementResource extends
BaseProcessInstanceManage
return doGetWorkItemsInProcessInstance(processId, processInstanceId);
}
+ @Override
+ @GET
+ @Path("{processId}/instances/{processInstanceId}/timers")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getProcessInstanceTimers(@PathParam("processId") String
processId, @PathParam("processInstanceId") String processInstanceId) {
+ return doGetProcessInstanceTimers(processId, processInstanceId);
+ }
+
@Override
@POST
@Path("{processId}/instances/{processInstanceId}/retrigger")
@@ -166,6 +174,14 @@ public class ProcessInstanceManagementResource extends
BaseProcessInstanceManage
return doCancelNodeInstanceId(processId, processInstanceId,
nodeInstanceId);
}
+ @Override
+ @GET
+
@Path("{processId}/instances/{processInstanceId}/nodeInstances/{nodeInstanceId}/timers")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getNodeInstanceTimers(@PathParam("processId") String
processId, @PathParam("processInstanceId") String processInstanceId,
@PathParam("nodeInstanceId") String nodeInstanceId) {
+ return doGetNodeInstanceTimers(processId, processInstanceId,
nodeInstanceId);
+ }
+
@Override
@DELETE
@Path("{processId}/instances/{processInstanceId}")
diff --git
a/springboot/addons/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementRestController.java
b/springboot/addons/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementRestController.java
index 5f143aac29..eec6482af3 100644
---
a/springboot/addons/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementRestController.java
+++
b/springboot/addons/process-management/src/main/java/org/kie/kogito/process/management/ProcessInstanceManagementRestController.java
@@ -101,6 +101,12 @@ public class ProcessInstanceManagementRestController
extends BaseProcessInstance
return doGetWorkItemsInProcessInstance(processId, processInstanceId);
}
+ @Override
+ @GetMapping(value = "{processId}/instances/{processInstanceId}/timers",
produces = APPLICATION_JSON_VALUE)
+ public ResponseEntity getProcessInstanceTimers(@PathVariable("processId")
String processId, @PathVariable("processInstanceId") String processInstanceId) {
+ return doGetProcessInstanceTimers(processId, processInstanceId);
+ }
+
@Override
@PostMapping(value =
"{processId}/instances/{processInstanceId}/retrigger", produces =
APPLICATION_JSON_VALUE)
public ResponseEntity retriggerInstanceInError(@PathVariable("processId")
String processId, @PathVariable("processInstanceId") String processInstanceId) {
@@ -133,6 +139,13 @@ public class ProcessInstanceManagementRestController
extends BaseProcessInstance
return doCancelNodeInstanceId(processId, processInstanceId,
nodeInstanceId);
}
+ @Override
+ @GetMapping(value =
"{processId}/instances/{processInstanceId}/nodeInstances/{nodeInstanceId}/timers",
produces = APPLICATION_JSON_VALUE)
+ public ResponseEntity getNodeInstanceTimers(@PathVariable("processId")
String processId, @PathVariable("processInstanceId") String processInstanceId,
+ @PathVariable("nodeInstanceId") String nodeInstanceId) {
+ return doGetNodeInstanceTimers(processId, processInstanceId,
nodeInstanceId);
+ }
+
@Override
@DeleteMapping(value = "{processId}/instances/{processInstanceId}",
produces = APPLICATION_JSON_VALUE)
public ResponseEntity cancelProcessInstanceId(@PathVariable("processId")
String processId, @PathVariable("processInstanceId") String processInstanceId) {
diff --git
a/springboot/integration-tests/integration-tests-springboot-processes-it/src/main/resources/timers.bpmn
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/main/resources/timers.bpmn
new file mode 100644
index 0000000000..63b3bac089
--- /dev/null
+++
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/main/resources/timers.bpmn
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied. See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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: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="_FbQn4Bn5ED6qPL2RHaehww"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd
http://www. [...]
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_PriorityInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_CommentInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_DescriptionInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_CreatedByInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_GroupIdInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_ContentInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotStartedReassignInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotCompletedReassignInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotStartedNotifyInputXItem"
structureRef="Object"/>
+ <bpmn2:itemDefinition
id="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_NotCompletedNotifyInputXItem"
structureRef="Object"/>
+ <bpmn2:collaboration id="_11F36E9B-11DF-499D-896C-0D73277FBCB5"
name="Default Collaboration">
+ <bpmn2:participant id="_3CC3D518-96F1-4246-B77A-BD69EA62333A" name="Pool
Participant" processRef="timers"/>
+ </bpmn2:collaboration>
+ <bpmn2:process id="timers" drools:packageName="com.example"
drools:version="1.0" drools:adHoc="false" name="timers" isExecutable="true"
processType="Public">
+ <bpmn2:extensionElements>
+ <drools:metaData name="customSLADueDate">
+ <drools:metaValue><![CDATA[200m]]></drools:metaValue>
+ </drools:metaData>
+ <drools:metaData name="processDuration">
+ <drools:metaValue><![CDATA[PT1M]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:sequenceFlow id="_2CCE6D96-07C9-4196-A3DA-2FA12675606B"
sourceRef="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
targetRef="_A2B595B9-3809-487E-B354-677DE3EB9B83"/>
+ <bpmn2:sequenceFlow id="_217C7B88-D29D-479F-9DDA-49C505B55DB3"
sourceRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490"
targetRef="_66215F0B-D52C-4DEF-8BAE-3524FD59A246"/>
+ <bpmn2:sequenceFlow id="_BB186F29-4721-4C71-BFAA-D816C47ED670"
sourceRef="_F35EC805-22D5-4833-B56D-9DE16B4B258B"
targetRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490"/>
+ <bpmn2:endEvent id="_A2B595B9-3809-487E-B354-677DE3EB9B83">
+ <bpmn2:incoming>_2CCE6D96-07C9-4196-A3DA-2FA12675606B</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:endEvent id="_66215F0B-D52C-4DEF-8BAE-3524FD59A246">
+ <bpmn2:incoming>_217C7B88-D29D-479F-9DDA-49C505B55DB3</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:userTask id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490" name="Task">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Task]]></drools:metaValue>
+ </drools:metaData>
+ <drools:metaData name="customSLADueDate">
+ <drools:metaValue><![CDATA[150m]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_BB186F29-4721-4C71-BFAA-D816C47ED670</bpmn2:incoming>
+ <bpmn2:outgoing>_217C7B88-D29D-479F-9DDA-49C505B55DB3</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput
id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX" drools:dtype="Object"
itemSubjectRef="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputXItem"
name="TaskName"/>
+ <bpmn2:dataInput
id="_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX"
drools:dtype="Object"
itemSubjectRef="__CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputXItem"
name="Skippable"/>
+ <bpmn2:inputSet>
+
<bpmn2:dataInputRefs>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX</bpmn2:dataInputRefs>
+
<bpmn2:dataInputRefs>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_CB75879B-EB0D-4F28-AC61-E6FAA0126490_TaskNameInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+
<bpmn2:targetRef>_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from
xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
+ <bpmn2:to
xsi:type="bpmn2:tFormalExpression"><![CDATA[_CB75879B-EB0D-4F28-AC61-E6FAA0126490_SkippableInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:potentialOwner id="_FbR2ABn5ED6qPL2RHaehww">
+ <bpmn2:resourceAssignmentExpression id="_FbR2ARn5ED6qPL2RHaehww">
+ <bpmn2:formalExpression>jdoe</bpmn2:formalExpression>
+ </bpmn2:resourceAssignmentExpression>
+ </bpmn2:potentialOwner>
+ </bpmn2:userTask>
+ <bpmn2:startEvent id="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <bpmn2:outgoing>_BB186F29-4721-4C71-BFAA-D816C47ED670</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ <bpmn2:boundaryEvent id="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
drools:dockerinfo="70.42^74|" drools:boundaryca="true" name="Boundary Timer"
attachedToRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[Boundary Timer]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:outgoing>_2CCE6D96-07C9-4196-A3DA-2FA12675606B</bpmn2:outgoing>
+ <bpmn2:timerEventDefinition>
+ <bpmn2:timeDuration
xsi:type="bpmn2:tFormalExpression">PT180S</bpmn2:timeDuration>
+ </bpmn2:timerEventDefinition>
+ </bpmn2:boundaryEvent>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="timers">
+ <bpmndi:BPMNShape id="shape__F35EC805-22D5-4833-B56D-9DE16B4B258B"
bpmnElement="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <dc:Bounds height="56" width="56" x="325" y="97"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490"
bpmnElement="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <dc:Bounds height="102" width="154" x="448" y="74"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__66215F0B-D52C-4DEF-8BAE-3524FD59A246"
bpmnElement="_66215F0B-D52C-4DEF-8BAE-3524FD59A246">
+ <dc:Bounds height="56" width="56" x="682" y="97"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3"
bpmnElement="_C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3">
+ <dc:Bounds height="56" width="56" x="518.42" y="148"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__A2B595B9-3809-487E-B354-677DE3EB9B83"
bpmnElement="_A2B595B9-3809-487E-B354-677DE3EB9B83">
+ <dc:Bounds height="56" width="56" x="682" y="246"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge
id="edge_shape__F35EC805-22D5-4833-B56D-9DE16B4B258B_to_shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490"
bpmnElement="_BB186F29-4721-4C71-BFAA-D816C47ED670">
+ <di:waypoint x="353" y="125"/>
+ <di:waypoint x="525" y="125"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="edge_shape__CB75879B-EB0D-4F28-AC61-E6FAA0126490_to_shape__66215F0B-D52C-4DEF-8BAE-3524FD59A246"
bpmnElement="_217C7B88-D29D-479F-9DDA-49C505B55DB3">
+ <di:waypoint x="525" y="125"/>
+ <di:waypoint x="710" y="125"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge
id="edge_shape__C64FDE83-9AE3-4BC8-94AC-14805BE0D3D3_to_shape__A2B595B9-3809-487E-B354-677DE3EB9B83"
bpmnElement="_2CCE6D96-07C9-4196-A3DA-2FA12675606B">
+ <di:waypoint x="546.42" y="176"/>
+ <di:waypoint x="546.42" y="274"/>
+ <di:waypoint x="682" y="274"/>
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+ <bpmn2:relationship type="BPSimData">
+ <bpmn2:extensionElements>
+ <bpsim:BPSimData>
+ <bpsim:Scenario id="default" name="Simulationscenario">
+ <bpsim:ScenarioParameters/>
+ <bpsim:ElementParameters
elementRef="_F35EC805-22D5-4833-B56D-9DE16B4B258B">
+ <bpsim:TimeParameters>
+ <bpsim:ProcessingTime>
+ <bpsim:NormalDistribution mean="0" standardDeviation="0"/>
+ </bpsim:ProcessingTime>
+ </bpsim:TimeParameters>
+ </bpsim:ElementParameters>
+ <bpsim:ElementParameters
elementRef="_CB75879B-EB0D-4F28-AC61-E6FAA0126490">
+ <bpsim:TimeParameters>
+ <bpsim:ProcessingTime>
+ <bpsim:NormalDistribution mean="0" standardDeviation="0"/>
+ </bpsim:ProcessingTime>
+ </bpsim:TimeParameters>
+ <bpsim:ResourceParameters>
+ <bpsim:Availability>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:Availability>
+ <bpsim:Quantity>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:Quantity>
+ </bpsim:ResourceParameters>
+ <bpsim:CostParameters>
+ <bpsim:UnitCost>
+ <bpsim:FloatingParameter value="0"/>
+ </bpsim:UnitCost>
+ </bpsim:CostParameters>
+ </bpsim:ElementParameters>
+ </bpsim:Scenario>
+ </bpsim:BPSimData>
+ </bpmn2:extensionElements>
+ <bpmn2:source>_FbQn4Bn5ED6qPL2RHaehww</bpmn2:source>
+ <bpmn2:target>_FbQn4Bn5ED6qPL2RHaehww</bpmn2:target>
+ </bpmn2:relationship>
+</bpmn2:definitions>
\ No newline at end of file
diff --git
a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/ManagementAddOnTest.java
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/ManagementAddOnTest.java
index ac7b72f40d..d15ee2104c 100644
---
a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/ManagementAddOnTest.java
+++
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/ManagementAddOnTest.java
@@ -20,6 +20,7 @@ package org.kie.kogito.integrationtests.springboot;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -31,12 +32,13 @@ import io.restassured.http.ContentType;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.Matchers.emptyOrNullString;
-import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.*;
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = KogitoSpringbootApplication.class)
@@ -44,6 +46,7 @@ class ManagementAddOnTest extends BaseRestTest {
private static final String HELLO1_NODE =
"_3CDC6E61-DCC5-4831-8BBB-417CFF517CB0";
private static final String GREETINGS = "greetings";
+ private static final String TIMERS = "timers";
static {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
@@ -128,6 +131,75 @@ class ManagementAddOnTest extends BaseRestTest {
assertThat(newNodeInstanceIds).doesNotContainAnyElementsOf(nodeInstanceIds);
}
+ @Test
+ void testManagementTimersEndpoint() {
+ String processInstanceId = given()
+ .body(Map.of())
+ .contentType(ContentType.JSON)
+ .when()
+ .post("/timers")
+ .then()
+ .statusCode(201)
+ .body("id", notNullValue())
+ .extract().path("id");
+
+ String nodeInstanceId = given()
+ .when()
+
.get("/management/processes/{processId}/instances/{processInstanceId}/nodeInstances",
TIMERS, processInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(1))
+ .extract().path("[0].nodeInstanceId");
+
+ given()
+ .when()
+
.get("/management/processes/{processId}/instances/{processInstanceId}/timers",
TIMERS, processInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(4))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA-Process] timers"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[CANCEL-Process] timers"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA] Task"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "Task-Boundary Timer"))));
+
+ given()
+ .when()
+
.get("/management/processes/{processId}/instances/{processInstanceId}/nodeInstances/{nodeInstanceId}/timers",
TIMERS, processInstanceId, nodeInstanceId)
+ .then()
+ .statusCode(200)
+ .body("$.size()", equalTo(2))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "[SLA] Task"))))
+ .body("", hasItem(allOf(
+ hasEntry("processId", "timers"),
+ hasEntry("processInstanceId", processInstanceId),
+ hasEntry("nodeInstanceId", nodeInstanceId),
+ hasKey("timerId"),
+ hasEntry("description", "Task-Boundary Timer"))));
+ }
+
private String givenGreetingsProcess() {
return given().contentType(ContentType.JSON)
.when()
diff --git
a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/TaskTest.java
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/TaskTest.java
index 66821bd1c0..c11f1f9831 100644
---
a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/TaskTest.java
+++
b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/TaskTest.java
@@ -104,7 +104,7 @@ public class TaskTest extends BaseRestTest {
@Test
void testJsonSchemaFiles() {
- long expectedJsonSchemas = 25;
+ long expectedJsonSchemas = 27;
Path jsonDir = Paths.get("target",
"classes").resolve(JsonSchemaUtil.getJsonDir());
try (Stream<Path> paths = Files.walk(jsonDir)) {
long generatedJsonSchemas = paths
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]