You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by eg...@apache.org on 2024/10/07 18:04:08 UTC
(incubator-kie-kogito-runtimes) branch main updated: [incubator-kie-issues-1484] Create endpoints for user task (#3673)
This is an automated email from the ASF dual-hosted git repository.
egonzalez 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 ad419c82f8 [incubator-kie-issues-1484] Create endpoints for user task (#3673)
ad419c82f8 is described below
commit ad419c82f8f4b45d99faacbe620a777b48a6af26
Author: Enrique <en...@ibm.com>
AuthorDate: Mon Oct 7 20:04:03 2024 +0200
[incubator-kie-issues-1484] Create endpoints for user task (#3673)
---
.../workitem/KogitoWorkItemHandlerFactory.java | 2 +-
.../usertask/event/KogitoUserTaskEventSupport.java | 3 +-
.../kogito/process/workitem/TaskMetaEntity.java | 4 +
.../java/org/kie/kogito/usertask/UserTask.java | 2 +
...rTasks.java => UserTaskAssignmentStrategy.java} | 14 +-
....java => UserTaskAssignmentStrategyConfig.java} | 13 +-
.../org/kie/kogito/usertask/UserTaskConfig.java | 4 +
.../org/kie/kogito/usertask/UserTaskInstance.java | 43 +-
.../org/kie/kogito/usertask/UserTaskInstances.java | 13 +-
.../org/kie/kogito/usertask/UserTaskService.java | 64 +++
.../java/org/kie/kogito/usertask/UserTasks.java | 2 +
.../kogito/usertask/events/UserTaskStateEvent.java | 6 +-
.../usertask/lifecycle/UserTaskLifeCycle.java | 6 +-
.../kogito/usertask/lifecycle/UserTaskState.java | 7 +-
...Token.java => UserTaskTransitionException.java} | 9 +-
.../lifecycle/UserTaskTransitionExecutor.java | 3 +-
.../lifecycle/UserTaskTransitionToken.java | 6 +-
.../org/kie/kogito/usertask/model/Attachment.java | 4 +
.../org/kie/kogito/usertask/model/Comment.java | 3 +
.../{UserTasks.java => model/CommentInfo.java} | 21 +-
.../UserTaskTransitionView.java} | 37 +-
.../org/kie/kogito/usertask/view/UserTaskView.java | 178 ++++++++
.../event/impl/DefaultInstanceEventBatch.java | 2 +-
.../UserTaskStateEventDataEventAdapter.java | 4 +-
.../compiler/canonical/AbstractNodeVisitor.java | 3 +-
.../canonical/ProcessToExecModelGenerator.java | 17 +-
...delMetaData.java => WorkItemModelMetaData.java} | 45 +-
.../process/instance/LightWorkItemManager.java | 23 +-
.../instance/impl/WorkflowProcessInstanceImpl.java | 12 +
.../instance/node/WorkItemNodeInstance.java | 4 +-
.../process/impl/AbstractProcessInstance.java | 33 +-
.../handler/UserTaskKogitoWorkItemHandler.java | 186 ++------
...erTaskKogitoWorkItemHandlerProcessListener.java | 66 +++
...{DefaultUserTask.java => AbstractUserTask.java} | 61 +--
.../impl/BasicUserTaskAssignmentStrategy.java | 33 +-
.../kie/kogito/usertask/impl/DefaultUserTask.java | 265 +-----------
.../DefaultUserTaskAssignmentStrategyConfig.java | 54 +++
.../usertask/impl/DefaultUserTaskConfig.java | 30 +-
.../impl/DefaultUserTaskEventListenerConfig.java | 7 +-
.../usertask/impl/DefaultUserTaskInstance.java | 188 +++++---
.../kie/kogito/usertask/impl/DefaultUserTasks.java | 34 ++
.../usertask/impl/InMemoryUserTaskInstances.java | 79 +++-
.../impl/KogitoUserTaskEventSupportImpl.java | 3 +-
.../kogito/usertask/impl/UserTaskServiceImpl.java | 265 ++++++++++++
.../impl/events/UserTaskStateEventImpl.java | 17 +-
.../impl/lifecycle/DefaultUserTaskLifeCycle.java | 153 +++++--
.../lifecycle/DefaultUserTaskTransitionToken.java | 22 +-
.../impl/DefaultKogitoWorkItemHandler.java | 28 +-
.../kie/kogito/codegen/tests/PublishEventIT.java | 22 +-
.../org/kie/kogito/codegen/tests/UserTaskIT.java | 478 ++++++++++-----------
.../kie/kogito/codegen/process/ProcessCodegen.java | 27 +-
.../codegen/process/ProcessResourceGenerator.java | 44 +-
...rator.java => WorkItemModelClassGenerator.java} | 12 +-
.../kogito/codegen/usertask/UserTaskCodegen.java | 53 ++-
.../codegen/usertask/UserTaskConfigGenerator.java | 3 -
.../RestResourceUserTaskQuarkusTemplate.java | 266 ------------
.../RestResourceUserTaskSpringTemplate.java | 259 -----------
.../RestResourceWorkItemQuarkusTemplate.java | 139 ++++++
.../RestResourceWorkItemSpringTemplate.java | 137 ++++++
.../RestResourceUserTaskQuarkusTemplate.java | 248 +++++++++++
.../RestResourceUserTaskSpringTemplate.java | 210 +++++++++
.../usertask/UserTaskConfigQuarkusTemplate.java | 20 +-
.../usertask/UserTaskConfigSpringTemplate.java | 17 +-
.../usertask/UserTaskQuarkusTemplate.java | 16 +-
.../usertask/UserTaskSpringTemplate.java | 17 +-
.../UserTasksContainerQuarkusTemplate.java | 46 ++
.../usertask/UserTasksContainerSpringTemplate.java | 53 ++-
.../UserTasksServiceProducerQuarkusTemplate.java | 68 +++
.../UserTasksServiceProducerSpringTemplate.java | 67 +++
.../java/org/kie/kogito/it/PersistenceTest.java | 2 +-
.../src/main/resources/AddedTask.bpmn2 | 231 ++++++++++
.../org/kie/kogito/it/InfinispanPersistenceIT.java | 75 ++++
.../integrationtests/quarkus/AdHocFragmentsIT.java | 2 +-
.../kogito/integrationtests/quarkus/TaskIT.java | 97 ++---
.../springboot/AdHocFragmentsTest.java | 2 +-
.../integrationtests/springboot/TaskTest.java | 55 +--
.../java/org/kie/kogito/it/PersistenceTest.java | 27 +-
77 files changed, 3085 insertions(+), 1686 deletions(-)
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/workitem/KogitoWorkItemHandlerFactory.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/workitem/KogitoWorkItemHandlerFactory.java
index 0b9438bb8c..307bbb2eed 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/internal/process/workitem/KogitoWorkItemHandlerFactory.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/process/workitem/KogitoWorkItemHandlerFactory.java
@@ -26,7 +26,7 @@ public interface KogitoWorkItemHandlerFactory {
public static List<KogitoWorkItemHandler> findAllKogitoWorkItemHandlersRegistered() {
List<KogitoWorkItemHandler> handlers = new ArrayList<>();
- ServiceLoader.load(KogitoWorkItemHandlerFactory.class).stream()
+ ServiceLoader.load(KogitoWorkItemHandlerFactory.class, Thread.currentThread().getContextClassLoader()).stream()
.map(ServiceLoader.Provider<KogitoWorkItemHandlerFactory>::get)
.map(KogitoWorkItemHandlerFactory::provide)
.flatMap(List::stream)
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/internal/usertask/event/KogitoUserTaskEventSupport.java b/api/kogito-api/src/main/java/org/kie/kogito/internal/usertask/event/KogitoUserTaskEventSupport.java
index 4adc903a21..5ec63f2704 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/internal/usertask/event/KogitoUserTaskEventSupport.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/internal/usertask/event/KogitoUserTaskEventSupport.java
@@ -23,6 +23,7 @@ import java.util.Set;
import org.kie.kogito.usertask.UserTaskEventListener;
import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
import org.kie.kogito.usertask.model.Attachment;
import org.kie.kogito.usertask.model.Comment;
@@ -37,7 +38,7 @@ public interface KogitoUserTaskEventSupport {
void fireOneUserTaskStateChange(
UserTaskInstance instance,
- String oldPhaseStatus, String newPhaseStatus);
+ UserTaskState oldPhaseStatus, UserTaskState newPhaseStatus);
void fireOnUserTaskNotStartedDeadline(
UserTaskInstance instance,
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java
index 84f07f496a..49150a0af6 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/process/workitem/TaskMetaEntity.java
@@ -57,6 +57,10 @@ public class TaskMetaEntity<K extends Serializable, T extends Serializable> impl
return updatedBy;
}
+ public void setId(K id) {
+ this.id = id;
+ }
+
public K getId() {
return id;
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTask.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTask.java
index 8910256e68..11d762195a 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTask.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTask.java
@@ -109,4 +109,6 @@ public interface UserTask {
Collection<DeadlineInfo<Reassignment>> getNotCompletedReassigments();
+ UserTaskAssignmentStrategy getAssignmentStrategy();
+
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategy.java
similarity index 70%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
copy to api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategy.java
index 3d31047cad..985a5d2557 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategy.java
@@ -18,14 +18,18 @@
*/
package org.kie.kogito.usertask;
-import java.util.Collection;
+import java.util.Optional;
-import org.kie.kogito.KogitoEngine;
+import org.kie.kogito.auth.IdentityProvider;
-public interface UserTasks extends KogitoEngine {
+public interface UserTaskAssignmentStrategy {
- UserTask userTaskById(String userTaskId);
+ static final String DEFAULT_NAME = "default";
- Collection<String> userTaskIds();
+ default String getName() {
+ return getClass().getName();
+ }
+
+ Optional<String> computeAssigment(UserTaskInstance userTaskInstance, IdentityProvider identityProvider);
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategyConfig.java
similarity index 71%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
copy to api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategyConfig.java
index 3d31047cad..b9bc180a52 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskAssignmentStrategyConfig.java
@@ -18,14 +18,15 @@
*/
package org.kie.kogito.usertask;
-import java.util.Collection;
+import java.util.List;
-import org.kie.kogito.KogitoEngine;
+public interface UserTaskAssignmentStrategyConfig {
-public interface UserTasks extends KogitoEngine {
+ List<UserTaskAssignmentStrategy> userTaskAssignmentStrategies();
- UserTask userTaskById(String userTaskId);
-
- Collection<String> userTaskIds();
+ UserTaskAssignmentStrategy forName(String name);
+ default UserTaskAssignmentStrategy defaultUserTaskAssignmentStrategy() {
+ return forName(UserTaskAssignmentStrategy.DEFAULT_NAME);
+ }
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskConfig.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskConfig.java
index ee031f8418..2bebb31ef6 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskConfig.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskConfig.java
@@ -28,6 +28,8 @@ public interface UserTaskConfig extends KogitoConfig {
UserTaskEventListenerConfig userTaskEventListeners();
+ UserTaskAssignmentStrategyConfig userTaskAssignmentStrategies();
+
UserTaskLifeCycle userTaskLifeCycle();
UnitOfWorkManager unitOfWorkManager();
@@ -36,4 +38,6 @@ public interface UserTaskConfig extends KogitoConfig {
IdentityProvider identityProvider();
+ UserTaskInstances userTaskInstances();
+
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java
index 9e73f14624..4a0023a0c4 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstance.java
@@ -22,8 +22,8 @@ import java.util.Collection;
import java.util.Map;
import java.util.Set;
+import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.usertask.lifecycle.UserTaskState;
-import org.kie.kogito.usertask.lifecycle.UserTaskTransitionToken;
import org.kie.kogito.usertask.model.Attachment;
import org.kie.kogito.usertask.model.Comment;
@@ -35,19 +35,15 @@ public interface UserTaskInstance {
UserTaskState getStatus();
+ String getUserTaskId();
+
boolean hasActualOwner();
- void setActuaOwner(String string);
+ void setActuaOwner(String actualOwner);
String getActualOwner();
- UserTaskTransitionToken createTransitionToken(String transitionId, Map<String, Object> data);
-
- void transition(UserTaskTransitionToken token);
-
- void complete();
-
- void abort();
+ void transition(String transitionId, Map<String, Object> data, IdentityProvider identityProvider);
String getExternalReferenceId();
@@ -59,6 +55,14 @@ public interface UserTaskInstance {
Map<String, Object> getMetadata();
+ Map<String, Object> getOutputs();
+
+ Map<String, Object> getInputs();
+
+ void setInput(String key, Object value);
+
+ void setOutput(String key, Object value);
+
/**
* Returns potential users that can work on this task
*
@@ -94,23 +98,24 @@ public interface UserTaskInstance {
*/
Set<String> getExcludedUsers();
- void addAttachment(Attachment attachment);
+ Attachment findAttachmentById(String attachmentId);
- void updateAttachment(Attachment newAttachment);
+ Attachment addAttachment(Attachment attachment);
- void removeAttachment(Attachment oldAttachment);
+ Attachment updateAttachment(Attachment newAttachment);
- void addComment(Comment comment);
+ Attachment removeAttachment(Attachment oldAttachment);
- void updateComment(Comment newComment);
+ Collection<Attachment> getAttachments();
- void removeComment(Comment comment);
+ Comment findCommentById(String commentId);
- Collection<Comment> getComments();
+ Comment addComment(Comment comment);
- Collection<Attachment> getAttachments();
+ Comment updateComment(Comment newComment);
- Attachment findAttachmentById(String attachmentId);
+ Comment removeComment(Comment comment);
+
+ Collection<Comment> getComments();
- Comment findCommentById(String commentId);
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java
index 57e956bd87..7f294b15fe 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskInstances.java
@@ -18,11 +18,20 @@
*/
package org.kie.kogito.usertask;
+import java.util.List;
import java.util.Optional;
import java.util.function.Function;
+import org.kie.kogito.auth.IdentityProvider;
+
public interface UserTaskInstances {
+ void setReconnectUserTaskInstance(Function<UserTaskInstance, UserTaskInstance> reconnectUserTaskInstance);
+
+ void setDisconnectUserTaskInstance(Function<UserTaskInstance, UserTaskInstance> disconnectUserTaskInstance);
+
+ List<UserTaskInstance> findByIdentity(IdentityProvider identityProvider);
+
Optional<UserTaskInstance> findById(String userTaskInstanceId);
boolean exists(String userTaskInstanceId);
@@ -33,8 +42,4 @@ public interface UserTaskInstances {
UserTaskInstance remove(String userTaskInstanceId);
- void setReconnectUserTaskInstance(Function<UserTaskInstance, UserTaskInstance> reconnectUserTaskInstance);
-
- void setDisconnectUserTaskInstance(Function<UserTaskInstance, UserTaskInstance> disconnectUserTaskInstance);
-
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskService.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskService.java
new file mode 100644
index 0000000000..70cfdfbdc2
--- /dev/null
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTaskService.java
@@ -0,0 +1,64 @@
+/*
+ * 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.usertask;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.usertask.model.Attachment;
+import org.kie.kogito.usertask.model.Comment;
+import org.kie.kogito.usertask.view.UserTaskTransitionView;
+import org.kie.kogito.usertask.view.UserTaskView;
+
+public interface UserTaskService {
+
+ Optional<UserTaskView> getUserTaskInstance(String taskId, IdentityProvider identity);
+
+ List<UserTaskView> list(IdentityProvider identity);
+
+ Optional<UserTaskView> transition(String taskId, String transitionId, Map<String, Object> data, IdentityProvider identity);
+
+ List<UserTaskTransitionView> allowedTransitions(String taskId, IdentityProvider identity);
+
+ Optional<UserTaskView> setOutputs(String taskId, Map<String, Object> data, IdentityProvider identity);
+
+ Optional<UserTaskView> setInputs(String taskId, Map<String, Object> data, IdentityProvider identity);
+
+ List<Comment> getComments(String taskId, IdentityProvider identity);
+
+ Optional<Comment> getComment(String taskId, String commentId, IdentityProvider identity);
+
+ Optional<Comment> addComment(String taskId, Comment comment, IdentityProvider identity);
+
+ Optional<Comment> updateComment(String taskId, Comment comment, IdentityProvider identity);
+
+ Optional<Comment> removeComment(String taskId, String commentId, IdentityProvider identity);
+
+ List<Attachment> getAttachments(String taskId, IdentityProvider identity);
+
+ Optional<Attachment> getAttachment(String taskId, String commentId, IdentityProvider identity);
+
+ Optional<Attachment> addAttachment(String taskId, Attachment comment, IdentityProvider identity);
+
+ Optional<Attachment> updateAttachment(String taskId, Attachment comment, IdentityProvider identity);
+
+ Optional<Attachment> removeAttachment(String taskId, String commentId, IdentityProvider identity);
+}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
index 3d31047cad..0253644c0f 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
@@ -24,6 +24,8 @@ import org.kie.kogito.KogitoEngine;
public interface UserTasks extends KogitoEngine {
+ UserTaskInstances instances();
+
UserTask userTaskById(String userTaskId);
Collection<String> userTaskIds();
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/events/UserTaskStateEvent.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/events/UserTaskStateEvent.java
index 196b76aafb..e5471cc96f 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/events/UserTaskStateEvent.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/events/UserTaskStateEvent.java
@@ -19,10 +19,12 @@
package org.kie.kogito.usertask.events;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
+
public interface UserTaskStateEvent extends UserTaskEvent {
- String getNewStatus();
+ UserTaskState getNewStatus();
- String getOldStatus();
+ UserTaskState getOldStatus();
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java
index eb8290884a..09170f4d1c 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java
@@ -19,14 +19,16 @@
package org.kie.kogito.usertask.lifecycle;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.usertask.UserTaskInstance;
public interface UserTaskLifeCycle {
- Optional<UserTaskTransitionToken> transition(UserTaskInstance userTaskInstance, UserTaskTransitionToken transition);
+ Optional<UserTaskTransitionToken> transition(UserTaskInstance userTaskInstance, UserTaskTransitionToken transition, IdentityProvider identity);
UserTaskTransitionToken newTransitionToken(String transitionId, UserTaskInstance userTaskInstance, Map<String, Object> data);
@@ -34,4 +36,6 @@ public interface UserTaskLifeCycle {
UserTaskTransitionToken newAbortTransitionToken(UserTaskInstance userTaskInstance, Map<String, Object> emptyMap);
+ List<UserTaskTransition> allowedTransitions(UserTaskInstance ut);
+
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskState.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskState.java
index 71ba89b94d..63a3242ede 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskState.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskState.java
@@ -19,7 +19,6 @@
package org.kie.kogito.usertask.lifecycle;
import java.util.Objects;
-import java.util.Optional;
public class UserTaskState {
@@ -69,8 +68,8 @@ public class UserTaskState {
return name;
}
- public Optional<TerminationType> isTerminate() {
- return Optional.ofNullable(terminate);
+ public boolean isTerminate() {
+ return terminate != null;
}
@Override
@@ -91,7 +90,7 @@ public class UserTaskState {
}
public static UserTaskState initalized() {
- return of(null);
+ return of("Created");
}
@Override
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionException.java
similarity index 79%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java
copy to api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionException.java
index db1dd9e8d7..3e98d19bdc 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionException.java
@@ -18,11 +18,12 @@
*/
package org.kie.kogito.usertask.lifecycle;
-import java.util.Map;
+public class UserTaskTransitionException extends RuntimeException {
-public interface UserTaskTransitionToken {
+ private static final long serialVersionUID = -9127576077607542859L;
- UserTaskTransition transition();
+ public UserTaskTransitionException(String msg) {
+ super(msg);
+ }
- Map<String, Object> data();
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionExecutor.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionExecutor.java
index 6124901d28..79eb36a5a0 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionExecutor.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionExecutor.java
@@ -20,10 +20,11 @@ package org.kie.kogito.usertask.lifecycle;
import java.util.Optional;
+import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.usertask.UserTaskInstance;
public interface UserTaskTransitionExecutor {
- Optional<UserTaskTransitionToken> execute(UserTaskInstance transition, UserTaskTransitionToken token);
+ Optional<UserTaskTransitionToken> execute(UserTaskInstance transition, UserTaskTransitionToken token, IdentityProvider identity);
}
\ No newline at end of file
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java
index db1dd9e8d7..8277f4d6d5 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskTransitionToken.java
@@ -22,7 +22,11 @@ import java.util.Map;
public interface UserTaskTransitionToken {
- UserTaskTransition transition();
+ String transitionId();
+
+ UserTaskState source();
+
+ UserTaskState target();
Map<String, Object> data();
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java
index 04ff75b130..d032eca9ea 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java
@@ -27,6 +27,10 @@ public class Attachment extends TaskMetaEntity<String, URI> {
private static final long serialVersionUID = 1L;
private String name;
+ public Attachment() {
+
+ }
+
public Attachment(String id, String user) {
super(id, user);
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Comment.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Comment.java
index 74a801b711..fe2a3fdf45 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Comment.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Comment.java
@@ -24,6 +24,9 @@ public class Comment extends TaskMetaEntity<String, String> {
private static final long serialVersionUID = -9106249675352498780L;
+ public Comment() {
+ }
+
public Comment(String id, String user) {
super(id, user);
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/CommentInfo.java
similarity index 69%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
copy to api/kogito-api/src/main/java/org/kie/kogito/usertask/model/CommentInfo.java
index 3d31047cad..5cbfd1404b 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/UserTasks.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/CommentInfo.java
@@ -16,16 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.kie.kogito.usertask;
+package org.kie.kogito.usertask.model;
-import java.util.Collection;
+public class CommentInfo {
-import org.kie.kogito.KogitoEngine;
+ private String comment;
-public interface UserTasks extends KogitoEngine {
+ public CommentInfo() {
- UserTask userTaskById(String userTaskId);
+ }
- Collection<String> userTaskIds();
+ public CommentInfo(String comment) {
+ this.comment = comment;
+ }
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskTransitionView.java
similarity index 54%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java
copy to api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskTransitionView.java
index 04ff75b130..3f22f091e7 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/model/Attachment.java
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskTransitionView.java
@@ -16,31 +16,38 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.kie.kogito.usertask.model;
+package org.kie.kogito.usertask.view;
-import java.net.URI;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
-import org.kie.kogito.process.workitem.TaskMetaEntity;
+public class UserTaskTransitionView {
-public class Attachment extends TaskMetaEntity<String, URI> {
+ private String transitionId;
+ private UserTaskState source;
+ private UserTaskState target;
- private static final long serialVersionUID = 1L;
- private String name;
+ public String getTransitionId() {
+ return transitionId;
+ }
+
+ public void setTransitionId(String transitionId) {
+ this.transitionId = transitionId;
+ }
- public Attachment(String id, String user) {
- super(id, user);
+ public UserTaskState getSource() {
+ return source;
}
- public String getName() {
- return name;
+ public void setSource(UserTaskState source) {
+ this.source = source;
}
- public void setName(String name) {
- this.name = name;
+ public UserTaskState getTarget() {
+ return target;
}
- @Override
- public Attachment clone() throws CloneNotSupportedException {
- return (Attachment) super.clone();
+ public void setTarget(UserTaskState target) {
+ this.target = target;
}
+
}
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskView.java b/api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskView.java
new file mode 100644
index 0000000000..660ea4c844
--- /dev/null
+++ b/api/kogito-api/src/main/java/org/kie/kogito/usertask/view/UserTaskView.java
@@ -0,0 +1,178 @@
+/*
+ * 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.usertask.view;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
+
+public class UserTaskView {
+
+ private String id;
+
+ private String userTaskId;
+
+ private UserTaskState status;
+
+ private String taskName;
+ private String taskDescription;
+ private Integer taskPriority;
+ private Set<String> potentialUsers;
+ private Set<String> potentialGroups;
+ private Set<String> adminUsers;
+ private Set<String> adminGroups;
+ private Set<String> excludedUsers;
+ private String externalReferenceId;
+ private String actualOwner;
+
+ private Map<String, Object> inputs;
+ private Map<String, Object> outputs;
+
+ private Map<String, Object> metadata;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUserTaskId() {
+ return userTaskId;
+ }
+
+ public void setUserTaskId(String userTaskId) {
+ this.userTaskId = userTaskId;
+ }
+
+ public UserTaskState getStatus() {
+ return status;
+ }
+
+ public void setStatus(UserTaskState status) {
+ this.status = status;
+ }
+
+ public String getTaskName() {
+ return taskName;
+ }
+
+ public void setTaskName(String taskName) {
+ this.taskName = taskName;
+ }
+
+ public String getTaskDescription() {
+ return taskDescription;
+ }
+
+ public void setTaskDescription(String taskDescription) {
+ this.taskDescription = taskDescription;
+ }
+
+ public Integer getTaskPriority() {
+ return taskPriority;
+ }
+
+ public void setTaskPriority(Integer taskPriority) {
+ this.taskPriority = taskPriority;
+ }
+
+ public Set<String> getPotentialUsers() {
+ return potentialUsers;
+ }
+
+ public void setPotentialUsers(Set<String> potentialUsers) {
+ this.potentialUsers = potentialUsers;
+ }
+
+ public Set<String> getPotentialGroups() {
+ return potentialGroups;
+ }
+
+ public void setPotentialGroups(Set<String> potentialGroups) {
+ this.potentialGroups = potentialGroups;
+ }
+
+ public Set<String> getAdminUsers() {
+ return adminUsers;
+ }
+
+ public void setAdminUsers(Set<String> adminUsers) {
+ this.adminUsers = adminUsers;
+ }
+
+ public Set<String> getAdminGroups() {
+ return adminGroups;
+ }
+
+ public void setAdminGroups(Set<String> adminGroups) {
+ this.adminGroups = adminGroups;
+ }
+
+ public Set<String> getExcludedUsers() {
+ return excludedUsers;
+ }
+
+ public void setExcludedUsers(Set<String> excludedUsers) {
+ this.excludedUsers = excludedUsers;
+ }
+
+ public String getExternalReferenceId() {
+ return externalReferenceId;
+ }
+
+ public void setExternalReferenceId(String externalReferenceId) {
+ this.externalReferenceId = externalReferenceId;
+ }
+
+ public String getActualOwner() {
+ return actualOwner;
+ }
+
+ public void setActualOwner(String actualOwner) {
+ this.actualOwner = actualOwner;
+ }
+
+ public Map<String, Object> getInputs() {
+ return inputs;
+ }
+
+ public void setInputs(Map<String, Object> inputs) {
+ this.inputs = inputs;
+ }
+
+ public Map<String, Object> getOutputs() {
+ return outputs;
+ }
+
+ public void setOutputs(Map<String, Object> outputs) {
+ this.outputs = outputs;
+ }
+
+ public Map<String, Object> getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Map<String, Object> metadata) {
+ this.metadata = metadata;
+ }
+
+}
diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/DefaultInstanceEventBatch.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/DefaultInstanceEventBatch.java
index c4f6cd76b2..df94b1183a 100644
--- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/DefaultInstanceEventBatch.java
+++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/DefaultInstanceEventBatch.java
@@ -68,7 +68,7 @@ public class DefaultInstanceEventBatch implements EventBatch {
@Override
public void append(Object event) {
- LOG.info("event generated {}", event);
+ LOG.trace("event generated {}", event);
this.dataEventAdapters.stream().filter(a -> a.accept(event)).map(a -> a.adapt(event)).forEach(this.processedEvents::add);
}
diff --git a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/adapter/UserTaskStateEventDataEventAdapter.java b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/adapter/UserTaskStateEventDataEventAdapter.java
index fe577ac0c2..af70b37ae3 100644
--- a/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/adapter/UserTaskStateEventDataEventAdapter.java
+++ b/api/kogito-events-core/src/main/java/org/kie/kogito/event/impl/adapter/UserTaskStateEventDataEventAdapter.java
@@ -54,9 +54,9 @@ public class UserTaskStateEventDataEventAdapter extends AbstractDataEventAdapter
.userTaskDescription(event.getUserTaskInstance().getTaskDescription())
.userTaskPriority(priorityStr)
.userTaskReferenceName(event.getUserTask().getReferenceName())
- .state(event.getNewStatus())
+ .state(event.getNewStatus().getName())
.actualOwner(event.getUserTaskInstance().getActualOwner())
- .eventType(isTransition(event) ? event.getNewStatus() : "Modify")
+ .eventType(isTransition(event) ? event.getNewStatus().getName() : "Modify")
.processInstanceId((String) event.getUserTaskInstance().getMetadata().get("ProcessInstanceId"));
UserTaskInstanceStateEventBody body = builder.build();
diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/AbstractNodeVisitor.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/AbstractNodeVisitor.java
index a8ce5a76b8..1946318d05 100644
--- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/AbstractNodeVisitor.java
+++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/AbstractNodeVisitor.java
@@ -53,7 +53,6 @@ import org.jbpm.workflow.core.impl.DroolsConsequenceAction;
import org.jbpm.workflow.core.impl.ExtendedNodeImpl;
import org.jbpm.workflow.core.impl.NodeImpl;
import org.jbpm.workflow.core.node.Assignment;
-import org.jbpm.workflow.core.node.HumanTaskNode;
import org.jbpm.workflow.core.node.StartNode;
import org.jbpm.workflow.core.node.Transformation;
import org.kie.api.definition.process.Connection;
@@ -117,7 +116,7 @@ public abstract class AbstractNodeVisitor<T extends Node> extends AbstractVisito
public void visitNode(T node, BlockStmt body, VariableScope variableScope, ProcessMetaData metadata) {
visitNode(FACTORY_FIELD_NAME, node, body, variableScope, metadata);
- if (isAdHocNode(node) && !(node instanceof HumanTaskNode)) {
+ if (isAdHocNode(node)) {
metadata.addSignal(node.getName(), null);
}
if (isExtendedNode(node)) {
diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessToExecModelGenerator.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessToExecModelGenerator.java
index 253d24a7f0..678c465733 100644
--- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessToExecModelGenerator.java
+++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/ProcessToExecModelGenerator.java
@@ -29,7 +29,7 @@ import org.jbpm.process.core.ContextContainer;
import org.jbpm.process.core.context.variable.Variable;
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.workflow.core.impl.WorkflowProcessImpl;
-import org.jbpm.workflow.core.node.HumanTaskNode;
+import org.jbpm.workflow.core.node.WorkItemNode;
import org.kie.api.definition.process.Node;
import org.kie.api.definition.process.WorkflowProcess;
import org.kie.kogito.ProcessInput;
@@ -243,27 +243,26 @@ public class ProcessToExecModelGenerator {
return sanitizeClassName(extractProcessId(processId) + MODEL_CLASS_SUFFIX);
}
- public List<UserTaskModelMetaData> generateUserTaskModel(WorkflowProcess process) {
+ public List<WorkItemModelMetaData> generateWorkItemModel(WorkflowProcess process) {
String packageName = process.getPackageName();
- List<UserTaskModelMetaData> userTaskModels = new ArrayList<>();
+ List<WorkItemModelMetaData> workItemTaskModels = new ArrayList<>();
VariableScope variableScope = (VariableScope) ((org.jbpm.process.core.Process) process).getDefaultContext(
VariableScope.VARIABLE_SCOPE);
for (Node node : ((WorkflowProcessImpl) process).getNodesRecursively()) {
- if (node instanceof HumanTaskNode) {
- HumanTaskNode humanTaskNode = (HumanTaskNode) node;
- VariableScope nodeVariableScope = (VariableScope) ((ContextContainer) humanTaskNode
+ if (node instanceof WorkItemNode workItemNode) {
+ VariableScope nodeVariableScope = (VariableScope) ((ContextContainer) workItemNode
.getParentContainer()).getDefaultContext(VariableScope.VARIABLE_SCOPE);
if (nodeVariableScope == null) {
nodeVariableScope = variableScope;
}
- userTaskModels.add(new UserTaskModelMetaData(packageName, variableScope, nodeVariableScope,
- humanTaskNode, process.getId()));
+ workItemTaskModels.add(new WorkItemModelMetaData(packageName, variableScope, nodeVariableScope,
+ workItemNode, process.getId()));
}
}
- return userTaskModels;
+ return workItemTaskModels;
}
public static String extractProcessId(String processId) {
diff --git a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/UserTaskModelMetaData.java b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemModelMetaData.java
similarity index 90%
rename from jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/UserTaskModelMetaData.java
rename to jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemModelMetaData.java
index 3d648ad2e2..5ae7418790 100644
--- a/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/UserTaskModelMetaData.java
+++ b/jbpm/jbpm-flow-builder/src/main/java/org/jbpm/compiler/canonical/WorkItemModelMetaData.java
@@ -30,7 +30,7 @@ import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.core.datatype.DataType;
import org.jbpm.process.core.datatype.DataTypeResolver;
import org.jbpm.util.PatternConstants;
-import org.jbpm.workflow.core.node.HumanTaskNode;
+import org.jbpm.workflow.core.node.WorkItemNode;
import org.kie.api.definition.process.WorkflowElementIdentifier;
import org.kie.kogito.UserTask;
import org.kie.kogito.UserTaskParam;
@@ -70,7 +70,7 @@ import static com.github.javaparser.StaticJavaParser.parseClassOrInterfaceType;
import static org.jbpm.ruleflow.core.Metadata.CUSTOM_AUTO_START;
import static org.kie.kogito.internal.utils.ConversionUtils.sanitizeClassName;
-public class UserTaskModelMetaData {
+public class WorkItemModelMetaData {
private static final String TASK_INTPUT_CLASS_SUFFIX = "TaskInput";
private static final String TASK_OUTTPUT_CLASS_SUFFIX = "TaskOutput";
@@ -86,7 +86,7 @@ public class UserTaskModelMetaData {
private final VariableScope processVariableScope;
private final VariableScope variableScope;
- private final HumanTaskNode humanTaskNode;
+ private final WorkItemNode workItemNode;
private final String processId;
private String inputModelClassName;
@@ -98,20 +98,20 @@ public class UserTaskModelMetaData {
private String taskModelClassName;
private String taskModelClassSimpleName;
- public UserTaskModelMetaData(String packageName, VariableScope processVariableScope, VariableScope variableScope, HumanTaskNode humanTaskNode, String processId) {
+ public WorkItemModelMetaData(String packageName, VariableScope processVariableScope, VariableScope variableScope, WorkItemNode workItemNode, String processId) {
this.packageName = packageName;
this.processVariableScope = processVariableScope;
this.variableScope = variableScope;
- this.humanTaskNode = humanTaskNode;
+ this.workItemNode = workItemNode;
this.processId = processId;
- this.inputModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + humanTaskNode.getId().toExternalFormat() + "_" + TASK_INTPUT_CLASS_SUFFIX);
+ this.inputModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + workItemNode.getId().toExternalFormat() + "_" + TASK_INTPUT_CLASS_SUFFIX);
this.inputModelClassName = packageName + '.' + inputModelClassSimpleName;
- this.outputModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + humanTaskNode.getId().toExternalFormat() + "_" + TASK_OUTTPUT_CLASS_SUFFIX);
+ this.outputModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + workItemNode.getId().toExternalFormat() + "_" + TASK_OUTTPUT_CLASS_SUFFIX);
this.outputModelClassName = packageName + '.' + outputModelClassSimpleName;
- this.taskModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + humanTaskNode.getId().toExternalFormat() + "_" + TASK_MODEL_CLASS_SUFFIX);
+ this.taskModelClassSimpleName = sanitizeClassName(ProcessToExecModelGenerator.extractProcessId(processId) + "_" + workItemNode.getId().toExternalFormat() + "_" + TASK_MODEL_CLASS_SUFFIX);
this.taskModelClassName = packageName + '.' + taskModelClassSimpleName;
}
@@ -144,21 +144,21 @@ public class UserTaskModelMetaData {
}
public String getName() {
- return (String) humanTaskNode.getWork().getParameters().getOrDefault(TASK_NAME, humanTaskNode.getName());
+ return (String) workItemNode.getWork().getParameters().getOrDefault(TASK_NAME, workItemNode.getName());
}
public String getNodeName() {
- return humanTaskNode.getName();
+ return workItemNode.getName();
}
public WorkflowElementIdentifier getId() {
- return humanTaskNode.getId();
+ return workItemNode.getId();
}
private void addUserTaskAnnotation(ClassOrInterfaceDeclaration modelClass) {
- String taskName = (String) humanTaskNode.getWork().getParameter(TASK_NAME);
+ String taskName = (String) workItemNode.getWork().getParameter(TASK_NAME);
if (taskName == null)
- taskName = humanTaskNode.getName();
+ taskName = workItemNode.getName();
modelClass.addAndGetAnnotation(UserTask.class).addPair("taskName", new StringLiteralExpr(taskName)).addPair("processName", new StringLiteralExpr(processId));
}
@@ -190,8 +190,8 @@ public class UserTaskModelMetaData {
NameExpr item = new NameExpr("item");
// map is task input -> context variable / process variable
- Map<String, String> inputTypes = humanTaskNode.getIoSpecification().getInputTypes();
- for (Entry<String, String> entry : humanTaskNode.getIoSpecification().getInputMapping().entrySet()) {
+ Map<String, String> inputTypes = workItemNode.getIoSpecification().getInputTypes();
+ for (Entry<String, String> entry : workItemNode.getIoSpecification().getInputMapping().entrySet()) {
if (INTERNAL_FIELDS.contains(entry.getKey())) {
continue;
}
@@ -235,7 +235,7 @@ public class UserTaskModelMetaData {
AssignExpr.Operator.ASSIGN));
}
- for (Entry<String, Object> entry : humanTaskNode.getWork().getParameters().entrySet()) {
+ for (Entry<String, Object> entry : workItemNode.getWork().getParameters().entrySet()) {
if (entry.getValue() == null || INTERNAL_FIELDS.contains(entry.getKey())) {
continue;
@@ -275,7 +275,6 @@ public class UserTaskModelMetaData {
return compilationUnit;
}
- @SuppressWarnings({ "unchecked" })
private CompilationUnit compilationUnitOutput() {
CompilationUnit compilationUnit = parse(this.getClass().getResourceAsStream("/class-templates/TaskOutputTemplate.java"));
compilationUnit.setPackageDeclaration(packageName);
@@ -303,8 +302,8 @@ public class UserTaskModelMetaData {
HashMap.class.getSimpleName() + "<>"), NodeList.nodeList()), AssignExpr.Operator.ASSIGN));
// map is task output -> context variable / process variable
- Map<String, String> outputTypes = humanTaskNode.getIoSpecification().getOutputTypes();
- for (Entry<String, String> entry : humanTaskNode.getIoSpecification().getOutputMappingBySources().entrySet()) {
+ Map<String, String> outputTypes = workItemNode.getIoSpecification().getOutputTypes();
+ for (Entry<String, String> entry : workItemNode.getIoSpecification().getOutputMappingBySources().entrySet()) {
if (entry.getValue() == null || INTERNAL_FIELDS.contains(entry.getKey())) {
continue;
}
@@ -382,7 +381,7 @@ public class UserTaskModelMetaData {
}
private void addComment(CompilationUnit unit, String prefix) {
- unit.addOrphanComment(new LineComment(prefix + " for user task '" + humanTaskNode.getName() + "' in process '" + processId + "'"));
+ unit.addOrphanComment(new LineComment(prefix + " for user task '" + workItemNode.getName() + "' in process '" + processId + "'"));
}
private void templateReplacement(NameExpr name) {
@@ -407,13 +406,13 @@ public class UserTaskModelMetaData {
}
public boolean isAdHoc() {
- return !Boolean.parseBoolean((String) humanTaskNode.getMetaData(CUSTOM_AUTO_START))
- && (humanTaskNode.getIncomingConnections() == null || humanTaskNode.getIncomingConnections().isEmpty());
+ return !Boolean.parseBoolean((String) workItemNode.getMetaData(CUSTOM_AUTO_START))
+ && (workItemNode.getIncomingConnections() == null || workItemNode.getIncomingConnections().isEmpty());
}
public SwitchEntry getModelSwitchEntry() {
SwitchEntry entry = new SwitchEntry();
- entry.setLabels(NodeList.nodeList(new StringLiteralExpr(humanTaskNode.getId().toExternalFormat())));
+ entry.setLabels(NodeList.nodeList(new StringLiteralExpr(workItemNode.getId().toExternalFormat())));
entry.addStatement(new ReturnStmt(new MethodCallExpr(new NameExpr(
taskModelClassSimpleName), new SimpleName("from")).addArgument(WORK_ITEM)));
return entry;
diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java
index 16a1519fe4..01b2410465 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/process/instance/LightWorkItemManager.java
@@ -74,8 +74,12 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
}
@Override
- public InternalKogitoWorkItem getWorkItem(String id) {
- return workItems.get(id);
+ public InternalKogitoWorkItem getWorkItem(String workItemId) {
+ InternalKogitoWorkItem workItem = workItems.get(workItemId);
+ if (workItem == null) {
+ throw new WorkItemNotFoundException("Work Item (" + workItemId + ") does not exist", workItemId);
+ }
+ return workItem;
}
@Override
@@ -131,7 +135,6 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
KogitoWorkItemHandler handler = getWorkItemHandler(workItem);
WorkItemTransition transition = handler.startingTransition(Collections.emptyMap());
transitionWorkItem(workItem, transition, true);
-
}
@Override
@@ -143,7 +146,6 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
KogitoProcessInstance processInstance = processInstanceManager.getProcessInstance(workItem.getProcessInstanceStringId());
workItem.setState(KogitoWorkItem.COMPLETED);
processInstance.signalEvent("workItemCompleted", workItem);
-
}
@Override
@@ -160,10 +162,7 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
@Override
public <T> T updateWorkItem(String workItemId, Function<KogitoWorkItem, T> updater, Policy... policies) {
- InternalKogitoWorkItem workItem = workItems.get(workItemId);
- if (workItem == null) {
- throw new WorkItemNotFoundException(workItemId);
- }
+ InternalKogitoWorkItem workItem = getWorkItem(workItemId);
Stream.of(policies).forEach(p -> p.enforce(workItem));
T results = updater.apply(workItem);
return results;
@@ -178,10 +177,7 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
@Override
public void transitionWorkItem(String workItemId, WorkItemTransition transition) {
- InternalKogitoWorkItem workItem = workItems.get(workItemId);
- if (workItem == null) {
- throw new WorkItemNotFoundException("Work Item (" + workItemId + ") does not exist", workItemId);
- }
+ InternalKogitoWorkItem workItem = getWorkItem(workItemId);
transitionWorkItem(workItem, transition, true);
}
@@ -209,7 +205,7 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
}
if (lastTransition.termination().isPresent()) {
- internalRemoveWorkItem(workItem.getStringId());
+
if (signal) {
switch (lastTransition.termination().get()) {
case COMPLETE:
@@ -222,6 +218,7 @@ public class LightWorkItemManager implements InternalKogitoWorkItemManager {
break;
}
}
+
}
}
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 7ae6edf3fb..93554930fa 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
@@ -76,6 +76,7 @@ import org.jbpm.workflow.instance.node.EventNodeInstanceInterface;
import org.jbpm.workflow.instance.node.EventSubProcessNodeInstance;
import org.jbpm.workflow.instance.node.FaultNodeInstance;
import org.jbpm.workflow.instance.node.StateBasedNodeInstance;
+import org.jbpm.workflow.instance.node.WorkItemNodeInstance;
import org.kie.api.definition.process.NodeContainer;
import org.kie.api.definition.process.WorkflowElementIdentifier;
import org.kie.api.runtime.rule.AgendaFilter;
@@ -464,6 +465,11 @@ public abstract class WorkflowProcessInstanceImpl extends ProcessInstanceImpl im
@Override
public void disconnect() {
+ for (org.kie.api.runtime.process.NodeInstance nodeInstance : getNodeInstances(true)) {
+ if (nodeInstance instanceof WorkItemNodeInstance workItemNodeInstance) {
+ workItemNodeInstance.internalRemoveWorkItem();
+ }
+ }
removeEventListeners();
unregisterExternalEventNodeListeners();
@@ -478,11 +484,17 @@ public abstract class WorkflowProcessInstanceImpl extends ProcessInstanceImpl im
@Override
public void reconnect() {
super.reconnect();
+ for (org.kie.api.runtime.process.NodeInstance nodeInstance : getNodeInstances(true)) {
+ if (nodeInstance instanceof WorkItemNodeInstance workItemNodeInstance) {
+ workItemNodeInstance.internalRegisterWorkItem();
+ }
+ }
for (NodeInstance nodeInstance : nodeInstances) {
if (nodeInstance instanceof EventBasedNodeInstanceInterface) {
((EventBasedNodeInstanceInterface) nodeInstance).addEventListeners();
}
}
+
registerExternalEventNodeListeners();
}
diff --git a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
index 5af0a5de03..be1ff4ddfa 100755
--- a/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
+++ b/jbpm/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/WorkItemNodeInstance.java
@@ -274,7 +274,7 @@ public class WorkItemNodeInstance extends StateBasedNodeInstance implements Even
if (workItemNode != null && workItem.getState() == COMPLETED) {
validateWorkItemResultVariable(getProcessInstance().getProcessName(), workItemNode.getOutAssociations(), workItem);
Map<String, Object> outputs = new HashMap<>(workItem.getResults());
- if (workItem.getActualOwner() != null) {
+ if (workItem.getActualOwner() != null && !outputs.containsKey("ActorId")) {
outputs.put("ActorId", workItem.getActualOwner());
}
NodeIoHelper.processOutputs(this, varRef -> outputs.get(varRef), varName -> this.getVariable(varName));
@@ -284,6 +284,8 @@ public class WorkItemNodeInstance extends StateBasedNodeInstance implements Even
setMetaData("NodeType", workItem.getName());
mapDynamicOutputData(workItem.getResults());
}
+
+ internalRemoveWorkItem();
if (isInversionOfControl()) {
KieRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
kruntime.update(kruntime.getFactHandle(this), this);
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 39d2937465..99f32900da 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
@@ -73,9 +73,13 @@ import org.kie.kogito.process.flexible.AdHocFragment;
import org.kie.kogito.process.flexible.Milestone;
import org.kie.kogito.process.workitems.InternalKogitoWorkItem;
import org.kie.kogito.services.uow.ProcessInstanceWorkUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class AbstractProcessInstance<T extends Model> implements ProcessInstance<T> {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractProcessInstance.class);
+
private static final String KOGITO_PROCESS_INSTANCE = "KogitoProcessInstance";
protected final T variables;
@@ -156,6 +160,7 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
}
protected void reconnect() {
+ LOG.debug("reconnect process {}", processInstance.getId());
//set correlation
if (correlationInstance.isEmpty()) {
correlationInstance = process().correlations().findByCorrelatedId(id());
@@ -169,12 +174,6 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
processInstance.setMetaData(KOGITO_PROCESS_INSTANCE, this);
addCompletionEventListener();
- for (org.kie.api.runtime.process.NodeInstance nodeInstance : processInstance.getNodeInstances()) {
- if (nodeInstance instanceof WorkItemNodeInstance) {
- ((WorkItemNodeInstance) nodeInstance).internalRegisterWorkItem();
- }
- }
-
unbind(variables, processInstance.getVariables());
}
@@ -193,15 +192,12 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
}
protected void disconnect() {
+
if (processInstance == null) {
return;
}
- for (org.kie.api.runtime.process.NodeInstance nodeInstance : processInstance.getNodeInstances()) {
- if (nodeInstance instanceof WorkItemNodeInstance) {
- ((WorkItemNodeInstance) nodeInstance).internalRemoveWorkItem();
- }
- }
+ LOG.debug("disconnect process {}", processInstance.getId());
processInstance.disconnect();
processInstance.setMetaData(KOGITO_PROCESS_INSTANCE, null);
@@ -248,6 +244,7 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
if (processInstance.getKnowledgeRuntime() != null) {
disconnect();
}
+
processInstance = null;
}
@@ -337,7 +334,7 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
@Override
public int status() {
- return this.status;
+ return status;
}
@Override
@@ -556,12 +553,14 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
@Override
public void completeWorkItem(String id, Map<String, Object> variables, Policy... policies) {
+ syncWorkItems();
getProcessRuntime().getKogitoProcessRuntime().getKogitoWorkItemManager().completeWorkItem(id, variables, policies);
removeOnFinish();
}
@Override
public <R> R updateWorkItem(String id, Function<KogitoWorkItem, R> updater, Policy... policies) {
+ syncWorkItems();
R result = getProcessRuntime().getKogitoProcessRuntime().getKogitoWorkItemManager().updateWorkItem(id, updater, policies);
addToUnitOfWork(pi -> ((MutableProcessInstances<T>) process.instances()).update(pi.id(), pi));
return result;
@@ -569,16 +568,26 @@ public abstract class AbstractProcessInstance<T extends Model> implements Proces
@Override
public void abortWorkItem(String id, Policy... policies) {
+ syncWorkItems();
getProcessRuntime().getKogitoProcessRuntime().getKogitoWorkItemManager().abortWorkItem(id, policies);
removeOnFinish();
}
@Override
public void transitionWorkItem(String id, WorkItemTransition transition) {
+ syncWorkItems();
getProcessRuntime().getKogitoProcessRuntime().getKogitoWorkItemManager().transitionWorkItem(id, transition);
removeOnFinish();
}
+ private void syncWorkItems() {
+ for (org.kie.api.runtime.process.NodeInstance nodeInstance : processInstance().getNodeInstances(true)) {
+ if (nodeInstance instanceof WorkItemNodeInstance workItemNodeInstance) {
+ workItemNodeInstance.internalRegisterWorkItem();
+ }
+ }
+ }
+
@Override
public Set<EventDescription<?>> events() {
return processInstance().getEventDescriptions();
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java
index 4fb06024d3..d612a69296 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandler.java
@@ -18,31 +18,27 @@
*/
package org.kie.kogito.jbpm.usertask.handler;
-import java.util.Map;
+import java.util.Collections;
import java.util.Optional;
import java.util.Set;
-import org.kie.kogito.auth.SecurityPolicy;
-import org.kie.kogito.internal.process.workitem.InvalidTransitionException;
+import org.kie.kogito.Application;
+import org.kie.kogito.auth.IdentityProviders;
import org.kie.kogito.internal.process.workitem.KogitoWorkItem;
import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler;
import org.kie.kogito.internal.process.workitem.KogitoWorkItemManager;
-import org.kie.kogito.internal.process.workitem.Policy;
-import org.kie.kogito.internal.process.workitem.WorkItemLifeCycle;
-import org.kie.kogito.internal.process.workitem.WorkItemLifeCyclePhase;
-import org.kie.kogito.internal.process.workitem.WorkItemPhaseState;
-import org.kie.kogito.internal.process.workitem.WorkItemTerminationType;
import org.kie.kogito.internal.process.workitem.WorkItemTransition;
import org.kie.kogito.process.workitems.InternalKogitoWorkItem;
import org.kie.kogito.process.workitems.impl.DefaultKogitoWorkItemHandler;
-import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCycle;
-import org.kie.kogito.process.workitems.impl.DefaultWorkItemLifeCyclePhase;
import org.kie.kogito.usertask.UserTask;
import org.kie.kogito.usertask.UserTasks;
import org.kie.kogito.usertask.impl.DefaultUserTaskInstance;
+import org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle;
import static java.util.Collections.emptyMap;
import static java.util.Optional.ofNullable;
+import static org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle.PARAMETER_NOTIFY;
+import static org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle.WORKFLOW_ENGINE_USER;
/**
* Default Work Item handler based on the standard life cycle
@@ -51,29 +47,6 @@ public class UserTaskKogitoWorkItemHandler extends DefaultKogitoWorkItemHandler
private static String UT_SEPARATOR = System.getProperty("org.jbpm.ht.user.separator", ",");
- public static final WorkItemPhaseState INACTIVE = WorkItemPhaseState.initialized();
- public static final WorkItemPhaseState COMPLETED = WorkItemPhaseState.of("Completed", WorkItemTerminationType.COMPLETE);
- public static final WorkItemPhaseState ABORTED = WorkItemPhaseState.of("Aborted", WorkItemTerminationType.ABORT);
- public static final WorkItemPhaseState ACTIVATED = WorkItemPhaseState.of("Activated");
- public static final WorkItemPhaseState RESERVED = WorkItemPhaseState.of("Reserved");
-
- public static final WorkItemLifeCyclePhase TRANSITION_RESERVED_COMPLETE =
- new DefaultWorkItemLifeCyclePhase("complete", RESERVED, COMPLETED, UserTaskKogitoWorkItemHandler::userTaskCompleteWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_ACTIVATED_COMPLETE =
- new DefaultWorkItemLifeCyclePhase("complete", ACTIVATED, COMPLETED, UserTaskKogitoWorkItemHandler::userTaskCompleteFromActiveWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_RESERVED_ABORT =
- new DefaultWorkItemLifeCyclePhase("abort", RESERVED, ABORTED, UserTaskKogitoWorkItemHandler::userTaskAbortWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_ACTIVATED_ABORT =
- new DefaultWorkItemLifeCyclePhase("abort", ACTIVATED, ABORTED, UserTaskKogitoWorkItemHandler::userTaskAbortWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_ACTIVATED_CLAIM =
- new DefaultWorkItemLifeCyclePhase("claim", ACTIVATED, RESERVED, UserTaskKogitoWorkItemHandler::userTaskClaimWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_CREATED_ACTIVE =
- new DefaultWorkItemLifeCyclePhase("activate", INACTIVE, ACTIVATED, UserTaskKogitoWorkItemHandler::userTaskActivateWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_RESERVED_RELEASE =
- new DefaultWorkItemLifeCyclePhase("release", RESERVED, ACTIVATED, UserTaskKogitoWorkItemHandler::userTaskReleaseWorkItemHandler);
- public static final WorkItemLifeCyclePhase TRANSITION_ACTIVATED_COMPLETED =
- new DefaultWorkItemLifeCyclePhase("skip", ACTIVATED, COMPLETED, UserTaskKogitoWorkItemHandler::userTaskCompleteWorkItemHandler);
-
private static final String DESCRIPTION = "Description";
private static final String PRIORITY = "Priority";
private static final String TASK_NAME = "TaskName";
@@ -83,40 +56,16 @@ public class UserTaskKogitoWorkItemHandler extends DefaultKogitoWorkItemHandler
private static final String BUSINESSADMINISTRATOR_GROUP_ID = "BusinessAdministratorGroupId";
private static final String EXCLUDED_OWNER_ID = "ExcludedOwnerId";
- @Override
- public String getName() {
- return "Human Task";
- }
-
- @Override
- public WorkItemLifeCycle initialize() {
- return new DefaultWorkItemLifeCycle(
- TRANSITION_CREATED_ACTIVE,
- TRANSITION_ACTIVATED_CLAIM,
- TRANSITION_ACTIVATED_ABORT,
- TRANSITION_ACTIVATED_COMPLETE,
- TRANSITION_RESERVED_RELEASE,
- TRANSITION_RESERVED_ABORT,
- TRANSITION_RESERVED_COMPLETE,
- TRANSITION_ACTIVATED_COMPLETED);
- }
-
- @Override
- public WorkItemTransition startingTransition(Map<String, Object> data, Policy... policies) {
- return workItemLifeCycle.newTransition("activate", null, data, policies);
- }
-
- @Override
- public WorkItemTransition abortTransition(String phaseStatus, Policy... policies) {
- return workItemLifeCycle.newTransition("abort", phaseStatus, emptyMap(), policies);
+ public UserTaskKogitoWorkItemHandler() {
+ super();
}
- @Override
- public WorkItemTransition completeTransition(String phaseStatus, Map<String, Object> data, Policy... policies) {
- return workItemLifeCycle.newTransition("complete", phaseStatus, data, policies);
+ public UserTaskKogitoWorkItemHandler(Application application) {
+ super();
+ this.setApplication(application);
}
- static public Optional<WorkItemTransition> userTaskActivateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
+ public Optional<WorkItemTransition> activateWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
UserTasks userTasks = handler.getApplication().get(UserTasks.class);
Object priority = workItem.getParameter(PRIORITY);
@@ -130,11 +79,11 @@ public class UserTaskKogitoWorkItemHandler extends DefaultKogitoWorkItemHandler
UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTask.createInstance();
- instance.setId(workItem.getStringId());
instance.setTaskName((String) workItem.getParameter(TASK_NAME));
instance.setTaskDescription((String) workItem.getParameter(DESCRIPTION));
instance.setTaskPriority(priorityInteger);
instance.setExternalReferenceId(workItem.getStringId());
+
instance.setMetadata("ProcessId", workItem.getProcessInstance().getProcessId());
instance.setMetadata("ProcessType", workItem.getProcessInstance().getProcess().getType());
instance.setMetadata("ProcessVersion", workItem.getProcessInstance().getProcessVersion());
@@ -144,114 +93,61 @@ public class UserTaskKogitoWorkItemHandler extends DefaultKogitoWorkItemHandler
instance.setMetadata("RootProcessInstanceId", workItem.getProcessInstance().getRootProcessInstanceId());
instance.setMetadata("ParentProcessInstanceId", workItem.getProcessInstance().getParentProcessInstanceId());
- ofNullable(workItem.getParameters().get(ACTOR_ID)).map(String.class::cast).map(UserTaskKogitoWorkItemHandler::toSet).ifPresent(instance::setPotentialUsers);
- ofNullable(workItem.getParameters().get(GROUP_ID)).map(String.class::cast).map(UserTaskKogitoWorkItemHandler::toSet).ifPresent(instance::setPotentialGroups);
- ofNullable(workItem.getParameters().get(BUSINESSADMINISTRATOR_ID)).map(String.class::cast).map(UserTaskKogitoWorkItemHandler::toSet).ifPresent(instance::setAdminUsers);
- ofNullable(workItem.getParameters().get(BUSINESSADMINISTRATOR_GROUP_ID)).map(String.class::cast).map(UserTaskKogitoWorkItemHandler::toSet).ifPresent(instance::setAdminGroups);
- ofNullable(workItem.getParameters().get(EXCLUDED_OWNER_ID)).map(String.class::cast).map(UserTaskKogitoWorkItemHandler::toSet).ifPresent(instance::setExcludedUsers);
+ userTask.instances().create(instance);
+ instance.fireInitialStateChange();
+ workItem.getParameters().forEach(instance::setInput);
+
+ ofNullable(workItem.getParameters().get(ACTOR_ID)).map(String.class::cast).map(this::toSet).ifPresent(instance::setPotentialUsers);
+ ofNullable(workItem.getParameters().get(GROUP_ID)).map(String.class::cast).map(this::toSet).ifPresent(instance::setPotentialGroups);
+ ofNullable(workItem.getParameters().get(BUSINESSADMINISTRATOR_ID)).map(String.class::cast).map(this::toSet).ifPresent(instance::setAdminUsers);
+ ofNullable(workItem.getParameters().get(BUSINESSADMINISTRATOR_GROUP_ID)).map(String.class::cast).map(this::toSet).ifPresent(instance::setAdminGroups);
+ ofNullable(workItem.getParameters().get(EXCLUDED_OWNER_ID)).map(String.class::cast).map(this::toSet).ifPresent(instance::setExcludedUsers);
- instance.assign();
- instance.transition(instance.createTransitionToken("activate", emptyMap()));
+ instance.transition(DefaultUserTaskLifeCycle.ACTIVATE, emptyMap(), IdentityProviders.of(WORKFLOW_ENGINE_USER));
if (workItem instanceof InternalKogitoWorkItem ikw) {
ikw.setExternalReferenceId(instance.getId());
ikw.setActualOwner(instance.getActualOwner());
}
- userTask.instances().create(instance);
- return Optional.empty();
- }
- static protected Set<String> toSet(String value) {
- if (value == null) {
- return null;
- }
- return Set.of(value.split(UT_SEPARATOR));
+ return Optional.empty();
}
- static public Optional<WorkItemTransition> userTaskClaimWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
- workItem.removeOutput("ACTUAL_OWNER");
-
+ @Override
+ public Optional<WorkItemTransition> completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
UserTasks userTasks = handler.getApplication().get(UserTasks.class);
UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> {
- Map<String, Object> data = transition.data();
if (workItem instanceof InternalKogitoWorkItem ikw) {
- getUserFromTransition(transition).ifPresent(ikw::setActualOwner);
- if (data.containsKey("ACTUAL_OWNER") && ikw.getActualOwner() == null) {
- ut.setActuaOwner((String) data.get("ACTUAL_OWNER"));
- }
- if (ikw.getActualOwner() == null) {
- throw new InvalidTransitionException("transition claim does not contain user id");
- }
+ ikw.setActualOwner(ut.getActualOwner());
}
- ut.setActuaOwner(workItem.getActualOwner());
- ut.transition(ut.createTransitionToken("claim", emptyMap()));
- userTask.instances().update(ut);
+ ut.transition(DefaultUserTaskLifeCycle.SKIP, Collections.singletonMap(PARAMETER_NOTIFY, Boolean.FALSE), IdentityProviders.of(WORKFLOW_ENGINE_USER));
});
return Optional.empty();
}
- static public Optional<WorkItemTransition> userTaskReleaseWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
- if (workItem instanceof InternalKogitoWorkItem ikw) {
- ikw.setActualOwner(null);
- }
- UserTasks userTasks = handler.getApplication().get(UserTasks.class);
- UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
- userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> {
- ut.setActuaOwner(null);
- ut.transition(ut.createTransitionToken("release", emptyMap()));
- userTask.instances().update(ut);
- });
-
- return Optional.empty();
- }
-
- static public Optional<WorkItemTransition> userTaskCompleteWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
+ @Override
+ public Optional<WorkItemTransition> abortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
UserTasks userTasks = handler.getApplication().get(UserTasks.class);
UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> {
- ut.transition(ut.createTransitionToken("complete", emptyMap()));
- userTask.instances().update(ut);
+ if (workItem instanceof InternalKogitoWorkItem ikw) {
+ ikw.setActualOwner(ut.getActualOwner());
+ }
+ ut.transition(DefaultUserTaskLifeCycle.FAIL, Collections.singletonMap(PARAMETER_NOTIFY, Boolean.FALSE), IdentityProviders.of(WORKFLOW_ENGINE_USER));
});
- if (workItem instanceof InternalKogitoWorkItem ikw && ikw.getActualOwner() == null) {
- getUserFromTransition(transition).ifPresent(user -> {
- ikw.setActualOwner(user);
- });
- }
return Optional.empty();
}
- static public Optional<WorkItemTransition> userTaskCompleteFromActiveWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem,
- WorkItemTransition transition) {
- UserTasks userTasks = handler.getApplication().get(UserTasks.class);
- UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
- userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> {
- ut.transition(ut.createTransitionToken("complete", emptyMap()));
- userTask.instances().update(ut);
- });
- if (workItem instanceof InternalKogitoWorkItem ikw) {
- getUserFromTransition(transition).ifPresent(user -> {
- ikw.setActualOwner(user);
- });
+ protected Set<String> toSet(String value) {
+ if (value == null) {
+ return null;
}
- return Optional.empty();
- }
-
- static public Optional<WorkItemTransition> userTaskAbortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workItem, WorkItemTransition transition) {
- UserTasks userTasks = handler.getApplication().get(UserTasks.class);
- UserTask userTask = userTasks.userTaskById((String) workItem.getParameter(KogitoWorkItem.PARAMETER_UNIQUE_TASK_ID));
- userTask.instances().findById(workItem.getExternalReferenceId()).ifPresent(ut -> {
- ut.transition(ut.createTransitionToken("skip", emptyMap()));
- userTask.instances().update(ut);
- });
- return Optional.empty();
+ return Set.of(value.split(UT_SEPARATOR));
}
- private static Optional<String> getUserFromTransition(WorkItemTransition transition) {
- Optional<SecurityPolicy> securityPolicy = transition.policies().stream().filter(SecurityPolicy.class::isInstance).map(SecurityPolicy.class::cast).findAny();
- if (securityPolicy.isPresent()) {
- return Optional.ofNullable(securityPolicy.get().getUser());
- }
- return Optional.empty();
+ @Override
+ public String getName() {
+ return "Human Task";
}
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java
new file mode 100644
index 0000000000..7d0bc70557
--- /dev/null
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/jbpm/usertask/handler/UserTaskKogitoWorkItemHandlerProcessListener.java
@@ -0,0 +1,66 @@
+/*
+ * 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.jbpm.usertask.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.kie.kogito.process.Processes;
+import org.kie.kogito.usertask.UserTaskEventListener;
+import org.kie.kogito.usertask.events.UserTaskStateEvent;
+import org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UserTaskKogitoWorkItemHandlerProcessListener implements UserTaskEventListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UserTaskKogitoWorkItemHandlerProcessListener.class);
+
+ private Processes processes;
+
+ public UserTaskKogitoWorkItemHandlerProcessListener(Processes processes) {
+ this.processes = processes;
+ }
+
+ @Override
+ public void onUserTaskState(UserTaskStateEvent event) {
+ UserTaskState userTaskState = event.getNewStatus();
+ if (!userTaskState.isTerminate()) {
+ return;
+ }
+
+ // we check first that the work item is not finished to convey the signal
+ Boolean notify = (Boolean) event.getUserTaskInstance().getMetadata().get(DefaultUserTaskLifeCycle.PARAMETER_NOTIFY);
+ if (notify != null && !notify) {
+ return;
+ }
+
+ LOG.debug("onUserTaskState {} on complete work item", event);
+ String processId = (String) event.getUserTaskInstance().getMetadata().get("ProcessId");
+ String processInstanceId = (String) event.getUserTaskInstance().getMetadata().get("ProcessInstanceId");
+
+ processes.processById(processId).instances().findById(processInstanceId).ifPresent(pi -> {
+ Map<String, Object> data = new HashMap<>(event.getUserTaskInstance().getOutputs());
+ data.put("ActorId", event.getUserTaskInstance().getActualOwner());
+ pi.completeWorkItem(event.getUserTaskInstance().getExternalReferenceId(), data);
+ });
+
+ }
+}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java
similarity index 74%
copy from jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java
copy to jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java
index 92e2fa9c74..19a7d8c1e7 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/AbstractUserTask.java
@@ -23,23 +23,16 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import org.kie.kogito.Application;
-import org.kie.kogito.uow.events.UnitOfWorkUserTaskEventListener;
import org.kie.kogito.usertask.UserTask;
-import org.kie.kogito.usertask.UserTaskConfig;
import org.kie.kogito.usertask.UserTaskInstance;
-import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.impl.model.DeadlineHelper;
import org.kie.kogito.usertask.model.DeadlineInfo;
import org.kie.kogito.usertask.model.Reassignment;
-public class DefaultUserTask implements UserTask {
-
+public abstract class AbstractUserTask implements UserTask {
private String separator = System.getProperty("org.jbpm.ht.user.separator", ",");
- private Application application;
private String id;
- private UserTaskInstances userTaskInstances;
private String name;
private String taskName;
private String taskDescription;
@@ -56,25 +49,9 @@ public class DefaultUserTask implements UserTask {
private Collection<DeadlineInfo<Reassignment>> startReassigments;
private Collection<DeadlineInfo<Reassignment>> endReassigments;
- public DefaultUserTask() {
- // nothing
- }
-
- public DefaultUserTask(String id, String name) {
- this(null, id, name, new InMemoryUserTaskInstances());
- }
-
- public DefaultUserTask(Application application, String id, String name) {
- this(application, id, name, new InMemoryUserTaskInstances());
- }
-
- public DefaultUserTask(Application application, String id, String name, UserTaskInstances userTaskInstances) {
- this.application = application;
+ public AbstractUserTask(String id, String name) {
this.id = id;
this.name = name;
- this.userTaskInstances = userTaskInstances;
- this.userTaskInstances.setReconnectUserTaskInstance(this::connect);
- this.userTaskInstances.setDisconnectUserTaskInstance(this::disconnect);
this.skippable = Boolean.FALSE;
this.potentialUsers = new HashSet<>();
this.potentialGroups = new HashSet<>();
@@ -85,16 +62,12 @@ public class DefaultUserTask implements UserTask {
this.endDeadlines = new HashSet<>();
this.startReassigments = new HashSet<>();
this.endReassigments = new HashSet<>();
-
- }
-
- public void setApplication(Application application) {
- this.application = application;
}
@Override
public UserTaskInstance createInstance() {
DefaultUserTaskInstance instance = new DefaultUserTaskInstance(this);
+ instance.setUserTaskId(id());
instance.setTaskName(getTaskName());
instance.setTaskDescription(getTaskDescription());
instance.setTaskPriority(getTaskPriority());
@@ -103,37 +76,9 @@ public class DefaultUserTask implements UserTask {
instance.setAdminUsers(getAdminUsers());
instance.setPotentialGroups(getPotentialGroups());
instance.setExcludedUsers(getExcludedUsers());
- connect(instance);
return instance;
}
- private UserTaskInstance disconnect(UserTaskInstance userTaskInstance) {
- DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
- instance.setUserTask(null);
- instance.setUserTaskEventSupport(null);
- instance.setUserTaskLifeCycle(null);
- instance.setInstances(null);
- return instance;
- }
-
- public UserTaskInstance connect(UserTaskInstance userTaskInstance) {
- DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
- UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
- KogitoUserTaskEventSupportImpl impl = new KogitoUserTaskEventSupportImpl(userTaskConfig.identityProvider());
- userTaskConfig.userTaskEventListeners().listeners().forEach(impl::addEventListener);
- impl.addEventListener(new UnitOfWorkUserTaskEventListener(application.unitOfWorkManager()));
- instance.setUserTask(this);
- instance.setUserTaskEventSupport(impl);
- instance.setUserTaskLifeCycle(userTaskConfig.userTaskLifeCycle());
- instance.setInstances(userTaskInstances);
- return instance;
- }
-
- @Override
- public UserTaskInstances instances() {
- return userTaskInstances;
- }
-
@Override
public String id() {
return id;
diff --git a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/BasicUserTaskAssignmentStrategy.java
similarity index 53%
copy from api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java
copy to jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/BasicUserTaskAssignmentStrategy.java
index eb8290884a..076a62c313 100644
--- a/api/kogito-api/src/main/java/org/kie/kogito/usertask/lifecycle/UserTaskLifeCycle.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/BasicUserTaskAssignmentStrategy.java
@@ -16,22 +16,31 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.kie.kogito.usertask.impl;
-package org.kie.kogito.usertask.lifecycle;
-
-import java.util.Map;
+import java.util.HashSet;
import java.util.Optional;
+import java.util.Set;
+import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
import org.kie.kogito.usertask.UserTaskInstance;
-public interface UserTaskLifeCycle {
-
- Optional<UserTaskTransitionToken> transition(UserTaskInstance userTaskInstance, UserTaskTransitionToken transition);
-
- UserTaskTransitionToken newTransitionToken(String transitionId, UserTaskInstance userTaskInstance, Map<String, Object> data);
-
- UserTaskTransitionToken newCompleteTransitionToken(UserTaskInstance userTaskInstance, Map<String, Object> emptyMap);
-
- UserTaskTransitionToken newAbortTransitionToken(UserTaskInstance userTaskInstance, Map<String, Object> emptyMap);
+public class BasicUserTaskAssignmentStrategy implements UserTaskAssignmentStrategy {
+
+ @Override
+ public String getName() {
+ return DEFAULT_NAME;
+ }
+
+ @Override
+ public Optional<String> computeAssigment(UserTaskInstance userTaskInstance, IdentityProvider identityProvider) {
+ Set<String> users = new HashSet<>(userTaskInstance.getPotentialUsers());
+ users.removeAll(userTaskInstance.getExcludedUsers());
+ if (users.size() == 1) {
+ return Optional.of(users.iterator().next());
+ }
+ return Optional.empty();
+ }
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java
index 92e2fa9c74..9b80e6e717 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTask.java
@@ -18,115 +18,30 @@
*/
package org.kie.kogito.usertask.impl;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
import org.kie.kogito.Application;
-import org.kie.kogito.uow.events.UnitOfWorkUserTaskEventListener;
-import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
import org.kie.kogito.usertask.UserTaskConfig;
-import org.kie.kogito.usertask.UserTaskInstance;
import org.kie.kogito.usertask.UserTaskInstances;
-import org.kie.kogito.usertask.impl.model.DeadlineHelper;
-import org.kie.kogito.usertask.model.DeadlineInfo;
-import org.kie.kogito.usertask.model.Reassignment;
-
-public class DefaultUserTask implements UserTask {
- private String separator = System.getProperty("org.jbpm.ht.user.separator", ",");
+public class DefaultUserTask extends AbstractUserTask {
private Application application;
- private String id;
private UserTaskInstances userTaskInstances;
- private String name;
- private String taskName;
- private String taskDescription;
- private String referenceName;
- private Integer taskPriority;
- private Boolean skippable;
- private Set<String> potentialUsers;
- private Set<String> potentialGroups;
- private Set<String> adminUsers;
- private Set<String> adminGroups;
- private Set<String> excludedUsers;
- private Collection<DeadlineInfo<Map<String, Object>>> startDeadlines;
- private Collection<DeadlineInfo<Map<String, Object>>> endDeadlines;
- private Collection<DeadlineInfo<Reassignment>> startReassigments;
- private Collection<DeadlineInfo<Reassignment>> endReassigments;
-
- public DefaultUserTask() {
- // nothing
- }
public DefaultUserTask(String id, String name) {
- this(null, id, name, new InMemoryUserTaskInstances());
+ super(id, name);
}
public DefaultUserTask(Application application, String id, String name) {
- this(application, id, name, new InMemoryUserTaskInstances());
- }
-
- public DefaultUserTask(Application application, String id, String name, UserTaskInstances userTaskInstances) {
- this.application = application;
- this.id = id;
- this.name = name;
- this.userTaskInstances = userTaskInstances;
- this.userTaskInstances.setReconnectUserTaskInstance(this::connect);
- this.userTaskInstances.setDisconnectUserTaskInstance(this::disconnect);
- this.skippable = Boolean.FALSE;
- this.potentialUsers = new HashSet<>();
- this.potentialGroups = new HashSet<>();
- this.adminUsers = new HashSet<>();
- this.adminGroups = new HashSet<>();
- this.excludedUsers = new HashSet<>();
- this.startDeadlines = new HashSet<>();
- this.endDeadlines = new HashSet<>();
- this.startReassigments = new HashSet<>();
- this.endReassigments = new HashSet<>();
-
- }
-
- public void setApplication(Application application) {
+ super(id, name);
this.application = application;
+ this.userTaskInstances = application.config().get(UserTaskConfig.class).userTaskInstances();
}
@Override
- public UserTaskInstance createInstance() {
- DefaultUserTaskInstance instance = new DefaultUserTaskInstance(this);
- instance.setTaskName(getTaskName());
- instance.setTaskDescription(getTaskDescription());
- instance.setTaskPriority(getTaskPriority());
- instance.setPotentialUsers(getPotentialUsers());
- instance.setPotentialGroups(getPotentialGroups());
- instance.setAdminUsers(getAdminUsers());
- instance.setPotentialGroups(getPotentialGroups());
- instance.setExcludedUsers(getExcludedUsers());
- connect(instance);
- return instance;
- }
-
- private UserTaskInstance disconnect(UserTaskInstance userTaskInstance) {
- DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
- instance.setUserTask(null);
- instance.setUserTaskEventSupport(null);
- instance.setUserTaskLifeCycle(null);
- instance.setInstances(null);
- return instance;
- }
-
- public UserTaskInstance connect(UserTaskInstance userTaskInstance) {
- DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ public UserTaskAssignmentStrategy getAssignmentStrategy() {
UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
- KogitoUserTaskEventSupportImpl impl = new KogitoUserTaskEventSupportImpl(userTaskConfig.identityProvider());
- userTaskConfig.userTaskEventListeners().listeners().forEach(impl::addEventListener);
- impl.addEventListener(new UnitOfWorkUserTaskEventListener(application.unitOfWorkManager()));
- instance.setUserTask(this);
- instance.setUserTaskEventSupport(impl);
- instance.setUserTaskLifeCycle(userTaskConfig.userTaskLifeCycle());
- instance.setInstances(userTaskInstances);
- return instance;
+ return userTaskConfig.userTaskAssignmentStrategies().defaultUserTaskAssignmentStrategy();
}
@Override
@@ -134,170 +49,4 @@ public class DefaultUserTask implements UserTask {
return userTaskInstances;
}
- @Override
- public String id() {
- return id;
- }
-
- @Override
- public String name() {
- return name;
- }
-
- public void setSkippable(String skippable) {
- this.skippable = Boolean.parseBoolean(skippable);
- }
-
- public Boolean getSkippable() {
- return skippable;
- }
-
- @Override
- public String getTaskName() {
- return taskName;
- }
-
- public void setTaskName(String taskName) {
- this.taskName = taskName;
- }
-
- @Override
- public String getTaskDescription() {
- return taskDescription;
- }
-
- public void setTaskDescription(String taskDescription) {
- this.taskDescription = taskDescription;
- }
-
- @Override
- public Integer getTaskPriority() {
- return this.taskPriority;
- }
-
- public void setTaskPriority(Integer taskPriority) {
- this.taskPriority = taskPriority;
- }
-
- public void setReferenceName(String referenceName) {
- this.referenceName = referenceName;
- }
-
- @Override
- public String getReferenceName() {
- return referenceName;
- }
-
- @Override
- public Set<String> getPotentialUsers() {
- return this.potentialUsers;
- }
-
- public void setPotentialUsers(String potentialUsers) {
- this.setPotentialUsers(toSet(potentialUsers));
- }
-
- public void setPotentialUsers(Set<String> potentialUsers) {
- this.potentialUsers = potentialUsers;
- }
-
- @Override
- public Set<String> getPotentialGroups() {
- return this.potentialGroups;
- }
-
- public void setPotentialGroups(String potentialGroups) {
- this.setPotentialGroups(toSet(potentialGroups));
- }
-
- public void setPotentialGroups(Set<String> potentialGroups) {
- this.potentialGroups = potentialGroups;
- }
-
- @Override
- public Set<String> getAdminUsers() {
- return this.adminUsers;
- }
-
- public void setAdminUsers(String adminUsers) {
- this.setAdminUsers(toSet(adminUsers));
- }
-
- public void setAdminUsers(Set<String> adminUsers) {
- this.adminUsers = adminUsers;
- }
-
- @Override
- public Set<String> getAdminGroups() {
- return this.adminGroups;
- }
-
- public void setAdminGroups(String adminGroups) {
- this.setAdminGroups(toSet(adminGroups));
- }
-
- public void setAdminGroups(Set<String> adminGroups) {
- this.adminGroups = adminGroups;
- }
-
- @Override
- public Set<String> getExcludedUsers() {
- return this.excludedUsers;
- }
-
- public void setExcludedUsers(String excludedUsers) {
- this.setExcludedUsers(toSet(excludedUsers));
- }
-
- public void setExcludedUsers(Set<String> excludedUsers) {
- this.excludedUsers = excludedUsers;
- }
-
- @Override
- public Collection<DeadlineInfo<Map<String, Object>>> getNotStartedDeadlines() {
- return startDeadlines;
- }
-
- public void setNotStartedDeadLines(String deadlines) {
- this.startDeadlines = DeadlineHelper.parseDeadlines(deadlines);
- }
-
- @Override
- public Collection<DeadlineInfo<Map<String, Object>>> getNotCompletedDeadlines() {
- return endDeadlines;
- }
-
- public void setNotCompletedDeadlines(String notStarted) {
- this.endDeadlines = DeadlineHelper.parseDeadlines(notStarted);
- }
-
- @Override
- public Collection<DeadlineInfo<Reassignment>> getNotStartedReassignments() {
- return startReassigments;
- }
-
- public void setNotStartedReassignments(String reassignments) {
- this.startReassigments = DeadlineHelper.parseReassignments(reassignments);
- }
-
- @Override
- public Collection<DeadlineInfo<Reassignment>> getNotCompletedReassigments() {
- return endReassigments;
- }
-
- public void setNotCompletedReassigments(String reassignments) {
- this.endReassigments = DeadlineHelper.parseReassignments(reassignments);
- }
-
- protected Set<String> toSet(String value) {
- if (value == null) {
- return new HashSet<>();
- }
- Set<String> store = new HashSet<>();
- for (String item : value.split(separator)) {
- store.add(item);
- }
- return store;
- }
-
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskAssignmentStrategyConfig.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskAssignmentStrategyConfig.java
new file mode 100644
index 0000000000..5c6029b477
--- /dev/null
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskAssignmentStrategyConfig.java
@@ -0,0 +1,54 @@
+/*
+ * 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.usertask.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
+
+public class DefaultUserTaskAssignmentStrategyConfig implements UserTaskAssignmentStrategyConfig {
+
+ private Map<String, UserTaskAssignmentStrategy> userTaskAssignmentStrategies;
+
+ public DefaultUserTaskAssignmentStrategyConfig() {
+ this.userTaskAssignmentStrategies = new HashMap<>();
+ BasicUserTaskAssignmentStrategy strategy = new BasicUserTaskAssignmentStrategy();
+ this.userTaskAssignmentStrategies.put(strategy.getName(), strategy);
+ }
+
+ public DefaultUserTaskAssignmentStrategyConfig(Iterable<UserTaskAssignmentStrategy> userTaskAssignmentStrategies) {
+ this();
+ userTaskAssignmentStrategies.forEach(uts -> this.userTaskAssignmentStrategies.put(uts.getName(), uts));
+ }
+
+ @Override
+ public List<UserTaskAssignmentStrategy> userTaskAssignmentStrategies() {
+ return new ArrayList<>(userTaskAssignmentStrategies.values());
+ }
+
+ @Override
+ public UserTaskAssignmentStrategy forName(String name) {
+ return userTaskAssignmentStrategies.get(name);
+ }
+
+}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskConfig.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskConfig.java
index 93d012f011..7282ce7253 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskConfig.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskConfig.java
@@ -27,8 +27,10 @@ import org.kie.kogito.services.identity.NoOpIdentityProvider;
import org.kie.kogito.services.uow.CollectingUnitOfWorkFactory;
import org.kie.kogito.services.uow.DefaultUnitOfWorkManager;
import org.kie.kogito.uow.UnitOfWorkManager;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
import org.kie.kogito.usertask.UserTaskConfig;
import org.kie.kogito.usertask.UserTaskEventListenerConfig;
+import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle;
import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
@@ -39,13 +41,17 @@ public class DefaultUserTaskConfig implements UserTaskConfig {
private JobsService jobService;
private IdentityProvider identityProvider;
private UserTaskLifeCycle userTaskLifeCycle;
+ private UserTaskAssignmentStrategyConfig userTaskAssignmentStrategyConfig;
+ private UserTaskInstances userTaskInstances;
public DefaultUserTaskConfig() {
this(new DefaultUserTaskEventListenerConfig(),
new DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory()),
null,
new NoOpIdentityProvider(),
- new DefaultUserTaskLifeCycle());
+ new DefaultUserTaskLifeCycle(),
+ new DefaultUserTaskAssignmentStrategyConfig(),
+ new InMemoryUserTaskInstances());
}
public DefaultUserTaskConfig(
@@ -53,13 +59,17 @@ public class DefaultUserTaskConfig implements UserTaskConfig {
Iterable<UnitOfWorkManager> unitOfWorkManager,
Iterable<JobsService> jobService,
Iterable<IdentityProvider> identityProvider,
- Iterable<UserTaskLifeCycle> userTaskLifeCycle) {
+ Iterable<UserTaskLifeCycle> userTaskLifeCycle,
+ Iterable<UserTaskAssignmentStrategyConfig> userTaskAssignmentStrategyConfig,
+ Iterable<UserTaskInstances> userTaskInstances) {
this.userTaskEventListeners = singleton(userTaskEventListenerConfig, DefaultUserTaskEventListenerConfig::new);
this.unitOfWorkManager = singleton(unitOfWorkManager, () -> new DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory()));
this.jobService = singleton(jobService, () -> null);
this.identityProvider = singleton(identityProvider, NoOpIdentityProvider::new);
this.userTaskLifeCycle = singleton(userTaskLifeCycle, DefaultUserTaskLifeCycle::new);
+ this.userTaskAssignmentStrategyConfig = singleton(userTaskAssignmentStrategyConfig, DefaultUserTaskAssignmentStrategyConfig::new);
+ this.userTaskInstances = singleton(userTaskInstances, InMemoryUserTaskInstances::new);
}
@@ -76,12 +86,16 @@ public class DefaultUserTaskConfig implements UserTaskConfig {
UnitOfWorkManager unitOfWorkManager,
JobsService jobService,
IdentityProvider identityProvider,
- UserTaskLifeCycle userTaskLifeCycle) {
+ UserTaskLifeCycle userTaskLifeCycle,
+ DefaultUserTaskAssignmentStrategyConfig userTaskAssignmentStrategyConfig,
+ UserTaskInstances userTaskInstances) {
this.userTaskEventListeners = userTaskEventListenerConfig;
this.unitOfWorkManager = unitOfWorkManager;
this.jobService = jobService;
this.identityProvider = identityProvider;
this.userTaskLifeCycle = userTaskLifeCycle;
+ this.userTaskAssignmentStrategyConfig = userTaskAssignmentStrategyConfig;
+ this.userTaskInstances = userTaskInstances;
}
@Override
@@ -109,4 +123,14 @@ public class DefaultUserTaskConfig implements UserTaskConfig {
return userTaskLifeCycle;
}
+ @Override
+ public UserTaskAssignmentStrategyConfig userTaskAssignmentStrategies() {
+ return userTaskAssignmentStrategyConfig;
+ }
+
+ @Override
+ public UserTaskInstances userTaskInstances() {
+ return userTaskInstances;
+ }
+
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskEventListenerConfig.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskEventListenerConfig.java
index 9cb7f3ac09..086c729124 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskEventListenerConfig.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskEventListenerConfig.java
@@ -32,8 +32,13 @@ public class DefaultUserTaskEventListenerConfig implements UserTaskEventListener
this.listeners = new ArrayList<>();
}
+ public DefaultUserTaskEventListenerConfig(Iterable<UserTaskEventListener> listeners) {
+ this();
+ listeners.forEach(this::addUserTaskEventListener);
+ }
+
public DefaultUserTaskEventListenerConfig(List<UserTaskEventListener> listeners) {
- this.listeners = new ArrayList<>(listeners);
+ this((Iterable<UserTaskEventListener>) listeners);
}
public void addUserTaskEventListener(UserTaskEventListener userTaskEventListener) {
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java
index 8adb9f07d0..e5265ae3f7 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTaskInstance.java
@@ -19,7 +19,7 @@
package org.kie.kogito.usertask.impl;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -28,6 +28,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.UUID;
+import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.internal.usertask.event.KogitoUserTaskEventSupport;
import org.kie.kogito.internal.usertask.event.KogitoUserTaskEventSupport.AssignmentType;
import org.kie.kogito.usertask.UserTask;
@@ -35,7 +36,6 @@ import org.kie.kogito.usertask.UserTaskInstance;
import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
import org.kie.kogito.usertask.lifecycle.UserTaskState;
-import org.kie.kogito.usertask.lifecycle.UserTaskTransition;
import org.kie.kogito.usertask.lifecycle.UserTaskTransitionToken;
import org.kie.kogito.usertask.model.Attachment;
import org.kie.kogito.usertask.model.Comment;
@@ -46,6 +46,8 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
private String id;
+ private String userTaskId;
+
private UserTaskState status;
private String actualOwner;
private String taskName;
@@ -75,6 +77,9 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
private UserTaskLifeCycle setUserTaskLifeCycle;
public DefaultUserTaskInstance() {
+ this.inputs = new HashMap<>();
+ this.outputs = new HashMap<>();
+ this.status = UserTaskState.initalized();
this.metadata = new HashMap<>();
this.attachments = new ArrayList<>();
this.comments = new ArrayList<>();
@@ -86,27 +91,10 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
}
public DefaultUserTaskInstance(UserTask userTask) {
+ this();
this.id = UUID.randomUUID().toString();
this.userTask = userTask;
this.instances = userTask.instances();
- this.status = UserTaskState.initalized();
- this.metadata = new HashMap<>();
- this.attachments = new ArrayList<>();
- this.comments = new ArrayList<>();
- this.potentialUsers = new HashSet<>();
- this.potentialGroups = new HashSet<>();
- this.adminUsers = new HashSet<>();
- this.adminGroups = new HashSet<>();
- this.excludedUsers = new HashSet<>();
- }
-
- public void assign() {
- Set<String> potentialUsers = new HashSet<>(this.getPotentialUsers());
- potentialUsers.removeAll(getExcludedUsers());
-
- if (potentialUsers.size() == 1) {
- this.actualOwner = potentialUsers.iterator().next();
- }
}
public void setUserTaskEventSupport(KogitoUserTaskEventSupport userTaskEventSupport) {
@@ -121,22 +109,17 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
this.instances = instances;
}
- @Override
- public void complete() {
- UserTaskTransitionToken transition = this.setUserTaskLifeCycle.newCompleteTransitionToken(this, Collections.emptyMap());
- transition(transition);
- instances.remove(id);
+ public void setId(String id) {
+ this.id = id;
}
@Override
- public void abort() {
- UserTaskTransitionToken transition = this.setUserTaskLifeCycle.newAbortTransitionToken(this, Collections.emptyMap());
- transition(transition);
- instances.remove(id);
+ public String getUserTaskId() {
+ return userTaskId;
}
- public void setId(String id) {
- this.id = id;
+ public void setUserTaskId(String userTaskId) {
+ this.userTaskId = userTaskId;
}
@Override
@@ -162,8 +145,9 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
public void setActuaOwner(String actualOwner) {
this.actualOwner = actualOwner;
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status.getName(), this.status.getName());
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status);
}
+ updatePersistence();
}
@Override
@@ -181,21 +165,29 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
}
@Override
- public UserTaskTransitionToken createTransitionToken(String transitionId, Map<String, Object> data) {
- return this.setUserTaskLifeCycle.newTransitionToken(transitionId, this, data);
- }
-
- @Override
- public void transition(UserTaskTransitionToken token) {
- Optional<UserTaskTransitionToken> next = Optional.of(token);
+ public void transition(String transitionId, Map<String, Object> data, IdentityProvider identity) {
+ Optional<UserTaskTransitionToken> next = Optional.of(this.setUserTaskLifeCycle.newTransitionToken(transitionId, this, data));
while (next.isPresent()) {
- UserTaskTransition transition = next.get().transition();
- next = this.setUserTaskLifeCycle.transition(this, token);
+ UserTaskTransitionToken transition = next.get();
+ next = this.setUserTaskLifeCycle.transition(this, transition, identity);
this.status = transition.target();
- this.userTaskEventSupport.fireOneUserTaskStateChange(this, transition.source().getName(), transition.target().getName());
- if (this.status.isTerminate().isPresent()) {
- this.instances.remove(this.id);
- }
+ this.updatePersistenceOrRemove();
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, transition.source(), transition.target());
+ }
+
+ }
+
+ private void updatePersistence() {
+ if (this.instances != null) {
+ this.instances.update(this);
+ }
+ }
+
+ private void updatePersistenceOrRemove() {
+ if (this.status.isTerminate()) {
+ this.instances.remove(this.id);
+ } else {
+ this.instances.update(this);
}
}
@@ -204,7 +196,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
return userTask;
}
- public void setUserTask(DefaultUserTask userTask) {
+ public void setUserTask(UserTask userTask) {
this.userTask = userTask;
}
@@ -213,7 +205,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
}
public void setInputs(Map<String, Object> inputs) {
- this.inputs = inputs;
+ inputs.forEach(this::setInput);
}
public Map<String, Object> getOutputs() {
@@ -221,7 +213,25 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
}
public void setOutputs(Map<String, Object> outputs) {
- this.outputs = outputs;
+ outputs.forEach(this::setOutput);
+ }
+
+ @Override
+ public void setInput(String key, Object newValue) {
+ Object oldValue = this.inputs.put(key, newValue);
+ if (this.userTaskEventSupport != null) {
+ this.userTaskEventSupport.fireOnUserTaskInputVariableChange(this, key, oldValue, newValue);
+ }
+ updatePersistence();
+ }
+
+ @Override
+ public void setOutput(String key, Object newValue) {
+ Object oldValue = this.outputs.put(key, newValue);
+ if (this.userTaskEventSupport != null) {
+ this.userTaskEventSupport.fireOnUserTaskOutputVariableChange(this, key, oldValue, newValue);
+ }
+ updatePersistence();
}
/**
@@ -237,7 +247,14 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
public void setTaskName(String taskName) {
this.taskName = taskName;
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status.getName(), this.status.getName());
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status);
+ }
+ updatePersistence();
+ }
+
+ public void fireInitialStateChange() {
+ if (this.userTaskEventSupport != null) {
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status);
}
}
@@ -254,8 +271,9 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status.getName(), this.status.getName());
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status);
}
+ updatePersistence();
}
/**
@@ -271,8 +289,9 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
public void setTaskPriority(Integer taskPriority) {
this.taskPriority = taskPriority;
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status.getName(), this.status.getName());
+ this.userTaskEventSupport.fireOneUserTaskStateChange(this, this.status, this.status);
}
+ updatePersistence();
}
/**
@@ -291,6 +310,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAssignmentChange(this, AssignmentType.USER_OWNERS, oldValues, potentialUsers);
}
+ updatePersistence();
}
/**
@@ -309,6 +329,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAssignmentChange(this, AssignmentType.USER_GROUPS, oldValues, potentialGroups);
}
+ updatePersistence();
}
/**
@@ -327,6 +348,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAssignmentChange(this, AssignmentType.ADMIN_USERS, oldValues, adminUsers);
}
+ updatePersistence();
}
/**
@@ -345,6 +367,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAssignmentChange(this, AssignmentType.ADMIN_GROUPS, oldValues, adminGroups);
}
+ updatePersistence();
}
/**
@@ -363,6 +386,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAssignmentChange(this, AssignmentType.USERS_EXCLUDED, oldValues, excludedUsers);
}
+ updatePersistence();
}
/**
@@ -370,41 +394,64 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
*
* @return A map which key is the attachment id and value the attachment object
*/
+
public List<Attachment> getAttachments() {
return attachments;
}
@Override
- public void addAttachment(Attachment attachment) {
+ public Attachment addAttachment(Attachment attachment) {
+ attachment.setId(UUID.randomUUID().toString());
+ attachment.setUpdatedAt(new Date());
this.attachments.add(attachment);
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAttachmentAdded(this, attachment);
}
+ updatePersistence();
+ return attachment;
}
@Override
- public void updateAttachment(Attachment newAttachment) {
+ public Attachment updateAttachment(Attachment newAttachment) {
Optional<Attachment> oldAttachment = this.attachments.stream().filter(e -> e.getId().equals(newAttachment.getId())).findFirst();
if (oldAttachment.isEmpty()) {
- return;
+ return null;
}
this.attachments.remove(oldAttachment.get());
+ if (newAttachment.getName() == null) {
+ String path = newAttachment.getContent().getPath();
+ int idx = path.lastIndexOf("/");
+ if (idx > 0) {
+ path = path.substring(idx + 1);
+ }
+ newAttachment.setName(path);
+ }
+ newAttachment.setUpdatedAt(new Date());
this.attachments.add(newAttachment);
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskAttachmentChange(this, oldAttachment.get(), newAttachment);
}
+ updatePersistence();
+ return newAttachment;
}
@Override
- public void removeAttachment(Attachment oldAttachment) {
- this.attachments.remove(oldAttachment);
+ public Attachment removeAttachment(Attachment attachment) {
+ Optional<Attachment> oldAttachment = this.attachments.stream().filter(e -> e.getId().equals(attachment.getId())).findFirst();
+ if (oldAttachment.isEmpty()) {
+ return null;
+ }
+ this.attachments.remove(attachment);
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOnUserTaskAttachmentDeleted(this, oldAttachment);
+ this.userTaskEventSupport.fireOnUserTaskAttachmentDeleted(this, oldAttachment.get());
}
+ updatePersistence();
+ return oldAttachment.get();
}
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
+ updatePersistence();
}
@@ -413,45 +460,61 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
*
* @return A map which key is the comment id and value the comment object
*/
+
public List<Comment> getComments() {
return comments;
}
@Override
- public void addComment(Comment comment) {
+ public Comment addComment(Comment comment) {
+ comment.setId(UUID.randomUUID().toString());
+ comment.setUpdatedAt(new Date());
this.comments.add(comment);
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskCommentAdded(this, comment);
}
+ updatePersistence();
+ return comment;
}
@Override
- public void updateComment(Comment newComment) {
+ public Comment updateComment(Comment newComment) {
Optional<Comment> oldComment = this.comments.stream().filter(e -> e.getId().equals(newComment.getId())).findFirst();
if (oldComment.isEmpty()) {
- return;
+ return null;
}
this.comments.remove(oldComment.get());
+ newComment.setUpdatedAt(new Date());
this.comments.add(newComment);
if (this.userTaskEventSupport != null) {
this.userTaskEventSupport.fireOnUserTaskCommentChange(this, oldComment.get(), newComment);
}
+ updatePersistence();
+ return newComment;
}
@Override
- public void removeComment(Comment comment) {
+ public Comment removeComment(Comment comment) {
+ Optional<Comment> oldComment = this.comments.stream().filter(e -> e.getId().equals(comment.getId())).findFirst();
+ if (oldComment.isEmpty()) {
+ return null;
+ }
this.comments.remove(comment);
if (this.userTaskEventSupport != null) {
- this.userTaskEventSupport.fireOnUserTaskCommentDeleted(this, comment);
+ this.userTaskEventSupport.fireOnUserTaskCommentDeleted(this, oldComment.get());
}
+ updatePersistence();
+ return oldComment.get();
}
public void setComments(List<Comment> comments) {
this.comments = comments;
+ updatePersistence();
}
public void setMetadata(String key, Object value) {
this.metadata.put(key, value);
+ updatePersistence();
}
public Map<String, Object> getMetadata() {
@@ -460,6 +523,7 @@ public class DefaultUserTaskInstance implements UserTaskInstance {
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
+ updatePersistence();
}
@Override
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTasks.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTasks.java
index a2a664e82d..e291867332 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTasks.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/DefaultUserTasks.java
@@ -25,13 +25,18 @@ import java.util.List;
import java.util.Map;
import org.kie.kogito.Application;
+import org.kie.kogito.uow.events.UnitOfWorkUserTaskEventListener;
import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.UserTasks;
public class DefaultUserTasks implements UserTasks {
private Map<String, UserTask> userTasks;
private Application application;
+ private UserTaskInstances userTaskInstances;
public DefaultUserTasks() {
this.userTasks = new HashMap<>();
@@ -49,6 +54,9 @@ public class DefaultUserTasks implements UserTasks {
UserTask userTask = userTaskIterator.next();
this.userTasks.put(userTask.id(), userTask);
}
+ userTaskInstances = application.config().get(UserTaskConfig.class).userTaskInstances();
+ userTaskInstances.setDisconnectUserTaskInstance(this::disconnect);
+ userTaskInstances.setReconnectUserTaskInstance(this::connect);
}
@Override
@@ -61,4 +69,30 @@ public class DefaultUserTasks implements UserTasks {
return userTasks.keySet();
}
+ @Override
+ public UserTaskInstances instances() {
+ return userTaskInstances;
+ }
+
+ public UserTaskInstance disconnect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ instance.setUserTask(null);
+ instance.setUserTaskEventSupport(null);
+ instance.setUserTaskLifeCycle(null);
+ instance.setInstances(null);
+ return instance;
+ }
+
+ public UserTaskInstance connect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ KogitoUserTaskEventSupportImpl impl = new KogitoUserTaskEventSupportImpl(userTaskConfig.identityProvider());
+ userTaskConfig.userTaskEventListeners().listeners().forEach(impl::addEventListener);
+ impl.addEventListener(new UnitOfWorkUserTaskEventListener(application.unitOfWorkManager()));
+ instance.setUserTask(application.get(UserTasks.class).userTaskById(instance.getUserTaskId()));
+ instance.setUserTaskEventSupport(impl);
+ instance.setUserTaskLifeCycle(userTaskConfig.userTaskLifeCycle());
+ instance.setInstances(userTaskInstances);
+ return instance;
+ }
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java
index 6704fbd83a..def2088da3 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/InMemoryUserTaskInstances.java
@@ -18,28 +18,42 @@
*/
package org.kie.kogito.usertask.impl;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Function;
+import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.usertask.UserTaskInstance;
import org.kie.kogito.usertask.UserTaskInstances;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class InMemoryUserTaskInstances implements UserTaskInstances {
+ private static Logger LOG = LoggerFactory.getLogger(InMemoryUserTaskInstances.class);
+
private Map<String, byte[]> userTaskInstances;
private Function<UserTaskInstance, UserTaskInstance> reconnectUserTaskInstance;
private Function<UserTaskInstance, UserTaskInstance> disconnectUserTaskInstance;
private ObjectMapper mapper;
public InMemoryUserTaskInstances() {
+ LOG.info("Initializing InMemoryUsertaskInstances");
this.userTaskInstances = new HashMap<>();
- this.reconnectUserTaskInstance = Function.identity();
- this.disconnectUserTaskInstance = Function.identity();
+ this.reconnectUserTaskInstance = null;
+ this.disconnectUserTaskInstance = null;
this.mapper = new ObjectMapper();
+ this.mapper.registerModule(new JavaTimeModule());
}
@Override
@@ -55,13 +69,68 @@ public class InMemoryUserTaskInstances implements UserTaskInstances {
@Override
public Optional<UserTaskInstance> findById(String userTaskInstanceId) {
try {
+ if (!userTaskInstances.containsKey(userTaskInstanceId)) {
+ return Optional.empty();
+ }
UserTaskInstance userTaskInstance = mapper.readValue(userTaskInstances.get(userTaskInstanceId), DefaultUserTaskInstance.class);
return Optional.ofNullable(reconnectUserTaskInstance.apply(userTaskInstance));
} catch (Exception e) {
+ LOG.error("during find by Id {}", userTaskInstanceId, e);
return Optional.empty();
}
}
+ @Override
+ public List<UserTaskInstance> findByIdentity(IdentityProvider identity) {
+ try {
+ String user = identity.getName();
+ Collection<String> roles = identity.getRoles();
+ List<UserTaskInstance> users = new ArrayList<>();
+ for (String id : userTaskInstances.keySet()) {
+ UserTaskInstance userTaskInstance = mapper.readValue(userTaskInstances.get(id), DefaultUserTaskInstance.class);
+ if (checkVisibility(userTaskInstance, user, roles)) {
+ users.add(reconnectUserTaskInstance.apply(userTaskInstance));
+ }
+ }
+ return users;
+ } catch (Exception e) {
+ LOG.error("during find by Identity {}", identity.getName(), e);
+ return Collections.emptyList();
+ }
+ }
+
+ private boolean checkVisibility(UserTaskInstance userTaskInstance, String user, Collection<String> roles) {
+ Set<String> adminUsers = userTaskInstance.getAdminUsers();
+ if (adminUsers.contains(user)) {
+ return true;
+ }
+
+ Set<String> userAdminGroups = new HashSet<>(userTaskInstance.getAdminGroups());
+ userAdminGroups.retainAll(roles);
+ if (!userAdminGroups.isEmpty()) {
+ return true;
+ }
+
+ if (userTaskInstance.getActualOwner() != null && userTaskInstance.getActualOwner().equals(user)) {
+ return true;
+ }
+
+ // there is no user
+ Set<String> users = new HashSet<>(userTaskInstance.getPotentialUsers());
+ users.removeAll(userTaskInstance.getExcludedUsers());
+ if (users.contains(user)) {
+ return true;
+ }
+
+ Set<String> userPotGroups = new HashSet<>(userTaskInstance.getPotentialGroups());
+ userPotGroups.retainAll(roles);
+ if (!userPotGroups.isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+
@Override
public boolean exists(String userTaskInstanceId) {
return userTaskInstances.containsKey(userTaskInstanceId);
@@ -74,6 +143,7 @@ public class InMemoryUserTaskInstances implements UserTaskInstances {
userTaskInstances.put(userTaskInstance.getId(), data);
return reconnectUserTaskInstance.apply(userTaskInstance);
} catch (Exception e) {
+ LOG.error("during create {}", userTaskInstance.getId(), e);
return null;
}
}
@@ -85,6 +155,7 @@ public class InMemoryUserTaskInstances implements UserTaskInstances {
userTaskInstances.put(userTaskInstance.getId(), data);
return userTaskInstance;
} catch (Exception e) {
+ LOG.error("during udpate {}", userTaskInstance.getId(), e);
return null;
}
}
@@ -92,8 +163,12 @@ public class InMemoryUserTaskInstances implements UserTaskInstances {
@Override
public UserTaskInstance remove(String userTaskInstanceId) {
try {
+ if (!userTaskInstances.containsKey(userTaskInstanceId)) {
+ return null;
+ }
return disconnectUserTaskInstance.apply(mapper.readValue(userTaskInstances.remove(userTaskInstanceId), DefaultUserTaskInstance.class));
} catch (Exception e) {
+ LOG.error("during remove {}", userTaskInstanceId, e);
return null;
}
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/KogitoUserTaskEventSupportImpl.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/KogitoUserTaskEventSupportImpl.java
index 1a2c3be5d6..b337d159d4 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/KogitoUserTaskEventSupportImpl.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/KogitoUserTaskEventSupportImpl.java
@@ -37,6 +37,7 @@ import org.kie.kogito.usertask.impl.events.UserTaskCommentEventImpl;
import org.kie.kogito.usertask.impl.events.UserTaskDeadlineEventImpl;
import org.kie.kogito.usertask.impl.events.UserTaskStateEventImpl;
import org.kie.kogito.usertask.impl.events.UserTaskVariableEventImpl;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
import org.kie.kogito.usertask.model.Attachment;
import org.kie.kogito.usertask.model.Comment;
@@ -84,7 +85,7 @@ public class KogitoUserTaskEventSupportImpl implements KogitoUserTaskEventSuppor
@Override
public void fireOneUserTaskStateChange(
UserTaskInstance userTaskInstance,
- String oldStatus, String newStatus) {
+ UserTaskState oldStatus, UserTaskState newStatus) {
UserTaskStateEventImpl event = new UserTaskStateEventImpl(userTaskInstance, oldStatus, newStatus, identityProvider.getName());
event.setOldStatus(oldStatus);
event.setNewStatus(newStatus);
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/UserTaskServiceImpl.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/UserTaskServiceImpl.java
new file mode 100644
index 0000000000..da83176f6d
--- /dev/null
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/UserTaskServiceImpl.java
@@ -0,0 +1,265 @@
+/*
+ * 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.usertask.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.kie.kogito.Application;
+import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTaskService;
+import org.kie.kogito.usertask.UserTasks;
+import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
+import org.kie.kogito.usertask.lifecycle.UserTaskTransition;
+import org.kie.kogito.usertask.model.Attachment;
+import org.kie.kogito.usertask.model.Comment;
+import org.kie.kogito.usertask.view.UserTaskTransitionView;
+import org.kie.kogito.usertask.view.UserTaskView;
+
+public class UserTaskServiceImpl implements UserTaskService {
+
+ private Application application;
+
+ public UserTaskServiceImpl(Application application) {
+ this.application = application;
+ }
+
+ @Override
+ public Optional<UserTaskView> getUserTaskInstance(String taskId, IdentityProvider identity) {
+ return application.get(UserTasks.class).instances().findById(taskId).map(this::toUserTaskView);
+ }
+
+ @Override
+ public List<UserTaskView> list(IdentityProvider identity) {
+ return application.get(UserTasks.class).instances().findByIdentity(identity).stream().map(this::toUserTaskView).toList();
+ }
+
+ private UserTaskView toUserTaskView(UserTaskInstance instance) {
+ UserTaskView view = new UserTaskView();
+ view.setId(instance.getId());
+ view.setUserTaskId(instance.getUserTaskId());
+ view.setStatus(instance.getStatus());
+ view.setTaskName(instance.getTaskName());
+ view.setTaskDescription(instance.getTaskDescription());
+ view.setTaskPriority(instance.getTaskPriority());
+ view.setPotentialUsers(instance.getPotentialUsers());
+ view.setPotentialGroups(instance.getPotentialGroups());
+ view.setExcludedUsers(instance.getExcludedUsers());
+ view.setAdminUsers(instance.getAdminUsers());
+ view.setAdminGroups(instance.getAdminGroups());
+ view.setActualOwner(instance.getActualOwner());
+ view.setInputs(instance.getInputs());
+ view.setOutputs(instance.getOutputs());
+ view.setMetadata(instance.getMetadata());
+ return view;
+ }
+
+ @Override
+ public Optional<UserTaskView> transition(String taskId, String transitionId, Map<String, Object> data, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ ut.transition(transitionId, data, identity);
+ return Optional.of(toUserTaskView(ut));
+ });
+ }
+
+ @Override
+ public List<UserTaskTransitionView> allowedTransitions(String taskId, IdentityProvider identity) {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Collections.emptyList();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ UserTaskLifeCycle userTaskLifeCycle = application.config().get(UserTaskConfig.class).userTaskLifeCycle();
+ List<UserTaskTransition> transitions = userTaskLifeCycle.allowedTransitions(ut);
+ return toUserTaskTransitionView(transitions);
+ }
+
+ private List<UserTaskTransitionView> toUserTaskTransitionView(List<UserTaskTransition> transitions) {
+ List<UserTaskTransitionView> views = new ArrayList<>();
+ for (UserTaskTransition transition : transitions) {
+ UserTaskTransitionView view = new UserTaskTransitionView();
+ view.setTransitionId(transition.id());
+ view.setSource(transition.source());
+ view.setTarget(transition.target());
+ views.add(view);
+ }
+
+ return views;
+ }
+
+ @Override
+ public Optional<UserTaskView> setOutputs(String taskId, Map<String, Object> data, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ data.forEach(ut::setOutput);
+ return Optional.of(toUserTaskView(ut));
+ });
+ }
+
+ @Override
+ public Optional<UserTaskView> setInputs(String taskId, Map<String, Object> data, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ data.forEach(ut::setInput);
+ return Optional.of(toUserTaskView(ut));
+ });
+ }
+
+ @Override
+ public List<Comment> getComments(String taskId, IdentityProvider identity) {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Collections.emptyList();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return new ArrayList<>(ut.getComments());
+ }
+
+ @Override
+ public Optional<Comment> getComment(String taskId, String commentId, IdentityProvider identity) {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return Optional.ofNullable(ut.findCommentById(commentId));
+ }
+
+ @Override
+ public Optional<Comment> addComment(String taskId, Comment comment, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ Comment wrap = new Comment(null, identity.getName());
+ wrap.setContent(comment.getContent());
+ return Optional.ofNullable(ut.addComment(wrap));
+ });
+ }
+
+ @Override
+ public Optional<Comment> updateComment(String taskId, Comment comment, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ Comment wrap = new Comment(comment.getId(), identity.getName());
+ wrap.setContent(comment.getContent());
+ return Optional.ofNullable(ut.updateComment(wrap));
+ });
+ }
+
+ @Override
+ public Optional<Comment> removeComment(String taskId, String commentId, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return Optional.ofNullable(ut.removeComment(new Comment(commentId, identity.getName())));
+ });
+ }
+
+ @Override
+ public List<Attachment> getAttachments(String taskId, IdentityProvider identity) {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Collections.emptyList();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return new ArrayList<>(ut.getAttachments());
+ }
+
+ @Override
+ public Optional<Attachment> getAttachment(String taskId, String attachmentId, IdentityProvider identity) {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return Optional.ofNullable(ut.findAttachmentById(attachmentId));
+ }
+
+ @Override
+ public Optional<Attachment> addAttachment(String taskId, Attachment attachment, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ Attachment wrap = new Attachment(null, identity.getName());
+ wrap.setContent(attachment.getContent());
+ wrap.setName(attachment.getName());
+ return Optional.ofNullable(ut.addAttachment(wrap));
+ });
+ }
+
+ @Override
+ public Optional<Attachment> updateAttachment(String taskId, Attachment attachment, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ Attachment wrap = new Attachment(attachment.getId(), identity.getName());
+ wrap.setContent(attachment.getContent());
+ wrap.setName(attachment.getName());
+ return Optional.ofNullable(ut.updateAttachment(attachment));
+ });
+ }
+
+ @Override
+ public Optional<Attachment> removeAttachment(String taskId, String attachmentId, IdentityProvider identity) {
+ return UnitOfWorkExecutor.executeInUnitOfWork(application.unitOfWorkManager(), () -> {
+ Optional<UserTaskInstance> userTaskInstance = application.get(UserTasks.class).instances().findById(taskId);
+ if (userTaskInstance.isEmpty()) {
+ return Optional.empty();
+ }
+ UserTaskInstance ut = userTaskInstance.get();
+ return Optional.ofNullable(ut.removeAttachment(new Attachment(attachmentId, identity.getName())));
+ });
+ }
+
+}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/events/UserTaskStateEventImpl.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/events/UserTaskStateEventImpl.java
index 1bc9005e1f..e7f734ed08 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/events/UserTaskStateEventImpl.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/events/UserTaskStateEventImpl.java
@@ -20,34 +20,37 @@ package org.kie.kogito.usertask.impl.events;
import org.kie.kogito.usertask.UserTaskInstance;
import org.kie.kogito.usertask.events.UserTaskStateEvent;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
public class UserTaskStateEventImpl extends UserTaskEventImpl implements UserTaskStateEvent {
private static final long serialVersionUID = 4556236095420836309L;
- private String oldStatus;
- private String newStatus;
+ private UserTaskState oldStatus;
+ private UserTaskState newStatus;
- public UserTaskStateEventImpl(UserTaskInstance userTaskInstance, String oldStatus, String newStatus, String user) {
+ public UserTaskStateEventImpl(UserTaskInstance userTaskInstance, UserTaskState oldStatus, UserTaskState newStatus, String user) {
super(userTaskInstance, user);
+ this.oldStatus = oldStatus;
+ this.newStatus = newStatus;
}
- public void setOldStatus(String oldStatus) {
+ public void setOldStatus(UserTaskState oldStatus) {
this.oldStatus = oldStatus;
}
- public void setNewStatus(String newStatus) {
+ public void setNewStatus(UserTaskState newStatus) {
this.newStatus = newStatus;
}
@Override
- public String getNewStatus() {
+ public UserTaskState getNewStatus() {
return newStatus;
}
@Override
- public String getOldStatus() {
+ public UserTaskState getOldStatus() {
return oldStatus;
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java
index da681ed8f4..369c7fc6bc 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskLifeCycle.java
@@ -18,34 +18,53 @@
*/
package org.kie.kogito.usertask.impl.lifecycle;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
+import org.kie.kogito.auth.IdentityProvider;
+import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.impl.DefaultUserTaskInstance;
import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
import org.kie.kogito.usertask.lifecycle.UserTaskState;
import org.kie.kogito.usertask.lifecycle.UserTaskState.TerminationType;
import org.kie.kogito.usertask.lifecycle.UserTaskTransition;
+import org.kie.kogito.usertask.lifecycle.UserTaskTransitionException;
import org.kie.kogito.usertask.lifecycle.UserTaskTransitionToken;
public class DefaultUserTaskLifeCycle implements UserTaskLifeCycle {
+ public static final String WORKFLOW_ENGINE_USER = "WORKFLOW_ENGINE_USER";
- public static final UserTaskState INACTIVE = UserTaskState.of(null);
+ public static final String PARAMETER_USER = "USER";
+ public static final String PARAMETER_NOTIFY = "NOTIFY";
+
+ public static final String ACTIVATE = "activate";
+ public static final String CLAIM = "claim";
+ public static final String RELEASE = "release";
+ public static final String COMPLETE = "complete";
+ public static final String SKIP = "skip";
+ public static final String FAIL = "fail";
+
+ public static final UserTaskState INACTIVE = UserTaskState.initalized();
public static final UserTaskState ACTIVE = UserTaskState.of("Ready");
public static final UserTaskState RESERVED = UserTaskState.of("Reserved");
public static final UserTaskState COMPLETED = UserTaskState.of("Completed", TerminationType.COMPLETED);
public static final UserTaskState ERROR = UserTaskState.of("Error", TerminationType.ERROR);
public static final UserTaskState OBSOLETE = UserTaskState.of("Obsolete", TerminationType.OBSOLETE);
- private static final UserTaskTransition T_NEW_ACTIVE = new DefaultUserTransition("activate", INACTIVE, ACTIVE, DefaultUserTaskLifeCycle::activate);
- private static final UserTaskTransition T_ACTIVE_RESERVED = new DefaultUserTransition("claim", ACTIVE, RESERVED, DefaultUserTaskLifeCycle::claim);
- private static final UserTaskTransition T_RESERVED_ACTIVE = new DefaultUserTransition("release", RESERVED, ACTIVE, DefaultUserTaskLifeCycle::release);
- private static final UserTaskTransition T_ACTIVE_COMPLETED = new DefaultUserTransition("complete", ACTIVE, COMPLETED, DefaultUserTaskLifeCycle::complete);
- private static final UserTaskTransition T_RESERVED_COMPLETED = new DefaultUserTransition("complete", RESERVED, COMPLETED, DefaultUserTaskLifeCycle::complete);
- private static final UserTaskTransition T_RESERVED_SKIPPED = new DefaultUserTransition("skip", RESERVED, OBSOLETE, DefaultUserTaskLifeCycle::skip);
- private static final UserTaskTransition T_ACTIVE_SKIPPED = new DefaultUserTransition("skip", ACTIVE, OBSOLETE, DefaultUserTaskLifeCycle::complete);
- private static final UserTaskTransition T_RESERVED_ERROR = new DefaultUserTransition("fail", RESERVED, ERROR, DefaultUserTaskLifeCycle::fail);
+ private final UserTaskTransition T_NEW_ACTIVE = new DefaultUserTransition(ACTIVATE, INACTIVE, ACTIVE, this::activate);
+ private final UserTaskTransition T_ACTIVE_RESERVED = new DefaultUserTransition(CLAIM, ACTIVE, RESERVED, this::claim);
+ private final UserTaskTransition T_ACTIVE_SKIPPED = new DefaultUserTransition(SKIP, ACTIVE, OBSOLETE, this::skip);
+ private final UserTaskTransition T_ACTIVE_ERROR = new DefaultUserTransition(FAIL, ACTIVE, ERROR, this::fail);
+ private final UserTaskTransition T_RESERVED_ACTIVE = new DefaultUserTransition(RELEASE, RESERVED, ACTIVE, this::release);
+ private final UserTaskTransition T_RESERVED_COMPLETED = new DefaultUserTransition(COMPLETE, RESERVED, COMPLETED, this::complete);
+ private final UserTaskTransition T_RESERVED_SKIPPED = new DefaultUserTransition(SKIP, RESERVED, OBSOLETE, this::skip);
+ private final UserTaskTransition T_RESERVED_ERROR = new DefaultUserTransition(FAIL, RESERVED, ERROR, this::fail);
private List<UserTaskTransition> transitions;
@@ -53,58 +72,140 @@ public class DefaultUserTaskLifeCycle implements UserTaskLifeCycle {
transitions = List.of(
T_NEW_ACTIVE,
T_ACTIVE_RESERVED,
+ T_ACTIVE_SKIPPED,
+ T_ACTIVE_ERROR,
T_RESERVED_ACTIVE,
- T_ACTIVE_COMPLETED,
T_RESERVED_COMPLETED,
- T_ACTIVE_SKIPPED,
T_RESERVED_SKIPPED,
T_RESERVED_ERROR);
}
@Override
- public Optional<UserTaskTransitionToken> transition(UserTaskInstance userTaskInstance, UserTaskTransitionToken transition) {
- return Optional.empty();
+ public List<UserTaskTransition> allowedTransitions(UserTaskInstance userTaskInstance) {
+ return transitions.stream().filter(t -> t.source().equals(userTaskInstance.getStatus())).toList();
}
@Override
- public UserTaskTransitionToken newTransitionToken(String transitionId, UserTaskInstance userTaskInstance, Map<String, Object> data) {
- UserTaskState state = userTaskInstance.getStatus();
- UserTaskTransition transition = transitions.stream().filter(e -> e.source().equals(state) && e.id().equals(transitionId)).findAny()
- .orElseThrow(() -> new RuntimeException("Invalid transition " + transitionId + " from " + state));
- return new DefaultUserTaskTransitionToken(transition, data);
+ public Optional<UserTaskTransitionToken> transition(UserTaskInstance userTaskInstance, UserTaskTransitionToken userTaskTransitionToken, IdentityProvider identityProvider) {
+ checkPermission(userTaskInstance, identityProvider);
+ UserTaskTransition transition = transitions.stream()
+ .filter(t -> t.source().equals(userTaskInstance.getStatus()) && t.id().equals(userTaskTransitionToken.transitionId()))
+ .findFirst()
+ .orElseThrow(() -> new UserTaskTransitionException("Invalid transition from " + userTaskInstance.getStatus()));
+ return transition.executor().execute(userTaskInstance, userTaskTransitionToken, identityProvider);
}
@Override
public UserTaskTransitionToken newCompleteTransitionToken(UserTaskInstance userTaskInstance, Map<String, Object> data) {
- return newTransitionToken("complete", userTaskInstance, data);
+ return newTransitionToken(COMPLETE, userTaskInstance.getStatus(), data);
}
@Override
public UserTaskTransitionToken newAbortTransitionToken(UserTaskInstance userTaskInstance, Map<String, Object> data) {
- return newTransitionToken("fail", userTaskInstance, data);
+ return newTransitionToken(FAIL, userTaskInstance.getStatus(), data);
}
- public static Optional<UserTaskTransitionToken> activate(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ @Override
+ public UserTaskTransitionToken newTransitionToken(String transitionId, UserTaskInstance userTaskInstance, Map<String, Object> data) {
+ return newTransitionToken(transitionId, userTaskInstance.getStatus(), data);
+ }
+
+ public UserTaskTransitionToken newTransitionToken(String transitionId, UserTaskState state, Map<String, Object> data) {
+ UserTaskTransition transition = transitions.stream().filter(e -> e.source().equals(state) && e.id().equals(transitionId)).findAny()
+ .orElseThrow(() -> new RuntimeException("Invalid transition " + transitionId + " from " + state));
+ return new DefaultUserTaskTransitionToken(transition.id(), transition.source(), transition.target(), data);
+ }
+
+ public Optional<UserTaskTransitionToken> activate(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ String user = assignStrategy(userTaskInstance, identityProvider);
+ if (user != null) {
+ return Optional.of(newTransitionToken(CLAIM, ACTIVE, Map.of(PARAMETER_USER, user)));
+ }
return Optional.empty();
}
- public static Optional<UserTaskTransitionToken> claim(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ public Optional<UserTaskTransitionToken> claim(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ if (userTaskInstance instanceof DefaultUserTaskInstance defaultUserTaskInstance) {
+ if (token.data().containsKey(PARAMETER_USER)) {
+ defaultUserTaskInstance.setActuaOwner((String) token.data().get(PARAMETER_USER));
+ } else {
+ defaultUserTaskInstance.setActuaOwner(identityProvider.getName());
+ }
+ }
return Optional.empty();
}
- public static Optional<UserTaskTransitionToken> release(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ public Optional<UserTaskTransitionToken> release(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ if (userTaskInstance instanceof DefaultUserTaskInstance defaultUserTaskInstance) {
+ defaultUserTaskInstance.setActuaOwner(null);
+ }
return Optional.empty();
}
- public static Optional<UserTaskTransitionToken> complete(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ public Optional<UserTaskTransitionToken> complete(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ token.data().forEach(userTaskInstance::setOutput);
return Optional.empty();
}
- public static Optional<UserTaskTransitionToken> skip(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ public Optional<UserTaskTransitionToken> skip(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ if (token.data().containsKey(PARAMETER_NOTIFY)) {
+ userTaskInstance.getMetadata().put(PARAMETER_NOTIFY, token.data().get(PARAMETER_NOTIFY));
+ }
return Optional.empty();
}
- public static Optional<UserTaskTransitionToken> fail(UserTaskInstance userTaskInstance, UserTaskTransitionToken token) {
+ public Optional<UserTaskTransitionToken> fail(UserTaskInstance userTaskInstance, UserTaskTransitionToken token, IdentityProvider identityProvider) {
+ if (token.data().containsKey(PARAMETER_NOTIFY)) {
+ userTaskInstance.getMetadata().put(PARAMETER_NOTIFY, token.data().get(PARAMETER_NOTIFY));
+ }
return Optional.empty();
}
+
+ private String assignStrategy(UserTaskInstance userTaskInstance, IdentityProvider identityProvider) {
+ UserTaskAssignmentStrategy assignmentStrategy = userTaskInstance.getUserTask().getAssignmentStrategy();
+ return assignmentStrategy.computeAssigment(userTaskInstance, identityProvider).orElse(null);
+ }
+
+ private void checkPermission(UserTaskInstance userTaskInstance, IdentityProvider identityProvider) {
+ String user = identityProvider.getName();
+ Collection<String> roles = identityProvider.getRoles();
+
+ if (WORKFLOW_ENGINE_USER.equals(user)) {
+ return;
+ }
+
+ // first we check admins
+ Set<String> adminUsers = userTaskInstance.getAdminUsers();
+ if (adminUsers.contains(user)) {
+ return;
+ }
+
+ Set<String> userAdminGroups = new HashSet<>(userTaskInstance.getAdminGroups());
+ userAdminGroups.retainAll(roles);
+ if (!userAdminGroups.isEmpty()) {
+ return;
+ }
+
+ if (userTaskInstance.getActualOwner() != null && userTaskInstance.getActualOwner().equals(user)) {
+ return;
+ }
+
+ if (List.of(INACTIVE, ACTIVE).contains(userTaskInstance.getStatus())) {
+ // there is no user
+ Set<String> users = new HashSet<>(userTaskInstance.getPotentialUsers());
+ users.removeAll(userTaskInstance.getExcludedUsers());
+ if (users.contains(identityProvider.getName())) {
+ return;
+ }
+
+ Set<String> userPotGroups = new HashSet<>(userTaskInstance.getPotentialGroups());
+ userPotGroups.retainAll(roles);
+ if (!userPotGroups.isEmpty()) {
+ return;
+ }
+ }
+
+ throw new NotAuthorizedException("user " + user + " with roles " + roles + " not autorized to perform an operation on user task " + userTaskInstance.getId());
+ }
+
}
diff --git a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java
index 303d9d8e80..f8cfd7733f 100644
--- a/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java
+++ b/jbpm/jbpm-usertask/src/main/java/org/kie/kogito/usertask/impl/lifecycle/DefaultUserTaskTransitionToken.java
@@ -20,21 +20,25 @@ package org.kie.kogito.usertask.impl.lifecycle;
import java.util.Map;
-import org.kie.kogito.usertask.lifecycle.UserTaskTransition;
+import org.kie.kogito.usertask.lifecycle.UserTaskState;
import org.kie.kogito.usertask.lifecycle.UserTaskTransitionToken;
public class DefaultUserTaskTransitionToken implements UserTaskTransitionToken {
- private UserTaskTransition transition;
+ private String transition;
private Map<String, Object> data;
+ private UserTaskState source;
+ private UserTaskState target;
- public DefaultUserTaskTransitionToken(UserTaskTransition transition, Map<String, Object> data) {
+ public DefaultUserTaskTransitionToken(String transition, UserTaskState source, UserTaskState target, Map<String, Object> data) {
this.transition = transition;
+ this.source = source;
+ this.target = target;
this.data = data;
}
@Override
- public UserTaskTransition transition() {
+ public String transitionId() {
return transition;
}
@@ -43,4 +47,14 @@ public class DefaultUserTaskTransitionToken implements UserTaskTransitionToken {
return data;
}
+ @Override
+ public UserTaskState source() {
+ return source;
+ }
+
+ @Override
+ public UserTaskState target() {
+ return target;
+ }
+
}
diff --git a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/DefaultKogitoWorkItemHandler.java b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/DefaultKogitoWorkItemHandler.java
index 993fb8f8ad..21ba12d2d1 100644
--- a/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/DefaultKogitoWorkItemHandler.java
+++ b/jbpm/process-workitems/src/main/java/org/kie/kogito/process/workitems/impl/DefaultKogitoWorkItemHandler.java
@@ -45,6 +45,11 @@ public class DefaultKogitoWorkItemHandler implements KogitoWorkItemHandler {
public static final String TRANSITION_ACTIVATE = "activate";
public static final String TRANSITION_SKIP = "skip";
+ public static final WorkItemPhaseState INITIALIZED = WorkItemPhaseState.initialized();
+ public static final WorkItemPhaseState COMPLETED = WorkItemPhaseState.of("Completed", WorkItemTerminationType.COMPLETE);
+ public static final WorkItemPhaseState ABORTED = WorkItemPhaseState.of("Aborted", WorkItemTerminationType.ABORT);
+ public static final WorkItemPhaseState ACTIVATED = WorkItemPhaseState.of("Activated");
+
private static Logger LOG = LoggerFactory.getLogger(DefaultKogitoWorkItemHandler.class);
protected Application application;
@@ -60,15 +65,10 @@ public class DefaultKogitoWorkItemHandler implements KogitoWorkItemHandler {
}
public WorkItemLifeCycle initialize() {
- WorkItemPhaseState initialized = WorkItemPhaseState.initialized();
- WorkItemPhaseState completed = WorkItemPhaseState.of("Completed", WorkItemTerminationType.COMPLETE);
- WorkItemPhaseState aborted = WorkItemPhaseState.of("Aborted", WorkItemTerminationType.ABORT);
- WorkItemPhaseState activated = WorkItemPhaseState.of("Activated");
-
- DefaultWorkItemLifeCyclePhase complete = new DefaultWorkItemLifeCyclePhase(TRANSITION_COMPLETE, activated, completed, this::completeWorkItemHandler);
- DefaultWorkItemLifeCyclePhase abort = new DefaultWorkItemLifeCyclePhase(TRANSITION_ABORT, activated, aborted, this::abortWorkItemHandler);
- DefaultWorkItemLifeCyclePhase active = new DefaultWorkItemLifeCyclePhase(TRANSITION_ACTIVATE, initialized, activated, this::activateWorkItemHandler);
- DefaultWorkItemLifeCyclePhase skip = new DefaultWorkItemLifeCyclePhase(TRANSITION_SKIP, activated, completed, this::skipWorkItemHandler);
+ DefaultWorkItemLifeCyclePhase complete = new DefaultWorkItemLifeCyclePhase(TRANSITION_COMPLETE, ACTIVATED, COMPLETED, this::completeWorkItemHandler);
+ DefaultWorkItemLifeCyclePhase abort = new DefaultWorkItemLifeCyclePhase(TRANSITION_ABORT, ACTIVATED, ABORTED, this::abortWorkItemHandler);
+ DefaultWorkItemLifeCyclePhase active = new DefaultWorkItemLifeCyclePhase(TRANSITION_ACTIVATE, INITIALIZED, ACTIVATED, this::activateWorkItemHandler);
+ DefaultWorkItemLifeCyclePhase skip = new DefaultWorkItemLifeCyclePhase(TRANSITION_SKIP, ACTIVATED, COMPLETED, this::skipWorkItemHandler);
return new DefaultWorkItemLifeCycle(active, skip, abort, complete);
}
@@ -83,17 +83,17 @@ public class DefaultKogitoWorkItemHandler implements KogitoWorkItemHandler {
@Override
public WorkItemTransition startingTransition(Map<String, Object> data, Policy... policies) {
- return workItemLifeCycle.newTransition("activate", null, data, policies);
+ return workItemLifeCycle.newTransition(TRANSITION_ACTIVATE, null, data, policies);
}
@Override
public WorkItemTransition abortTransition(String phaseStatus, Policy... policies) {
- return workItemLifeCycle.newTransition("abort", phaseStatus, emptyMap(), policies);
+ return workItemLifeCycle.newTransition(TRANSITION_ABORT, phaseStatus, emptyMap(), policies);
}
@Override
public WorkItemTransition completeTransition(String phaseStatus, Map<String, Object> data, Policy... policies) {
- return workItemLifeCycle.newTransition("complete", phaseStatus, data, policies);
+ return workItemLifeCycle.newTransition(TRANSITION_COMPLETE, phaseStatus, data, policies);
}
@Override
@@ -121,11 +121,11 @@ public class DefaultKogitoWorkItemHandler implements KogitoWorkItemHandler {
return Optional.empty();
}
- public Optional<WorkItemTransition> abortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) {
+ public Optional<WorkItemTransition> completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) {
return Optional.empty();
}
- public Optional<WorkItemTransition> completeWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) {
+ public Optional<WorkItemTransition> abortWorkItemHandler(KogitoWorkItemManager manager, KogitoWorkItemHandler handler, KogitoWorkItem workitem, WorkItemTransition transition) {
return Optional.empty();
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java
index 39efe72339..5284672e0a 100644
--- a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java
+++ b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/PublishEventIT.java
@@ -149,8 +149,11 @@ public class PublishEventIT extends AbstractCodegenIT {
}
- private Optional<UserTaskInstanceStateDataEvent> findUserTaskInstanceEvent(List<DataEvent<?>> events, String status) {
- return events.stream().filter(UserTaskInstanceStateDataEvent.class::isInstance).map(e -> (UserTaskInstanceStateDataEvent) e).filter(e -> status.equals(e.getData().getState())).findAny();
+ private Optional<UserTaskInstanceStateDataEvent> findUserTaskInstanceEvent(List<DataEvent<?>> events, String taskName, String status) {
+ return events.stream().filter(UserTaskInstanceStateDataEvent.class::isInstance)
+ .map(e -> (UserTaskInstanceStateDataEvent) e)
+ .filter(e -> status.equals(e.getData().getState()) && e.getData().getUserTaskName().equals(taskName))
+ .findAny();
}
private Optional<DataEvent<?>> findProcessInstanceEvent(List<DataEvent<?>> events, int state) {
@@ -205,7 +208,7 @@ public class PublishEventIT extends AbstractCodegenIT {
List<ProcessInstanceNodeEventBody> left = findNodeInstanceEvents(events, 2);
assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("StartNode");
- Optional<UserTaskInstanceStateDataEvent> userFirstTask = findUserTaskInstanceEvent(events, "Ready");
+ Optional<UserTaskInstanceStateDataEvent> userFirstTask = findUserTaskInstanceEvent(events, "FirstTask", "Ready");
assertThat(userFirstTask).isPresent();
assertUserTaskInstanceEvent(userFirstTask.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task");
@@ -226,11 +229,12 @@ public class PublishEventIT extends AbstractCodegenIT {
left = findNodeInstanceEvents(events, 1);
assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("HumanTaskNode");
- Optional<UserTaskInstanceStateDataEvent> firstUserTaskInstance = findUserTaskInstanceEvent(events, "Ready");
- Optional<UserTaskInstanceStateDataEvent> secondUserTaskInstance = findUserTaskInstanceEvent(events, "Completed");
+ Optional<UserTaskInstanceStateDataEvent> firstUserTaskInstance = findUserTaskInstanceEvent(events, "SecondTask", "Ready");
+ // we completed through the work item handler so the user task is really obsolete
+ Optional<UserTaskInstanceStateDataEvent> secondUserTaskInstance = findUserTaskInstanceEvent(events, "FirstTask", "Obsolete");
assertUserTaskInstanceEvent(firstUserTaskInstance.get(), "SecondTask", null, "1", "Ready", "UserTasksProcess", "Second Task");
- assertUserTaskInstanceEvent(secondUserTaskInstance.get(), "FirstTask", null, "1", "Completed", "UserTasksProcess", "First Task");
+ assertUserTaskInstanceEvent(secondUserTaskInstance.get(), "FirstTask", null, "1", "Obsolete", "UserTasksProcess", "First Task");
workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
@@ -252,7 +256,7 @@ public class PublishEventIT extends AbstractCodegenIT {
left = findNodeInstanceEvents(events, 2);
assertThat(left).hasSize(2).extractingResultOf("getNodeType").containsOnly("HumanTaskNode", "EndNode");
- assertUserTaskInstanceEvent(events.get(0), "SecondTask", null, "1", "Completed", "UserTasksProcess", "Second Task");
+ assertUserTaskInstanceEvent(events.get(0), "SecondTask", null, "1", "Obsolete", "UserTasksProcess", "Second Task");
}
@Test
@@ -285,7 +289,7 @@ public class PublishEventIT extends AbstractCodegenIT {
List<ProcessInstanceNodeEventBody> triggered = findNodeInstanceEvents(events, 1);
assertThat(triggered).hasSize(2).extractingResultOf("getNodeName").containsOnly("StartProcess", "First Task");
- Optional<UserTaskInstanceStateDataEvent> event = findUserTaskInstanceEvent(events, "Ready");
+ Optional<UserTaskInstanceStateDataEvent> event = findUserTaskInstanceEvent(events, "FirstTask", "Ready");
assertThat(event).isPresent();
assertUserTaskInstanceEvent(event.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task");
@@ -343,7 +347,7 @@ public class PublishEventIT extends AbstractCodegenIT {
List<ProcessInstanceNodeEventBody> left = findNodeInstanceEvents(events, 2);
assertThat(left).hasSize(1).extractingResultOf("getNodeType").containsOnly("StartNode");
- Optional<UserTaskInstanceStateDataEvent> userTask = findUserTaskInstanceEvent(events, "Ready");
+ Optional<UserTaskInstanceStateDataEvent> userTask = findUserTaskInstanceEvent(events, "FirstTask", "Ready");
assertThat(userTask).isPresent();
assertUserTaskInstanceEvent(userTask.get(), "FirstTask", null, "1", "Ready", "UserTasksProcess", "First Task");
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/UserTaskIT.java b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/UserTaskIT.java
index dc15d15ae9..7a0e493fa4 100644
--- a/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/UserTaskIT.java
+++ b/kogito-codegen-modules/kogito-codegen-processes-integration-tests/src/test/java/org/kie/kogito/codegen/tests/UserTaskIT.java
@@ -26,7 +26,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.kie.kogito.Application;
import org.kie.kogito.Model;
@@ -38,31 +37,32 @@ import org.kie.kogito.codegen.data.Person;
import org.kie.kogito.internal.process.event.DefaultKogitoProcessEventListener;
import org.kie.kogito.internal.process.event.ProcessWorkItemTransitionEvent;
import org.kie.kogito.internal.process.runtime.KogitoProcessInstance;
-import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler;
import org.kie.kogito.internal.process.workitem.NotAuthorizedException;
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.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler;
+import org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandlerProcessListener;
import org.kie.kogito.process.Process;
import org.kie.kogito.process.ProcessConfig;
import org.kie.kogito.process.ProcessInstance;
import org.kie.kogito.process.Processes;
import org.kie.kogito.process.VariableViolationException;
import org.kie.kogito.process.WorkItem;
+import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTasks;
+import org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
-import static org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler.ACTIVATED;
-import static org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler.RESERVED;
-import static org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler.TRANSITION_ACTIVATED_CLAIM;
-import static org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler.TRANSITION_RESERVED_COMPLETE;
-import static org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler.TRANSITION_RESERVED_RELEASE;
-
-@Disabled
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle.CLAIM;
+import static org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle.COMPLETE;
+import static org.kie.kogito.usertask.impl.lifecycle.DefaultUserTaskLifeCycle.RELEASE;
+
public class UserTaskIT extends AbstractCodegenIT {
private Policy securityPolicy = SecurityPolicy.of("john", emptyList());
@@ -86,6 +86,9 @@ public class UserTaskIT extends AbstractCodegenIT {
}
});
+ // we wired user tasks and processes
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
+
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -100,28 +103,55 @@ public class UserTaskIT extends AbstractCodegenIT {
List<WorkItem> workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
assertThat(workItems.get(0).getName()).isEqualTo("FirstTask");
- WorkItem wi = workItems.get(0);
+ WorkItem wi_1 = workItems.get(0);
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+
+ UserTask userTask_1 = userTasks.userTaskById(getUserTaskId(wi_1.getExternalReferenceId()));
+ UserTaskInstance userTaskInstance_1 = userTask_1.instances().findById(getUserTaskInstanceId(wi_1.getExternalReferenceId())).get();
+ assertThat(userTaskInstance_1).isNotNull();
+
+ List<UserTaskInstance> userTaskList = userTasks.instances().findByIdentity(IdentityProviders.of("mary"));
+ assertThat(userTaskList).hasSize(1);
+
+ userTaskList = userTask_1.instances().findByIdentity(IdentityProviders.of("invalid"));
+ assertThat(userTaskList).hasSize(0);
+
+ userTaskList = userTask_1.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskList).hasSize(1);
+
+ userTaskInstance_1 = userTaskList.get(0);
+ userTaskInstance_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ userTaskInstance_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
assertThat(workItems.get(0).getName()).isEqualTo("SecondTask");
+ WorkItem wi_2 = workItems.get(0);
+
+ UserTask userTask_2 = userTasks.userTaskById(getUserTaskId(wi_2.getExternalReferenceId()));
+ UserTaskInstance userTaskInstance_2 = userTask_2.instances().findById(getUserTaskInstanceId(wi_2.getExternalReferenceId())).get();
+ assertThat(userTaskInstance_2).isNotNull();
+
+ userTaskList = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskList).hasSize(1);
+
+ userTaskInstance_1 = userTaskList.get(0);
+ userTaskInstance_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
- processInstance.completeWorkItem(workItems.get(0).getId(), null, securityPolicy);
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
- assertThat(workItemTransitionEvents).hasSize(12);
+ assertThat(workItemTransitionEvents).hasSize(8);
+ }
+
+ private String getUserTaskInstanceId(String externalReference) {
+ return externalReference.split(":")[1];
+ }
+
+ private String getUserTaskId(String externalReference) {
+ return externalReference.split(":")[0];
}
@Test
@@ -129,7 +159,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -146,16 +176,12 @@ public class UserTaskIT extends AbstractCodegenIT {
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
@@ -164,9 +190,11 @@ public class UserTaskIT extends AbstractCodegenIT {
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- handler = getWorkItemHandler(p, wi);
- transition = handler.completeTransition(workItems.get(0).getPhaseStatus(), parameters, securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ ut_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
+
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
}
@@ -175,7 +203,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -193,32 +221,20 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(wi.getName()).isEqualTo("FirstTask");
assertThat(wi.getResults()).isEmpty();
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), Map.of("ACTUAL_OWNER", "john", "test", "value"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
-
- assertThat(wi.getResults()).hasSize(1)
- .containsEntry("test", "value");
-
- handler = getWorkItemHandler(p, wi);
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
+ ut_1.transition(COMPLETE, Map.of("test", "value"), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ assertThat(ut_2.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
processInstance.abort();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
@@ -229,7 +245,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -245,43 +261,26 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
-
- WorkItemTransition claim = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), claim);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+ assertThat(ut_1.getActualOwner()).isEqualTo("john");
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
+ ut_1.transition(RELEASE, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.ACTIVE);
+ assertThat(ut_1.getActualOwner()).isNull();
- WorkItemTransition release = handler.newTransition(TRANSITION_RESERVED_RELEASE.id(), wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), release);
+ ut_1.transition(DefaultUserTaskLifeCycle.CLAIM, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+ assertThat(ut_1.getActualOwner()).isEqualTo("john");
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
- assertThat(wi.getResults()).isEmpty();
-
- claim = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), claim);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
- WorkItemTransition transition = handler.completeTransition(wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), transition);
+ ut_1.transition(DefaultUserTaskLifeCycle.COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
workItems = processInstance.workItems(securityPolicy);
@@ -289,11 +288,14 @@ public class UserTaskIT extends AbstractCodegenIT {
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ assertThat(ut_2.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
processInstance.abort();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
+ assertThat(userTasks.instances().findByIdentity(IdentityProviders.of("john"))).hasSize(0);
}
@Test
@@ -301,6 +303,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
final List<String> workItemTransitionEvents = new ArrayList<>();
app.config().get(ProcessConfig.class).processEventListeners().listeners().add(new DefaultKogitoProcessEventListener() {
@@ -330,37 +333,30 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), Map.of("ACTUAL_OWNER", "john", "test", "value"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).hasSize(1)
- .containsEntry("test", "value");
-
- transition = handler.completeTransition(wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.ACTIVE);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.COMPLETED);
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ assertThat(ut_2.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
processInstance.abort();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
- assertThat(workItemTransitionEvents).hasSize(12);
+ assertThat(workItemTransitionEvents).hasSize(8);
}
@Test
@@ -368,7 +364,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -384,7 +380,7 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
final String wiId = wi.getId();
@@ -394,11 +390,13 @@ public class UserTaskIT extends AbstractCodegenIT {
List<WorkItem> securedWorkItems = processInstance.workItems(SecurityPolicy.of(identity));
assertThat(securedWorkItems).isEmpty();
- assertThatExceptionOfType(WorkItemNotFoundException.class).isThrownBy(() -> processInstance.workItem(wiId, SecurityPolicy.of(identity)));
+ assertThatExceptionOfType(NotAuthorizedException.class).isThrownBy(() -> processInstance.workItem(wiId, SecurityPolicy.of(identity)));
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition claimKelly = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "kelly"), SecurityPolicy.of(identity));
- assertThatExceptionOfType(NotAuthorizedException.class).isThrownBy(() -> processInstance.transitionWorkItem(wiId, claimKelly));
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance utInvalid = userTaskInstances.get(0);
+ assertThatExceptionOfType(NotAuthorizedException.class).isThrownBy(() -> utInvalid.transition(CLAIM, emptyMap(), IdentityProviders.of("invalid")));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
@@ -406,32 +404,32 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- WorkItemTransition claimJohn = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(wiId, claimJohn);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).isEmpty();
- WorkItemTransition completeJohn = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(wiId, completeJohn);
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ assertThat(ut_2.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+
processInstance.abort();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
+ assertThat(userTasks.instances().findByIdentity(IdentityProviders.of("john"))).hasSize(0);
}
@Test
@@ -439,7 +437,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("approvals");
Model m = p.createModel();
@@ -458,10 +456,12 @@ public class UserTaskIT extends AbstractCodegenIT {
List<WorkItem> workItems = processInstance.workItems(policy);
assertThat(workItems).hasSize(1);
- WorkItem wi = workItems.get(0);
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ActorId", "manager"), policy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("manager"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("manager"));
+
// actual owner of the first task is excluded owner on the second task so won't find it
workItems = processInstance.workItems(policy);
assertThat(workItems).isEmpty();
@@ -471,15 +471,12 @@ public class UserTaskIT extends AbstractCodegenIT {
workItems = processInstance.workItems(policy);
assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), policy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
- workItems = processInstance.workItems(policy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), emptyMap(), policy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("admin", singletonList("managers")));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ ut_2.transition(CLAIM, emptyMap(), IdentityProviders.of("admin", singletonList("managers")));
+ ut_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("admin", singletonList("managers")));
assertThat(processInstance.status()).isEqualTo(KogitoProcessInstance.STATE_COMPLETED);
}
@@ -489,7 +486,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("approvals");
Model m = p.createModel();
@@ -519,13 +516,13 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
assertThat(workItems).hasSize(1);
- WorkItem wi = workItems.get(0);
-
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), policy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
- processInstance.completeWorkItem(workItems.get(0).getId(), null, policy);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(identity);
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), identity);
+ ut_1.transition(COMPLETE, emptyMap(), identity);
assertThat(processInstance.status()).isEqualTo(KogitoProcessInstance.STATE_COMPLETED);
}
@@ -535,7 +532,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -547,30 +544,20 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- List<WorkItem> workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- WorkItem wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
-
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- workItems = processInstance.workItems(securityPolicy);
+ List<WorkItem> workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
+ WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
String firstSecondTaskNodeInstanceId = wi.getNodeInstanceId();
@@ -582,11 +569,14 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
// since it was triggered again it must have different node instance id
assertThat(wi.getNodeInstanceId()).isNotEqualTo(firstSecondTaskNodeInstanceId);
- transition = handler.completeTransition(workItems.get(0).getPhaseStatus(), parameters, securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ ut_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
}
@@ -596,7 +586,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -613,18 +603,14 @@ public class UserTaskIT extends AbstractCodegenIT {
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
@@ -632,8 +618,7 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
-
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
String firstSecondTaskNodeInstanceId = wi.getNodeInstanceId();
@@ -645,12 +630,14 @@ public class UserTaskIT extends AbstractCodegenIT {
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
// since it was retriggered it must have different node instance id
assertThat(wi.getNodeInstanceId()).isNotEqualTo(firstSecondTaskNodeInstanceId);
- transition = handler.completeTransition(workItems.get(0).getPhaseStatus(), parameters, securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), transition);
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ ut_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
}
@@ -660,7 +647,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -676,58 +663,36 @@ public class UserTaskIT extends AbstractCodegenIT {
assertThat(workItems).hasSize(1);
WorkItem wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), Map.of("ACTUAL_OWNER", "john", "test", "value"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+ ut_1.transition(RELEASE, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.ACTIVE);
+ assertThat(ut_1.getActualOwner()).isNull();
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ assertThat(ut_1.getActualOwner()).isEqualTo("john");
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
-
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).hasSize(1)
- .containsEntry("test", "value");
-
- transition = handler.newTransition(TRANSITION_RESERVED_RELEASE.id(), wi.getPhaseStatus(), emptyMap(), securityPolicy);
-
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(ACTIVATED.getName());
- assertThat(wi.getResults()).hasSize(0);
-
- transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), Map.of("ACTUAL_OWNER", "john", "test", "value"), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), transition);
- assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
- assertThat(wi.getResults()).hasSize(1)
- .containsEntry("test", "value");
-
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), emptyMap(), securityPolicy);
- processInstance.transitionWorkItem(wi.getId(), transition);
- assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ACTIVE);
-
workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
wi = workItems.get(0);
assertThat(wi.getName()).isEqualTo("SecondTask");
- assertThat(wi.getPhaseStatus()).isEqualTo(RESERVED.getName());
+ assertThat(wi.getPhaseStatus()).isEqualTo(UserTaskKogitoWorkItemHandler.ACTIVATED.getName());
assertThat(wi.getResults()).isEmpty();
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ assertThat(ut_2.getStatus()).isEqualTo(DefaultUserTaskLifeCycle.RESERVED);
+
processInstance.abort();
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_ABORTED);
}
@@ -738,7 +703,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval-with-readonly-variable-tags.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Class<?> resourceClazz = Class.forName("org.acme.travels.ApprovalsModel", true, testClassLoader());
assertThat(resourceClazz).isNotNull();
@@ -774,7 +739,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval-with-internal-variable-tags.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Class<?> resourceClazz = Class.forName("org.acme.travels.ApprovalsModel", true, testClassLoader());
assertThat(resourceClazz).isNotNull();
// internal variables are not exposed on the model
@@ -800,7 +765,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval-with-required-variable-tags.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("approvals");
Model m = p.createModel();
@@ -818,7 +783,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/approval-with-io-variable-tags.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Class<?> modelClazz = Class.forName("org.acme.travels.ApprovalsModel", true, testClassLoader());
assertThat(modelClazz).isNotNull();
assertThat(modelClazz.getDeclaredField("decision")).isNotNull();
@@ -857,7 +822,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTaskWithIOexpression.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTask");
Model m = p.createModel();
@@ -888,7 +853,7 @@ public class UserTaskIT extends AbstractCodegenIT {
Application app = generateCodeProcessesOnly("usertask/UserTasksProcess.bpmn2");
assertThat(app).isNotNull();
-
+ app.config().get(UserTaskConfig.class).userTaskEventListeners().listeners().add(new UserTaskKogitoWorkItemHandlerProcessListener(app.get(Processes.class)));
Process<? extends Model> p = app.get(Processes.class).processById("UserTasksProcess");
Model m = p.createModel();
@@ -912,24 +877,23 @@ public class UserTaskIT extends AbstractCodegenIT {
List<WorkItem> workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
assertThat(workItems.get(0).getName()).isEqualTo("FirstTask");
- WorkItem wi = workItems.get(0);
- KogitoWorkItemHandler handler = getWorkItemHandler(p, wi);
- WorkItemTransition transition = handler.newTransition(TRANSITION_ACTIVATED_CLAIM.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
-
- workItems = processInstance.workItems(securityPolicy);
- assertThat(workItems).hasSize(1);
- wi = workItems.get(0);
- assertThat(wi.getName()).isEqualTo("FirstTask");
- transition = handler.newTransition(TRANSITION_RESERVED_COMPLETE.id(), wi.getPhaseStatus(), singletonMap("ACTUAL_OWNER", "john"), securityPolicy);
- processInstance.transitionWorkItem(workItems.get(0).getId(), transition);
+ UserTasks userTasks = app.get(UserTasks.class);
+ List<UserTaskInstance> userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_1 = userTaskInstances.get(0);
+ ut_1.transition(CLAIM, emptyMap(), IdentityProviders.of("john"));
+ ut_1.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
workItems = processInstance.workItems(securityPolicy);
assertThat(workItems).hasSize(1);
assertThat(workItems.get(0).getName()).isEqualTo("SecondTask");
- processInstance.completeWorkItem(workItems.get(0).getId(), null, securityPolicy);
+ userTaskInstances = userTasks.instances().findByIdentity(IdentityProviders.of("john"));
+ assertThat(userTaskInstances).isNotNull().hasSize(1);
+ UserTaskInstance ut_2 = userTaskInstances.get(0);
+ ut_2.transition(COMPLETE, emptyMap(), IdentityProviders.of("john"));
+
assertThat(processInstance.status()).isEqualTo(ProcessInstance.STATE_COMPLETED);
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
index 71debb2806..86e6bd8053 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessCodegen.java
@@ -42,7 +42,7 @@ import org.jbpm.compiler.canonical.ModelMetaData;
import org.jbpm.compiler.canonical.ProcessMetaData;
import org.jbpm.compiler.canonical.ProcessToExecModelGenerator;
import org.jbpm.compiler.canonical.TriggerMetaData;
-import org.jbpm.compiler.canonical.UserTaskModelMetaData;
+import org.jbpm.compiler.canonical.WorkItemModelMetaData;
import org.jbpm.compiler.xml.XmlProcessReader;
import org.jbpm.compiler.xml.core.SemanticModules;
import org.jbpm.process.core.impl.ProcessImpl;
@@ -288,7 +288,7 @@ public class ProcessCodegen extends AbstractGenerator {
Map<String, InputModelClassGenerator> processIdToInputModelGenerator = new HashMap<>();
Map<String, OutputModelClassGenerator> processIdToOutputModelGenerator = new HashMap<>();
- Map<String, List<UserTaskModelMetaData>> processIdToUserTaskModel = new HashMap<>();
+ Map<String, List<WorkItemModelMetaData>> processIdToWorkItemModel = new HashMap<>();
Map<String, ProcessMetaData> processIdToMetadata = new HashMap<>();
// first we generate all the data classes from variable declarations
@@ -305,10 +305,13 @@ public class ProcessCodegen extends AbstractGenerator {
}
}
- // then we generate user task inputs and outputs if any
+ // then we generate work items task inputs and outputs if any
for (WorkflowProcess workFlowProcess : processes.values()) {
- UserTasksModelClassGenerator utcg = new UserTasksModelClassGenerator(workFlowProcess);
- processIdToUserTaskModel.put(workFlowProcess.getId(), utcg.generate());
+ if (KogitoWorkflowProcess.SW_TYPE.equals(workFlowProcess.getType())) {
+ continue;
+ }
+ WorkItemModelClassGenerator utcg = new WorkItemModelClassGenerator(workFlowProcess);
+ processIdToWorkItemModel.put(workFlowProcess.getId(), utcg.generate());
}
// then we can instantiate the exec model generator
@@ -363,7 +366,7 @@ public class ProcessCodegen extends AbstractGenerator {
applicationCanonicalName());
processResourceGenerator
- .withUserTasks(processIdToUserTaskModel.get(workFlowProcess.getId()))
+ .withWorkItems(processIdToWorkItemModel.get(workFlowProcess.getId()))
.withSignals(metaData.getSignals())
.withTriggers(metaData.isStartable(), metaData.isDynamic(), metaData.getTriggers())
.withTransaction(isTransactionEnabled());
@@ -421,14 +424,14 @@ public class ProcessCodegen extends AbstractGenerator {
mmd.generate());
}
- for (List<UserTaskModelMetaData> utmd : processIdToUserTaskModel.values()) {
+ for (List<WorkItemModelMetaData> utmd : processIdToWorkItemModel.values()) {
- for (UserTaskModelMetaData ut : utmd) {
- storeFile(MODEL_TYPE, UserTasksModelClassGenerator.generatedFilePath(ut.getInputModelClassName()), ut.generateInput());
+ for (WorkItemModelMetaData ut : utmd) {
+ storeFile(MODEL_TYPE, WorkItemModelClassGenerator.generatedFilePath(ut.getInputModelClassName()), ut.generateInput());
- storeFile(MODEL_TYPE, UserTasksModelClassGenerator.generatedFilePath(ut.getOutputModelClassName()), ut.generateOutput());
+ storeFile(MODEL_TYPE, WorkItemModelClassGenerator.generatedFilePath(ut.getOutputModelClassName()), ut.generateOutput());
- storeFile(MODEL_TYPE, UserTasksModelClassGenerator.generatedFilePath(ut.getTaskModelClassName()), ut.generateModel());
+ storeFile(MODEL_TYPE, WorkItemModelClassGenerator.generatedFilePath(ut.getTaskModelClassName()), ut.generateModel());
}
}
@@ -442,7 +445,7 @@ public class ProcessCodegen extends AbstractGenerator {
for (ProcessResourceGenerator resourceGenerator : rgs) {
storeFile(REST_TYPE, resourceGenerator.generatedFilePath(),
resourceGenerator.generate());
- storeFile(MODEL_TYPE, UserTasksModelClassGenerator.generatedFilePath(resourceGenerator.getTaskModelFactoryClassName()), resourceGenerator.getTaskModelFactory());
+ storeFile(MODEL_TYPE, WorkItemModelClassGenerator.generatedFilePath(resourceGenerator.getTaskModelFactoryClassName()), resourceGenerator.getTaskModelFactory());
}
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
index 165477103f..3e2f8765a4 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/ProcessResourceGenerator.java
@@ -34,7 +34,7 @@ import org.drools.codegen.common.rest.RestAnnotator;
import org.drools.util.StringUtils;
import org.jbpm.compiler.canonical.ProcessToExecModelGenerator;
import org.jbpm.compiler.canonical.TriggerMetaData;
-import org.jbpm.compiler.canonical.UserTaskModelMetaData;
+import org.jbpm.compiler.canonical.WorkItemModelMetaData;
import org.jbpm.ruleflow.core.Metadata;
import org.jbpm.ruleflow.core.RuleFlowProcess;
import org.jbpm.workflow.core.node.StartNode;
@@ -88,7 +88,7 @@ public class ProcessResourceGenerator {
private static final String REST_TEMPLATE_NAME = "RestResource";
private static final String REACTIVE_REST_TEMPLATE_NAME = "ReactiveRestResource";
- private static final String REST_USER_TASK_TEMPLATE_NAME = "RestResourceUserTask";
+ private static final String REST_WORK_ITEM_TEMPLATE_NAME = "RestResourceWorkItem";
private static final String REST_SIGNAL_TEMPLATE_NAME = "RestResourceSignal";
private static final String SIGNAL_METHOD_PREFFIX = "signal_";
@@ -109,7 +109,7 @@ public class ProcessResourceGenerator {
private boolean transactionEnabled;
private List<TriggerMetaData> triggers;
- private List<UserTaskModelMetaData> userTasks;
+ private List<WorkItemModelMetaData> workItems;
private Map<String, String> signals;
private CompilationUnit taskModelFactoryUnit;
private String taskModelFactoryClassName;
@@ -134,8 +134,8 @@ public class ProcessResourceGenerator {
this.processClazzName = processfqcn;
}
- public ProcessResourceGenerator withUserTasks(List<UserTaskModelMetaData> userTasks) {
- this.userTasks = userTasks;
+ public ProcessResourceGenerator withWorkItems(List<WorkItemModelMetaData> userTasks) {
+ this.workItems = userTasks;
return this;
}
@@ -211,7 +211,7 @@ public class ProcessResourceGenerator {
taskModelFactoryClass.setName(taskModelFactorySimpleClassName);
typeInterpolations.put("$TaskModelFactory$", taskModelFactoryClassName);
- manageUserTasks(templateBuilder, template, taskModelFactoryClass, index);
+ manageWorkItems(templateBuilder, template, taskModelFactoryClass, index);
typeInterpolations.put("$Clazz$", resourceClazzName);
typeInterpolations.put("$Type$", dataClazzName);
@@ -366,13 +366,13 @@ public class ProcessResourceGenerator {
});
}
- protected void manageUserTasks(TemplatedGenerator.Builder templateBuilder, ClassOrInterfaceDeclaration template,
+ protected void manageWorkItems(TemplatedGenerator.Builder templateBuilder, ClassOrInterfaceDeclaration template,
ClassOrInterfaceDeclaration taskModelFactoryClass, AtomicInteger index) {
- if (userTasks != null && !userTasks.isEmpty()) {
+ if (workItems != null && !workItems.isEmpty()) {
- CompilationUnit userTaskClazz = templateBuilder.build(context, REST_USER_TASK_TEMPLATE_NAME).compilationUnitOrThrow();
+ CompilationUnit workItemClazz = templateBuilder.build(context, REST_WORK_ITEM_TEMPLATE_NAME).compilationUnitOrThrow();
- ClassOrInterfaceDeclaration userTaskTemplate = userTaskClazz
+ ClassOrInterfaceDeclaration userTaskTemplate = workItemClazz
.findFirst(ClassOrInterfaceDeclaration.class)
.orElseThrow(() -> new NoSuchElementException("Compilation unit doesn't contain a class or interface declaration!"));
@@ -381,8 +381,8 @@ public class ProcessResourceGenerator {
.orElseThrow(IllegalStateException::new);
SwitchStmt switchExpr = taskModelFactoryMethod.getBody().map(b -> b.findFirst(SwitchStmt.class).orElseThrow(IllegalStateException::new)).orElseThrow(IllegalStateException::new);
- for (UserTaskModelMetaData userTask : userTasks) {
- String methodSuffix = sanitizeName(userTask.getName()) + "_" + index.getAndIncrement();
+ for (WorkItemModelMetaData workItem : workItems) {
+ String methodSuffix = sanitizeName(workItem.getName()) + "_" + index.getAndIncrement();
userTaskTemplate.findAll(MethodDeclaration.class).forEach(md -> {
MethodDeclaration cloned = md.clone();
template.addMethod(cloned.getName() + "_" + methodSuffix, Keyword.PUBLIC)
@@ -392,16 +392,16 @@ public class ProcessResourceGenerator {
.setAnnotations(cloned.getAnnotations());
});
- template.findAll(StringLiteralExpr.class).forEach(s -> interpolateUserTaskStrings(s, userTask));
- template.findAll(ClassOrInterfaceType.class).forEach(c -> interpolateUserTaskTypes(c, userTask));
- template.findAll(NameExpr.class).forEach(c -> interpolateUserTaskNameExp(c, userTask));
- if (!userTask.isAdHoc()) {
+ template.findAll(StringLiteralExpr.class).forEach(s -> interpolateUserTaskStrings(s, workItem));
+ template.findAll(ClassOrInterfaceType.class).forEach(c -> interpolateUserTaskTypes(c, workItem));
+ template.findAll(NameExpr.class).forEach(c -> interpolateUserTaskNameExp(c, workItem));
+ if (!workItem.isAdHoc()) {
template.findAll(MethodDeclaration.class)
.stream()
.filter(md -> md.getNameAsString().equals(SIGNAL_METHOD_PREFFIX + methodSuffix))
.forEach(template::remove);
}
- switchExpr.getEntries().add(0, userTask.getModelSwitchEntry());
+ switchExpr.getEntries().add(0, workItem.getModelSwitchEntry());
}
}
@@ -479,14 +479,14 @@ public class ProcessResourceGenerator {
vv.setString(interpolated);
}
- private void interpolateUserTaskStrings(StringLiteralExpr vv, UserTaskModelMetaData userTask) {
+ private void interpolateUserTaskStrings(StringLiteralExpr vv, WorkItemModelMetaData userTask) {
String s = vv.getValue();
String interpolated = s.replace("$taskName$", sanitizeName(userTask.getName()));
interpolated = interpolated.replace("$taskNodeName$", userTask.getNodeName());
vv.setString(interpolated);
}
- private void interpolateUserTaskNameExp(NameExpr name, UserTaskModelMetaData userTask) {
+ private void interpolateUserTaskNameExp(NameExpr name, WorkItemModelMetaData userTask) {
name.setName(userTask.templateReplacement(name.getNameAsString()));
}
@@ -497,7 +497,7 @@ public class ProcessResourceGenerator {
m.setName(interpolated);
}
- private void interpolateUserTaskTypes(Type t, UserTaskModelMetaData userTask) {
+ private void interpolateUserTaskTypes(Type t, WorkItemModelMetaData userTask) {
if (t.isArrayType()) {
t = t.asArrayType().getElementType();
}
@@ -508,11 +508,11 @@ public class ProcessResourceGenerator {
}
}
- private void interpolateUserTaskTypes(SimpleName returnType, UserTaskModelMetaData userTask) {
+ private void interpolateUserTaskTypes(SimpleName returnType, WorkItemModelMetaData userTask) {
returnType.setIdentifier(userTask.templateReplacement(returnType.getIdentifier()));
}
- private void interpolateUserTaskTypeArguments(NodeList<Type> ta, UserTaskModelMetaData userTask) {
+ private void interpolateUserTaskTypeArguments(NodeList<Type> ta, WorkItemModelMetaData userTask) {
ta.stream().forEach(t -> interpolateUserTaskTypes(t, userTask));
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/UserTasksModelClassGenerator.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/WorkItemModelClassGenerator.java
similarity index 81%
rename from kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/UserTasksModelClassGenerator.java
rename to kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/WorkItemModelClassGenerator.java
index a3850d60f1..e66be467ca 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/UserTasksModelClassGenerator.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/process/WorkItemModelClassGenerator.java
@@ -21,21 +21,21 @@ package org.kie.kogito.codegen.process;
import java.util.List;
import org.jbpm.compiler.canonical.ProcessToExecModelGenerator;
-import org.jbpm.compiler.canonical.UserTaskModelMetaData;
+import org.jbpm.compiler.canonical.WorkItemModelMetaData;
import org.kie.api.definition.process.WorkflowProcess;
-public class UserTasksModelClassGenerator {
+public class WorkItemModelClassGenerator {
private final WorkflowProcess workFlowProcess;
- private List<UserTaskModelMetaData> modelMetaData;
+ private List<WorkItemModelMetaData> modelMetaData;
- public UserTasksModelClassGenerator(WorkflowProcess workFlowProcess) {
+ public WorkItemModelClassGenerator(WorkflowProcess workFlowProcess) {
this.workFlowProcess = workFlowProcess;
}
- public List<UserTaskModelMetaData> generate() {
+ public List<WorkItemModelMetaData> generate() {
// create model class for all variables
- modelMetaData = ProcessToExecModelGenerator.INSTANCE.generateUserTaskModel(workFlowProcess);
+ modelMetaData = ProcessToExecModelGenerator.INSTANCE.generateWorkItemModel(workFlowProcess);
return modelMetaData;
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
index 58bd4a54b6..bd10069d47 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskCodegen.java
@@ -18,10 +18,13 @@
*/
package org.kie.kogito.codegen.usertask;
+import java.io.File;
import java.io.IOException;
import java.io.Reader;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -74,6 +77,7 @@ import static java.util.stream.Collectors.toList;
import static org.kie.kogito.serverless.workflow.utils.ServerlessWorkflowUtils.FAIL_ON_ERROR_PROPERTY;
public class UserTaskCodegen extends AbstractGenerator {
+
private static final String NODE_NAME = "NodeName";
private static final String DESCRIPTION = "Description";
private static final String PRIORITY = "Priority";
@@ -97,6 +101,8 @@ public class UserTaskCodegen extends AbstractGenerator {
TemplatedGenerator templateGenerator;
private List<Work> descriptors;
+ private TemplatedGenerator producerTemplateGenerator;
+ private TemplatedGenerator restTemplateGenerator;
public UserTaskCodegen(KogitoBuildContext context, List<Work> collectedResources) {
super(context, "usertasks");
@@ -106,6 +112,16 @@ public class UserTaskCodegen extends AbstractGenerator {
.withTemplateBasePath("/class-templates/usertask")
.withTargetTypeName(SECTION_CLASS_NAME)
.build(context, "UserTask");
+
+ producerTemplateGenerator = TemplatedGenerator.builder()
+ .withTemplateBasePath("/class-templates/usertask")
+ .withTargetTypeName(SECTION_CLASS_NAME)
+ .build(context, "UserTasksServiceProducer");
+
+ restTemplateGenerator = TemplatedGenerator.builder()
+ .withTemplateBasePath("/class-templates/usertask")
+ .withTargetTypeName(SECTION_CLASS_NAME)
+ .build(context, "RestResourceUserTask");
}
@Override
@@ -125,6 +141,42 @@ public class UserTaskCodegen extends AbstractGenerator {
@Override
protected Collection<GeneratedFile> internalGenerate() {
+ if (descriptors.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<GeneratedFile> generatedFiles = new ArrayList<>();
+ generatedFiles.addAll(generateUserTask());
+ if (context().hasDI()) {
+ generatedFiles.add(generateProducer());
+ }
+
+ if (context().hasRESTForGenerator(this)) {
+ generatedFiles.add(generateRestEndpiont());
+ }
+
+ return generatedFiles;
+ }
+
+ private GeneratedFile generateRestEndpiont() {
+ String packageName = context().getPackageName();
+ CompilationUnit compilationUnit = producerTemplateGenerator.compilationUnitOrThrow("Not rest endpoints template found for user tasks");
+ compilationUnit.setPackageDeclaration(packageName);
+ String className = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class).get().getNameAsString();
+ String urlBase = packageName.replaceAll("\\.", File.separator);
+ return new GeneratedFile(GeneratedFileType.SOURCE, Path.of(urlBase).resolve(className + ".java"), compilationUnit.toString());
+ }
+
+ private GeneratedFile generateProducer() {
+ String packageName = context().getPackageName();
+ CompilationUnit compilationUnit = restTemplateGenerator.compilationUnitOrThrow("No producer template found for user tasks");
+ compilationUnit.setPackageDeclaration(packageName);
+ String className = compilationUnit.findFirst(ClassOrInterfaceDeclaration.class).get().getNameAsString();
+ String urlBase = packageName.replaceAll("\\.", File.separator);
+ return new GeneratedFile(GeneratedFileType.SOURCE, Path.of(urlBase).resolve(className + ".java"), compilationUnit.toString());
+ }
+
+ private List<GeneratedFile> generateUserTask() {
List<GeneratedFile> generatedFiles = new ArrayList<>();
for (Work info : descriptors) {
CompilationUnit unit = templateGenerator.compilationUnit().get();
@@ -171,7 +223,6 @@ public class UserTaskCodegen extends AbstractGenerator {
generatedFiles.add(new GeneratedFile(GeneratedFileType.SOURCE, UserTaskCodegenHelper.path(info).resolve(className + ".java"), unit.toString()));
}
-
return generatedFiles;
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskConfigGenerator.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskConfigGenerator.java
index 641f3b2d1a..d6483f92b2 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskConfigGenerator.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/java/org/kie/kogito/codegen/usertask/UserTaskConfigGenerator.java
@@ -35,11 +35,9 @@ import com.github.javaparser.ast.body.ConstructorDeclaration;
public class UserTaskConfigGenerator implements ConfigGenerator {
- private List<Work> collectedResources;
private TemplatedGenerator templateGenerator;
public UserTaskConfigGenerator(KogitoBuildContext context, List<Work> collectedResources) {
- this.collectedResources = collectedResources;
templateGenerator = TemplatedGenerator.builder()
.withTemplateBasePath("/class-templates/usertask")
.build(context, "UserTaskConfig");
@@ -54,7 +52,6 @@ public class UserTaskConfigGenerator implements ConfigGenerator {
public GeneratedFile generate() {
CompilationUnit unit = templateGenerator.compilationUnit().get();
String packageName = unit.getPackageDeclaration().get().getNameAsString();
- unit.getPackageDeclaration().get().setName(packageName);
ClassOrInterfaceDeclaration clazzDeclaration = unit.findFirst(ClassOrInterfaceDeclaration.class).get();
clazzDeclaration.setName(configClassName());
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskQuarkusTemplate.java
deleted file mode 100644
index 36f93ac462..0000000000
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskQuarkusTemplate.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * 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 com.myspace.demo;
-
-import java.util.List;
-
-import jakarta.ws.rs.NotFoundException;
-import jakarta.ws.rs.core.Context;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.UriInfo;
-
-import org.kie.kogito.auth.IdentityProviders;
-import org.kie.kogito.auth.SecurityPolicy;
-import org.kie.kogito.process.Process;
-import org.kie.kogito.process.ProcessInstance;
-import org.kie.kogito.process.ProcessInstanceReadMode;
-import org.kie.kogito.process.WorkItem;
-import org.kie.kogito.process.impl.Sig;
-import org.kie.kogito.services.uow.UnitOfWorkExecutor;
-
-public class $Type$Resource {
-
- @POST
- @Path("/{id}/$taskName$")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response signal(@PathParam("id") final String id,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- @Context UriInfo uriInfo) {
- return processService.signalWorkItem(process, id, "$taskName$", SecurityPolicy.of(user, groups))
- .map(task -> Response
- .created(uriInfo.getAbsolutePathBuilder().path(task.getId()).build())
- .entity(task.getResults())
- .build())
- .orElseThrow(NotFoundException::new);
- }
-
- @POST
- @Path("/{id}/$taskName$/{taskId}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public $Type$Output completeTask(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("phase") @DefaultValue("complete") final String phase,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- final $TaskOutput$ model) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
- .orElseThrow(NotFoundException::new);
- }
-
- @PUT
- @Path("/{id}/$taskName$/{taskId}")
- @Consumes(MediaType.APPLICATION_JSON)
- public $TaskOutput$ saveTask(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- final $TaskOutput$ model) {
- return processService.setWorkItemOutput(process, id, taskId, SecurityPolicy.of(user, groups), model, $TaskOutput$::fromMap)
- .orElseThrow(NotFoundException::new);
- }
-
- @POST
- @Path("/{id}/$taskName$/{taskId}/phases/{phase}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public $Type$Output taskTransition(
- @PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("phase") final String phase,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- final $TaskOutput$ model) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
- .orElseThrow(NotFoundException::new);
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}")
- @Produces(MediaType.APPLICATION_JSON)
- public $TaskModel$ getWorkItem(@PathParam("id") String id,
- @PathParam("taskId") String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getWorkItem(process, id, taskId, SecurityPolicy.of(user, groups), $TaskModel$::from)
- .orElseThrow(NotFoundException::new);
- }
-
- @DELETE
- @Path("/{id}/$taskName$/{taskId}")
- @Produces(MediaType.APPLICATION_JSON)
- public $Type$Output abortTask(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("phase") @DefaultValue("abort") final String phase,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), null)
- .orElseThrow(NotFoundException::new);
- }
-
- @GET
- @Path("$taskName$/schema")
- @Produces(MediaType.APPLICATION_JSON)
- public Map<String, Object> getSchema() {
- return JsonSchemaUtil.load(this.getClass().getClassLoader(), process.id(), "$taskName$");
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}/schema")
- @Produces(MediaType.APPLICATION_JSON)
- public Map<String, Object> getSchemaAndPhases(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getWorkItemSchemaAndPhases(process, id, taskId, "$taskName$", SecurityPolicy.of(user, groups));
- }
-
- @POST
- @Path("/{id}/$taskName$/{taskId}/comments")
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces(MediaType.APPLICATION_JSON)
- public Response addComment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- String commentInfo,
- @Context UriInfo uriInfo) {
- return processService.addComment(process, id, taskId, SecurityPolicy.of(user, groups), commentInfo)
- .map(comment -> Response.created(uriInfo.getAbsolutePathBuilder().path(comment.getId().toString()).build())
- .entity(comment).build())
- .orElseThrow(NotFoundException::new);
- }
-
- @PUT
- @Path("/{id}/$taskName$/{taskId}/comments/{commentId}")
- @Consumes(MediaType.TEXT_PLAIN)
- @Produces(MediaType.APPLICATION_JSON)
- public Comment updateComment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("commentId") final String commentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- String comment) {
- return processService.updateComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups), comment)
- .orElseThrow(NotFoundException::new);
- }
-
- @DELETE
- @Path("/{id}/$taskName$/{taskId}/comments/{commentId}")
- public Response deleteComment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("commentId") final String commentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.deleteComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups))
- .map(removed -> (removed ? Response.ok() : Response.status(Status.NOT_FOUND)).build())
- .orElseThrow(NotFoundException::new);
- }
-
- @POST
- @Path("/{id}/$taskName$/{taskId}/attachments")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response addAttachment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- AttachmentInfo attachmentInfo,
- @Context UriInfo uriInfo) {
- return processService.addAttachment(process, id, taskId, SecurityPolicy.of(user, groups), attachmentInfo)
- .map(attachment -> Response
- .created(uriInfo.getAbsolutePathBuilder().path(attachment.getId().toString()).build())
- .entity(attachment).build())
- .orElseThrow(NotFoundException::new);
- }
-
- @PUT
- @Path("/{id}/$taskName$/{taskId}/attachments/{attachmentId}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Attachment updateAttachment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("attachmentId") final String attachmentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups,
- AttachmentInfo attachment) {
- return processService.updateAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups), attachment)
- .orElseThrow(NotFoundException::new);
- }
-
- @DELETE
- @Path("/{id}/$taskName$/{taskId}/attachments/{attachmentId}")
- public Response deleteAttachment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("attachmentId") final String attachmentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.deleteAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups))
- .map(removed -> (removed ? Response.ok() : Response.status(Status.NOT_FOUND)).build())
- .orElseThrow(NotFoundException::new);
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}/attachments/{attachmentId}")
- @Produces(MediaType.APPLICATION_JSON)
- public Attachment getAttachment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("attachmentId") final String attachmentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new NotFoundException("Attachment " + attachmentId + " not found"));
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}/attachments")
- @Produces(MediaType.APPLICATION_JSON)
- public Collection<Attachment> getAttachments(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getAttachments(process, id, taskId, SecurityPolicy.of(user, groups))
- .orElseThrow(NotFoundException::new);
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}/comments/{commentId}")
- @Produces(MediaType.APPLICATION_JSON)
- public Comment getComment(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @PathParam("commentId") final String commentId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new NotFoundException("Comment " + commentId + " not found"));
- }
-
- @GET
- @Path("/{id}/$taskName$/{taskId}/comments")
- @Produces(MediaType.APPLICATION_JSON)
- public Collection<Comment> getComments(@PathParam("id") final String id,
- @PathParam("taskId") final String taskId,
- @QueryParam("user") final String user,
- @QueryParam("group") final List<String> groups) {
- return processService.getComments(process, id, taskId, SecurityPolicy.of(user, groups))
- .orElseThrow(NotFoundException::new);
- }
-}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskSpringTemplate.java
deleted file mode 100644
index a18e56c337..0000000000
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceUserTaskSpringTemplate.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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 com.myspace.demo;
-
-import java.util.List;
-import java.util.Map;
-
-import org.jbpm.util.JsonSchemaUtil;
-import org.kie.kogito.auth.IdentityProviders;
-import org.kie.kogito.auth.SecurityPolicy;
-import org.kie.kogito.process.ProcessInstance;
-import org.kie.kogito.process.WorkItem;
-import org.kie.kogito.process.impl.Sig;
-import org.kie.kogito.process.workitem.Comment;
-import org.kie.kogito.process.workitem.TaskMetaInfo;
-import org.kie.kogito.services.uow.UnitOfWorkExecutor;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PatchMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.util.UriComponentsBuilder;
-
-public class $Type$Resource {
-
- @PostMapping(value = "/{id}/$taskName$", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity signal(@PathVariable("id") final String id,
- @RequestParam("user") final String user,
- @RequestParam("group") final List<String> groups,
- final UriComponentsBuilder uriComponentsBuilder) {
-
- return processService.signalWorkItem(process, id, "$taskName$", SecurityPolicy.of(user, groups))
- .map(task -> ResponseEntity
- .created(uriComponentsBuilder
- .path("/$name$/{id}/$taskName$/{taskId}")
- .buildAndExpand(id, task.getId()).toUri())
- .body(task.getResults()))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PostMapping(value = "/{id}/$taskName$/{taskId}/phases/{phase}", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.APPLICATION_JSON_VALUE)
- public $Type$Output completeTask(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("phase") final String phase,
- @RequestParam("user") final String user,
- @RequestParam("group") final List<String> groups,
- @RequestBody(required = false) final $TaskOutput$ model) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PutMapping(value = "/{id}/$taskName$/{taskId}", consumes = MediaType.APPLICATION_JSON_VALUE)
- public $TaskOutput$ saveTask(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups,
- @RequestBody(required = false) final $TaskOutput$ model) {
- return processService.setWorkItemOutput(process, id, taskId, SecurityPolicy.of(user, groups), model, $TaskOutput$::fromMap)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PostMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.APPLICATION_JSON_VALUE)
- public $Type$Output taskTransition(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "phase", required = false,
- defaultValue = "complete") final String phase,
- @RequestParam(value = "user",
- required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups,
- @RequestBody(required = false) final $TaskOutput$ model) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public $TaskModel$ getTask(@PathVariable("id") String id,
- @PathVariable("taskId") String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups) {
- return processService.getWorkItem(process, id, taskId, SecurityPolicy.of(user, groups), $TaskModel$::from)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @DeleteMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public $Type$Output abortTask(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "phase", required = false,
- defaultValue = "abort") final String phase,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups) {
- return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), null)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @GetMapping(value = "$taskName$/schema", produces = MediaType.APPLICATION_JSON_VALUE)
- public Map<String, Object> getSchema() {
- return JsonSchemaUtil.load(this.getClass().getClassLoader(), process.id(), "$taskName$");
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}/schema", produces = MediaType.APPLICATION_JSON_VALUE)
- public Map<String, Object> getSchemaAndPhases(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups) {
- return processService.getWorkItemSchemaAndPhases(process, id, taskId, "$taskName$", SecurityPolicy.of(user, groups));
- }
-
- @PostMapping(value = "/{id}/$taskName$/{taskId}/comments", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.TEXT_PLAIN_VALUE)
- public ResponseEntity<Comment> addComment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups,
- @RequestBody String commentInfo,
- UriComponentsBuilder uriComponentsBuilder) {
- return processService.addComment(process, id, taskId, SecurityPolicy.of(user, groups), commentInfo)
- .map(comment -> ResponseEntity
- .created(uriComponentsBuilder.path("/$name$/{id}/$taskName$/{taskId}/comments/{commentId}")
- .buildAndExpand(id, taskId, comment.getId().toString()).toUri())
- .body(comment))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PutMapping(value = "/{id}/$taskName$/{taskId}/comments/{commentId}", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.TEXT_PLAIN_VALUE)
- public Comment updateComment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("commentId") final String commentId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups,
- @RequestBody String comment) {
- return processService.updateComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups), comment)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @DeleteMapping(value = "/{id}/$taskName$/{taskId}/comments/{commentId}")
- public ResponseEntity deleteComment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("commentId") final String commentId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups) {
- return processService.deleteComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups))
- .map(removed -> (removed ? ResponseEntity.ok().build() : ResponseEntity.notFound().build()))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PostMapping(value = "/{id}/$taskName$/{taskId}/attachments", produces = MediaType.APPLICATION_JSON_VALUE,
- consumes = MediaType.APPLICATION_JSON_VALUE)
- public ResponseEntity<Attachment> addAttachment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups,
- @RequestBody AttachmentInfo attachmentInfo,
- UriComponentsBuilder uriComponentsBuilder) {
- return processService.addAttachment(process, id, taskId, SecurityPolicy.of(user, groups), attachmentInfo)
- .map(attachment -> ResponseEntity
- .created(uriComponentsBuilder.path(
- "/$name$/{id}/$taskName$/{taskId}/attachments/{attachmentId}")
- .buildAndExpand(id,
- taskId, attachment.getId())
- .toUri())
- .body(attachment))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @PutMapping(value = "/{id}/$taskName$/{taskId}/attachments/{attachmentId}",
- produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
- public Attachment updateAttachment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("attachmentId") final String attachmentId,
- @RequestParam(value = "user",
- required = false) final String user,
- @RequestParam(value = "group",
- required = false) final List<String> groups,
- @RequestBody AttachmentInfo attachment) {
- return processService.updateAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups), attachment)
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @DeleteMapping(value = "/{id}/$taskName$/{taskId}/attachments/{attachmentId}")
- public ResponseEntity deleteAttachment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("attachmentId") final String attachmentId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups) {
-
- return processService.deleteAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups))
- .map(removed -> (removed ? ResponseEntity.ok() : ResponseEntity.notFound()).build())
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}/attachments/{attachmentId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public Attachment getAttachment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("attachmentId") final String attachmentId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups) {
- return processService.getAttachment(process, id, taskId, attachmentId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Attachment " + attachmentId + " not found"));
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}/attachments", produces = MediaType.APPLICATION_JSON_VALUE)
- public Collection<Attachment> getAttachments(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user") final String user,
- @RequestParam(value = "group") final List<String> groups) {
- return processService.getAttachments(process, id, taskId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}/comments/{commentId}", produces = MediaType.APPLICATION_JSON_VALUE)
- public Comment getComment(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @PathVariable("commentId") final String commentId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups) {
- return processService.getComment(process, id, taskId, commentId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Comment " + commentId + " not found"));
- }
-
- @GetMapping(value = "/{id}/$taskName$/{taskId}/comments", produces = MediaType.APPLICATION_JSON_VALUE)
- public Collection<Comment> getComments(@PathVariable("id") final String id,
- @PathVariable("taskId") final String taskId,
- @RequestParam(value = "user", required = false) final String user,
- @RequestParam(value = "group", required = false) final List<String> groups) {
- return processService.getComments(process, id, taskId, SecurityPolicy.of(user, groups))
- .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
- }
-}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemQuarkusTemplate.java
new file mode 100644
index 0000000000..2bf6dd3bc6
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemQuarkusTemplate.java
@@ -0,0 +1,139 @@
+/*
+ * 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 com.myspace.demo;
+
+import java.util.List;
+
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+
+import org.kie.kogito.auth.IdentityProviders;
+import org.kie.kogito.auth.SecurityPolicy;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.ProcessInstanceReadMode;
+import org.kie.kogito.process.WorkItem;
+import org.kie.kogito.process.impl.Sig;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.usertask.UserTaskService;
+
+import jakarta.inject.Inject;
+
+public class $Type$Resource {
+
+ @POST
+ @Path("/{id}/$taskName$/trigger")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response signal(@PathParam("id") final String id,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups,
+ @Context UriInfo uriInfo) {
+ return processService.signalWorkItem(process, id, "$taskName$", SecurityPolicy.of(user, groups))
+ .map(task -> Response
+ .created(uriInfo.getAbsolutePathBuilder().path(task.getId()).build())
+ .entity(task.getResults())
+ .build())
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @POST
+ @Path("/{id}/$taskName$/{taskId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public $Type$Output completeTask(@PathParam("id") final String id,
+ @PathParam("taskId") final String taskId,
+ @QueryParam("phase") @DefaultValue("complete") final String phase,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups,
+ final $TaskOutput$ model) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @PUT
+ @Path("/{id}/$taskName$/{taskId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public $TaskOutput$ saveTask(@PathParam("id") final String id,
+ @PathParam("taskId") final String taskId,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups,
+ final $TaskOutput$ model) {
+ return processService.setWorkItemOutput(process, id, taskId, SecurityPolicy.of(user, groups), model, $TaskOutput$::fromMap)
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @POST
+ @Path("/{id}/$taskName$/{taskId}/phases/{phase}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public $Type$Output taskTransition(
+ @PathParam("id") final String id,
+ @PathParam("taskId") final String taskId,
+ @PathParam("phase") final String phase,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups,
+ final $TaskOutput$ model) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{id}/$taskName$/{taskId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public $TaskModel$ getWorkItem(@PathParam("id") String id,
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups) {
+ return processService.getWorkItem(process, id, taskId, SecurityPolicy.of(user, groups), $TaskModel$::from)
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @DELETE
+ @Path("/{id}/$taskName$/{taskId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public $Type$Output abortTask(@PathParam("id") final String id,
+ @PathParam("taskId") final String taskId,
+ @QueryParam("phase") @DefaultValue("abort") final String phase,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), null)
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("$taskName$/schema")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Map<String, Object> getSchema() {
+ return JsonSchemaUtil.load(this.getClass().getClassLoader(), process.id(), "$taskName$");
+ }
+
+ @GET
+ @Path("/{id}/$taskName$/{taskId}/schema")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Map<String, Object> getSchemaAndPhases(@PathParam("id") final String id,
+ @PathParam("taskId") final String taskId,
+ @QueryParam("user") final String user,
+ @QueryParam("group") final List<String> groups) {
+ return processService.getWorkItemSchemaAndPhases(process, id, taskId, "$taskName$", SecurityPolicy.of(user, groups));
+ }
+
+}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemSpringTemplate.java
new file mode 100644
index 0000000000..7a5e65aea2
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/RestResourceWorkItemSpringTemplate.java
@@ -0,0 +1,137 @@
+/*
+ * 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 com.myspace.demo;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jbpm.util.JsonSchemaUtil;
+import org.kie.kogito.auth.IdentityProviders;
+import org.kie.kogito.auth.SecurityPolicy;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.WorkItem;
+import org.kie.kogito.process.impl.Sig;
+import org.kie.kogito.process.workitem.Comment;
+import org.kie.kogito.process.workitem.TaskMetaInfo;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.usertask.UserTaskService;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class $Type$Resource {
+
+ @PostMapping(value = "/{id}/$taskName$/trigger", produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity signal(@PathVariable("id") final String id,
+ @RequestParam("user") final String user,
+ @RequestParam("group") final List<String> groups,
+ final UriComponentsBuilder uriComponentsBuilder) {
+
+ return processService.signalWorkItem(process, id, "$taskName$", SecurityPolicy.of(user, groups))
+ .map(task -> ResponseEntity
+ .created(uriComponentsBuilder
+ .path("/$name$/{id}/$taskName$/{taskId}")
+ .buildAndExpand(id, task.getId()).toUri())
+ .body(task.getResults()))
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PostMapping(value = "/{id}/$taskName$/{taskId}/phases/{phase}", produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public $Type$Output completeTask(@PathVariable("id") final String id,
+ @PathVariable("taskId") final String taskId,
+ @PathVariable("phase") final String phase,
+ @RequestParam("user") final String user,
+ @RequestParam("group") final List<String> groups,
+ @RequestBody(required = false) final $TaskOutput$ model) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PutMapping(value = "/{id}/$taskName$/{taskId}", consumes = MediaType.APPLICATION_JSON_VALUE)
+ public $TaskOutput$ saveTask(@PathVariable("id") final String id,
+ @PathVariable("taskId") final String taskId,
+ @RequestParam(value = "user", required = false) final String user,
+ @RequestParam(value = "group", required = false) final List<String> groups,
+ @RequestBody(required = false) final $TaskOutput$ model) {
+ return processService.setWorkItemOutput(process, id, taskId, SecurityPolicy.of(user, groups), model, $TaskOutput$::fromMap)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PostMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ public $Type$Output taskTransition(@PathVariable("id") final String id,
+ @PathVariable("taskId") final String taskId,
+ @RequestParam(value = "phase", required = false,
+ defaultValue = "complete") final String phase,
+ @RequestParam(value = "user",
+ required = false) final String user,
+ @RequestParam(value = "group",
+ required = false) final List<String> groups,
+ @RequestBody(required = false) final $TaskOutput$ model) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), model)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public $TaskModel$ getTask(@PathVariable("id") String id,
+ @PathVariable("taskId") String taskId,
+ @RequestParam(value = "user", required = false) final String user,
+ @RequestParam(value = "group",
+ required = false) final List<String> groups) {
+ return processService.getWorkItem(process, id, taskId, SecurityPolicy.of(user, groups), $TaskModel$::from)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @DeleteMapping(value = "/{id}/$taskName$/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public $Type$Output abortTask(@PathVariable("id") final String id,
+ @PathVariable("taskId") final String taskId,
+ @RequestParam(value = "phase", required = false,
+ defaultValue = "abort") final String phase,
+ @RequestParam(value = "user", required = false) final String user,
+ @RequestParam(value = "group",
+ required = false) final List<String> groups) {
+ return processService.transitionWorkItem(process, id, taskId, phase, SecurityPolicy.of(user, groups), null)
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping(value = "$taskName$/schema", produces = MediaType.APPLICATION_JSON_VALUE)
+ public Map<String, Object> getSchema() {
+ return JsonSchemaUtil.load(this.getClass().getClassLoader(), process.id(), "$taskName$");
+ }
+
+ @GetMapping(value = "/{id}/$taskName$/{taskId}/schema", produces = MediaType.APPLICATION_JSON_VALUE)
+ public Map<String, Object> getSchemaAndPhases(@PathVariable("id") final String id,
+ @PathVariable("taskId") final String taskId,
+ @RequestParam(value = "user", required = false) final String user,
+ @RequestParam(value = "group",
+ required = false) final List<String> groups) {
+ return processService.getWorkItemSchemaAndPhases(process, id, taskId, "$taskName$", SecurityPolicy.of(user, groups));
+ }
+
+}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskQuarkusTemplate.java
new file mode 100644
index 0000000000..231dfcc737
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskQuarkusTemplate.java
@@ -0,0 +1,248 @@
+/*
+ * 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 com.myspace.demo;
+
+import java.util.Map;
+import java.util.List;
+import java.util.Collection;
+
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.Consumes;
+
+import org.kie.kogito.auth.IdentityProviders;
+import org.kie.kogito.auth.SecurityPolicy;
+import org.kie.kogito.process.Process;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.ProcessInstanceReadMode;
+import org.kie.kogito.process.WorkItem;
+import org.kie.kogito.process.impl.Sig;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.usertask.UserTaskService;
+import org.kie.kogito.usertask.view.UserTaskView;
+import org.kie.kogito.usertask.view.UserTaskTransitionView;
+
+import org.kie.kogito.usertask.model.*;
+
+import jakarta.inject.Inject;
+
+@Path("/usertasks/instance")
+public class UserTasksResource {
+
+ @Inject
+ UserTaskService userTaskService;
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public List<UserTaskView> list(@QueryParam("user") String user, @QueryParam("group") List<String> groups) {
+ return userTaskService.list(IdentityProviders.of(user, groups));
+ }
+
+ @GET
+ @Path("/{taskId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public UserTaskView find(@PathParam("taskId") String taskId, @QueryParam("user") String user, @QueryParam("group") List<String> groups) {
+ return userTaskService.getUserTaskInstance(taskId, IdentityProviders.of(user, groups)).orElseThrow(NotFoundException::new);
+ }
+
+ @POST
+ @Path("/{taskId}/transition")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public UserTaskView transition(
+ @PathParam("taskId") String taskId,
+ @QueryParam("transitionId") String transitionId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups, Map<String, Object> data) {
+ return userTaskService.transition(taskId, transitionId, data, IdentityProviders.of(user, groups)).orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{taskId}/transition")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Collection<UserTaskTransitionView> transition(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.allowedTransitions(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @PUT
+ @Path("/{taskId}/outputs")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public UserTaskView setOutput(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ Map<String, Object> data) {
+ return userTaskService.setOutputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(NotFoundException::new);
+ }
+
+ @PUT
+ @Path("/{taskId}/inputs")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public UserTaskView setOutput(@PathParam("id") String id,
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ Map<String, Object> data) {
+ return userTaskService.setInputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{taskId}/comments")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Collection<Comment> getComments(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.getComments(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @POST
+ @Path("/{taskId}/comments")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Comment addComment(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ CommentInfo commentInfo) {
+ Comment comment = new Comment(null, user);
+ comment.setContent(commentInfo.getComment());
+ return userTaskService.addComment(taskId, comment, IdentityProviders.of(user, groups)).orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{taskId}/comments/{commentId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Comment getComment(
+ @PathParam("taskId") String taskId,
+ @PathParam("commentId") String commentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.getComment(taskId, commentId, IdentityProviders.of(user, groups))
+ .orElseThrow(() -> new NotFoundException("Comment " + commentId + " not found"));
+ }
+
+ @PUT
+ @Path("/{taskId}/comments/{commentId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Comment updateComment(
+ @PathParam("taskId") String taskId,
+ @PathParam("commentId") String commentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ CommentInfo commentInfo) {
+ Comment comment = new Comment(commentId, user);
+ comment.setContent(commentInfo.getComment());
+ return userTaskService.updateComment(taskId, comment, IdentityProviders.of(user, groups))
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @DELETE
+ @Path("/{taskId}/comments/{commentId}")
+ public Comment deleteComment(
+ @PathParam("taskId") String taskId,
+ @PathParam("commentId") String commentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.removeComment(taskId, commentId, IdentityProviders.of(user, groups))
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{taskId}/attachments")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Collection<Attachment> getAttachments(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.getAttachments(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @POST
+ @Path("/{taskId}/attachments")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Attachment addAttachment(
+ @PathParam("taskId") String taskId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ AttachmentInfo attachmentInfo) {
+ Attachment attachment = new Attachment(null, user);
+ attachment.setName(attachmentInfo.getName());
+ attachment.setContent(attachmentInfo.getUri());
+ return userTaskService.addAttachment(taskId, attachment, IdentityProviders.of(user, groups))
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @PUT
+ @Path("/{taskId}/attachments/{attachmentId}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Attachment updateAttachment(
+ @PathParam("taskId") String taskId,
+ @PathParam("attachmentId") String attachmentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups,
+ AttachmentInfo attachmentInfo) {
+ Attachment attachment = new Attachment(attachmentId, user);
+ attachment.setName(attachmentInfo.getName());
+ attachment.setContent(attachmentInfo.getUri());
+ return userTaskService.updateAttachment(taskId, attachment, IdentityProviders.of(user, groups))
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @DELETE
+ @Path("/{taskId}/attachments/{attachmentId}")
+ public Attachment deleteAttachment(
+ @PathParam("taskId") String taskId,
+ @PathParam("attachmentId") String attachmentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.removeAttachment(taskId, attachmentId, IdentityProviders.of(user, groups))
+ .orElseThrow(NotFoundException::new);
+ }
+
+ @GET
+ @Path("/{taskId}/attachments/{attachmentId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Attachment getAttachment(
+ @PathParam("taskId") String taskId,
+ @PathParam("attachmentId") String attachmentId,
+ @QueryParam("user") String user,
+ @QueryParam("group") List<String> groups) {
+ return userTaskService.getAttachment(taskId, attachmentId, IdentityProviders.of(user, groups))
+ .orElseThrow(() -> new NotFoundException("Attachment " + attachmentId + " not found"));
+ }
+
+}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskSpringTemplate.java
new file mode 100644
index 0000000000..87c757d3d7
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/RestResourceUserTaskSpringTemplate.java
@@ -0,0 +1,210 @@
+/*
+ * 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 com.myspace.demo;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+import org.jbpm.util.JsonSchemaUtil;
+import org.kie.kogito.auth.IdentityProviders;
+import org.kie.kogito.auth.SecurityPolicy;
+import org.kie.kogito.process.ProcessInstance;
+import org.kie.kogito.process.WorkItem;
+import org.kie.kogito.process.impl.Sig;
+import org.kie.kogito.services.uow.UnitOfWorkExecutor;
+import org.kie.kogito.usertask.UserTaskService;
+import org.kie.kogito.usertask.view.UserTaskTransitionView;
+import org.kie.kogito.usertask.view.UserTaskView;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import org.kie.kogito.usertask.model.*;
+
+@RestController
+@RequestMapping(value = "/usertasks/instance", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
+public class UserTasksResource {
+
+ @Autowired
+ UserTaskService userTaskService;
+
+ @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
+ public List<UserTaskView> list(@RequestParam("user") String user, @RequestParam("group") List<String> groups) {
+ return userTaskService.list(IdentityProviders.of(user, groups));
+ }
+
+ @GetMapping(value = "/{taskId}", produces = MediaType.APPLICATION_JSON_VALUE)
+ public UserTaskView find(@PathVariable("taskId") String taskId, @RequestParam("user") String user, @RequestParam("group") List<String> groups) {
+ return userTaskService.getUserTaskInstance(taskId, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PostMapping(value = "/{taskId}/transition")
+ public UserTaskView transition(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("transitionId") String transitionId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody Map<String, Object> data) {
+ return userTaskService.transition(taskId, transitionId, data, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping(value = "/{taskId}/transition", produces = MediaType.APPLICATION_JSON_VALUE)
+ public Collection<UserTaskTransitionView> transition(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.allowedTransitions(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @PutMapping("/{taskId}/outputs")
+ public UserTaskView setOutput(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody Map<String, Object> data) {
+ return userTaskService.setOutputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PutMapping("/{taskId}/inputs")
+ public UserTaskView setOutput(@PathVariable("id") String id,
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody Map<String, Object> data) {
+ return userTaskService.setInputs(taskId, data, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping("/{taskId}/comments")
+ public Collection<Comment> getComments(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.getComments(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @PostMapping("/{taskId}/comments")
+ public Comment addComment(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody CommentInfo commentInfo) {
+ Comment comment = new Comment(null, user);
+ comment.setContent(commentInfo.getComment());
+ return userTaskService.addComment(taskId, comment, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping("/{taskId}/comments/{commentId}")
+ public Comment getComment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("commentId") String commentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.getComment(taskId, commentId, IdentityProviders.of(user, groups))
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Comment " + commentId + " not found"));
+ }
+
+ @PutMapping("/{taskId}/comments/{commentId}")
+ public Comment updateComment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("commentId") String commentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody CommentInfo commentInfo) {
+ Comment comment = new Comment(commentId, user);
+ comment.setContent(commentInfo.getComment());
+ return userTaskService.updateComment(taskId, comment, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @DeleteMapping("/{taskId}/comments/{commentId}")
+ public Comment deleteComment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("commentId") String commentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.removeComment(taskId, commentId, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping("/{taskId}/attachments")
+ public Collection<Attachment> getAttachments(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.getAttachments(taskId, IdentityProviders.of(user, groups));
+ }
+
+ @PostMapping("/{taskId}/attachments")
+ public Attachment addAttachment(
+ @PathVariable("taskId") String taskId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody AttachmentInfo attachmentInfo) {
+ Attachment attachment = new Attachment(null, user);
+ attachment.setName(attachmentInfo.getName());
+ attachment.setContent(attachmentInfo.getUri());
+ return userTaskService.addAttachment(taskId, attachment, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @PutMapping("/{taskId}/attachments/{attachmentId}")
+ public Attachment updateAttachment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("attachmentId") String attachmentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups,
+ @RequestBody AttachmentInfo attachmentInfo) {
+ Attachment attachment = new Attachment(attachmentId, user);
+ attachment.setName(attachmentInfo.getName());
+ attachment.setContent(attachmentInfo.getUri());
+ return userTaskService.updateAttachment(taskId, attachment, IdentityProviders.of(user, groups))
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @DeleteMapping("/{taskId}/attachments/{attachmentId}")
+ public Attachment deleteAttachment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("attachmentId") String attachmentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.removeAttachment(taskId, attachmentId, IdentityProviders.of(user, groups)).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
+ }
+
+ @GetMapping("/{taskId}/attachments/{attachmentId}")
+ public Attachment getAttachment(
+ @PathVariable("taskId") String taskId,
+ @PathVariable("attachmentId") String attachmentId,
+ @RequestParam("user") String user,
+ @RequestParam("group") List<String> groups) {
+ return userTaskService.getAttachment(taskId, attachmentId, IdentityProviders.of(user, groups))
+ .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Attachment " + attachmentId + " not found"));
+ }
+
+}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigQuarkusTemplate.java
index 3486fad384..3d327fb03f 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigQuarkusTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigQuarkusTemplate.java
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,6 +17,8 @@
* specific language governing permissions and limitations
* under the License.
*/
+import java.util.List;
+
import org.kie.api.event.process.ProcessEventListener;
import org.kie.kogito.auth.IdentityProvider;
import org.kie.kogito.event.EventPublisher;
@@ -27,26 +30,31 @@ import org.kie.kogito.uow.UnitOfWorkManager;
import org.kie.kogito.uow.events.UnitOfWorkEventListener;
import org.kie.kogito.usertask.impl.DefaultUserTaskConfig;
import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
import org.kie.kogito.usertask.UserTaskEventListenerConfig;
+import org.kie.kogito.usertask.UserTaskInstances;
import jakarta.enterprise.inject.Instance;
@jakarta.inject.Singleton
public class UserTaskConfig extends DefaultUserTaskConfig {
-
-
+
@jakarta.inject.Inject
public UserTaskConfig(
Instance<UserTaskEventListenerConfig> workItemHandlerConfig,
Instance<UnitOfWorkManager> unitOfWorkManager,
Instance<JobsService> jobsService,
Instance<IdentityProvider> identityProvider,
- Instance<UserTaskLifeCycle> userTaskLifeCycle) {
- super(workItemHandlerConfig,
+ Instance<UserTaskLifeCycle> userTaskLifeCycle,
+ Instance<UserTaskAssignmentStrategyConfig> userTaskAssignmentStrategyConfigs,
+ Instance<UserTaskInstances> userTaskInstances) {
+ super(workItemHandlerConfig,
unitOfWorkManager,
jobsService,
identityProvider,
- userTaskLifeCycle);
+ userTaskLifeCycle,
+ userTaskAssignmentStrategyConfigs,
+ userTaskInstances);
}
-
+
}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigSpringTemplate.java
index d8e00dbc57..11f7935f43 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigSpringTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskConfigSpringTemplate.java
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -29,24 +30,30 @@ import org.kie.kogito.uow.UnitOfWorkManager;
import org.kie.kogito.uow.events.UnitOfWorkEventListener;
import org.kie.kogito.usertask.impl.DefaultUserTaskConfig;
import org.kie.kogito.usertask.lifecycle.UserTaskLifeCycle;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
import org.kie.kogito.usertask.UserTaskEventListenerConfig;
+import org.kie.kogito.usertask.UserTaskInstances;
@org.springframework.stereotype.Component
public class UserTaskConfig extends DefaultUserTaskConfig {
-
+
@org.springframework.beans.factory.annotation.Autowired
public UserTaskConfig(
List<UserTaskEventListenerConfig> workItemHandlerConfig,
List<UnitOfWorkManager> unitOfWorkManager,
List<JobsService> jobsService,
List<IdentityProvider> identityProvider,
- List<UserTaskLifeCycle> userTaskLifeCycle) {
+ List<UserTaskLifeCycle> userTaskLifeCycle,
+ List<UserTaskAssignmentStrategyConfig> userTaskAssignmentStrategyConfigs,
+ List<UserTaskInstances> userTaskInstances) {
- super(workItemHandlerConfig,
+ super(workItemHandlerConfig,
unitOfWorkManager,
jobsService,
identityProvider,
- userTaskLifeCycle);
+ userTaskLifeCycle,
+ userTaskAssignmentStrategyConfigs,
+ userTaskInstances);
}
-
+
}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskQuarkusTemplate.java
index 5e915790f9..3d5213b17a 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskQuarkusTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskQuarkusTemplate.java
@@ -22,6 +22,9 @@ import java.util.Set;
import org.kie.kogito.Application;
import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.impl.DefaultUserTask;
public class UserTaskTemplate extends DefaultUserTask {
@@ -32,9 +35,16 @@ public class UserTaskTemplate extends DefaultUserTask {
public UserTaskTemplate() {
}
+
+ @Override
+ public UserTaskAssignmentStrategy getAssignmentStrategy() {
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ return userTaskConfig.userTaskAssignmentStrategies().defaultUserTaskAssignmentStrategy();
+ }
- @jakarta.annotation.PostConstruct
- public void setup() {
- this.setApplication(application);
+ @Override
+ public UserTaskInstances instances() {
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ return userTaskConfig.userTaskInstances();
}
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskSpringTemplate.java
index 64e9aa5354..eae587b8ea 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskSpringTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTaskSpringTemplate.java
@@ -22,6 +22,9 @@ import java.util.Set;
import org.kie.kogito.Application;
import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstances;
import org.kie.kogito.usertask.impl.DefaultUserTask;
public class UserTaskTemplate extends DefaultUserTask {
@@ -33,8 +36,16 @@ public class UserTaskTemplate extends DefaultUserTask {
}
- @jakarta.annotation.PostConstruct
- public void setup() {
- this.setApplication(application);
+ @Override
+ public UserTaskAssignmentStrategy getAssignmentStrategy() {
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ return userTaskConfig.userTaskAssignmentStrategies().defaultUserTaskAssignmentStrategy();
}
+
+ @Override
+ public UserTaskInstances instances() {
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ return userTaskConfig.userTaskInstances();
+ }
+
}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerQuarkusTemplate.java
index 9d22ea14ee..8e98179784 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerQuarkusTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerQuarkusTemplate.java
@@ -22,21 +22,40 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
+
+import org.kie.kogito.uow.events.UnitOfWorkUserTaskEventListener;
+import org.kie.kogito.usertask.impl.DefaultUserTaskInstance;
+import org.kie.kogito.usertask.impl.KogitoUserTaskEventSupportImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTaskInstances;
+
import jakarta.enterprise.inject.Instance;
@jakarta.enterprise.context.ApplicationScoped
public class UserTasks implements org.kie.kogito.usertask.UserTasks {
+ private static Logger LOG = LoggerFactory.getLogger(UserTasks.class);
+
@jakarta.inject.Inject
jakarta.enterprise.inject.Instance<UserTask> userTasks;
+ @jakarta.inject.Inject
+ Application application;
+
private Map<String, UserTask> mappedUserTask = new HashMap<>();
@jakarta.annotation.PostConstruct
public void setup() {
+ UserTaskInstances userTaskInstances = application.config().get(UserTaskConfig.class).userTaskInstances();
+ userTaskInstances.setDisconnectUserTaskInstance(this::disconnect);
+ userTaskInstances.setReconnectUserTaskInstance(this::connect);
for (UserTask userTask : userTasks) {
mappedUserTask.put(userTask.id(), userTask);
+ LOG.info("Registering user task {} with task name {}", userTask.id(), userTask.getTaskName());
}
}
@@ -47,4 +66,31 @@ public class UserTasks implements org.kie.kogito.usertask.UserTasks {
public Collection<String> userTaskIds() {
return mappedUserTask.keySet();
}
+
+ @Override
+ public UserTaskInstances instances() {
+ return application.config().get(UserTaskConfig.class).userTaskInstances();
+ }
+
+ private UserTaskInstance disconnect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ instance.setUserTask(null);
+ instance.setUserTaskEventSupport(null);
+ instance.setUserTaskLifeCycle(null);
+ instance.setInstances(null);
+ return instance;
+ }
+
+ public UserTaskInstance connect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ KogitoUserTaskEventSupportImpl impl = new KogitoUserTaskEventSupportImpl(userTaskConfig.identityProvider());
+ userTaskConfig.userTaskEventListeners().listeners().forEach(impl::addEventListener);
+ impl.addEventListener(new UnitOfWorkUserTaskEventListener(application.unitOfWorkManager()));
+ instance.setUserTask(application.get(UserTasks.class).userTaskById(instance.getUserTaskId()));
+ instance.setUserTaskEventSupport(impl);
+ instance.setUserTaskLifeCycle(userTaskConfig.userTaskLifeCycle());
+ instance.setInstances(application.config().get(UserTaskConfig.class).userTaskInstances());
+ return instance;
+ }
}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerSpringTemplate.java
index 1e65367bfc..9785b44d7c 100644
--- a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerSpringTemplate.java
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksContainerSpringTemplate.java
@@ -22,24 +22,44 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
+
+import org.kie.kogito.Application;
+import org.kie.kogito.uow.events.UnitOfWorkUserTaskEventListener;
+import org.kie.kogito.usertask.impl.DefaultUserTaskInstance;
+import org.kie.kogito.usertask.impl.KogitoUserTaskEventSupportImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskInstance;
+import org.kie.kogito.usertask.UserTaskInstances;
@org.springframework.web.context.annotation.ApplicationScope
@org.springframework.stereotype.Component
public class UserTasks implements org.kie.kogito.usertask.UserTasks {
-
+
+ private static Logger LOG = LoggerFactory.getLogger(UserTasks.class);
+
@org.springframework.beans.factory.annotation.Autowired
Collection<UserTask> userTasks;
+ @org.springframework.beans.factory.annotation.Autowired
+ Application application;
+
private Map<String, UserTask> mappedUserTask = new HashMap<>();
-
+
@jakarta.annotation.PostConstruct
public void setup() {
+ UserTaskInstances userTaskInstances = application.config().get(UserTaskConfig.class).userTaskInstances();
+ userTaskInstances.setDisconnectUserTaskInstance(this::disconnect);
+ userTaskInstances.setReconnectUserTaskInstance(this::connect);
+
for (UserTask userTask : userTasks) {
mappedUserTask.put(userTask.id(), userTask);
+ LOG.info("Registering user task {} with task name {}", userTask.id(), userTask.getTaskName());
}
}
-
+
public UserTask userTaskById(String userTaskId) {
return mappedUserTask.get(userTaskId);
}
@@ -47,4 +67,31 @@ public class UserTasks implements org.kie.kogito.usertask.UserTasks {
public Collection<String> userTaskIds() {
return mappedUserTask.keySet();
}
+
+ @Override
+ public UserTaskInstances instances() {
+ return application.config().get(UserTaskConfig.class).userTaskInstances();
+ }
+
+ private UserTaskInstance disconnect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ instance.setUserTask(null);
+ instance.setUserTaskEventSupport(null);
+ instance.setUserTaskLifeCycle(null);
+ instance.setInstances(null);
+ return instance;
+ }
+
+ public UserTaskInstance connect(UserTaskInstance userTaskInstance) {
+ DefaultUserTaskInstance instance = (DefaultUserTaskInstance) userTaskInstance;
+ UserTaskConfig userTaskConfig = application.config().get(UserTaskConfig.class);
+ KogitoUserTaskEventSupportImpl impl = new KogitoUserTaskEventSupportImpl(userTaskConfig.identityProvider());
+ userTaskConfig.userTaskEventListeners().listeners().forEach(impl::addEventListener);
+ impl.addEventListener(new UnitOfWorkUserTaskEventListener(application.unitOfWorkManager()));
+ instance.setUserTask(application.get(org.kie.kogito.usertask.UserTasks.class).userTaskById(instance.getUserTaskId()));
+ instance.setUserTaskEventSupport(impl);
+ instance.setUserTaskLifeCycle(userTaskConfig.userTaskLifeCycle());
+ instance.setInstances(application.config().get(UserTaskConfig.class).userTaskInstances());
+ return instance;
+ }
}
\ No newline at end of file
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerQuarkusTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerQuarkusTemplate.java
new file mode 100644
index 0000000000..837b7312e1
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerQuarkusTemplate.java
@@ -0,0 +1,68 @@
+/*
+ * 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 $Package$;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import jakarta.enterprise.inject.Instance;
+
+import org.kie.kogito.Application;
+import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler;
+import org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler;
+import org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandlerProcessListener;
+import org.kie.kogito.process.Processes;
+import org.kie.kogito.usertask.UserTask;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
+import org.kie.kogito.usertask.UserTaskEventListener;
+import org.kie.kogito.usertask.UserTaskService;
+import org.kie.kogito.usertask.UserTaskConfig;
+import org.kie.kogito.usertask.UserTaskEventListenerConfig;
+import org.kie.kogito.usertask.impl.DefaultUserTaskEventListenerConfig;
+import org.kie.kogito.usertask.impl.DefaultUserTaskAssignmentStrategyConfig;
+import org.kie.kogito.usertask.impl.UserTaskServiceImpl;
+
+@ApplicationScoped
+public class UserTasksServiceProducer {
+
+ @Produces
+ public UserTaskService userTaskService(Application application) {
+ return new UserTaskServiceImpl(application);
+ }
+
+ @Produces
+ public UserTaskEventListener userTaskListener(Processes processes) {
+ return new UserTaskKogitoWorkItemHandlerProcessListener(processes);
+ }
+
+ @Produces
+ public KogitoWorkItemHandler userTaskWorkItemHandler(Application application) {
+ return new UserTaskKogitoWorkItemHandler(application);
+ }
+
+ @Produces
+ public UserTaskEventListenerConfig userTaskEventListenerConfig(Instance<UserTaskEventListener> userTaskEventListener) {
+ return new DefaultUserTaskEventListenerConfig(userTaskEventListener);
+ }
+
+ @Produces
+ public UserTaskAssignmentStrategyConfig userTaskAssignmentStrategyConfig(Instance<UserTaskAssignmentStrategy> userTaskAssignmentStrategy) {
+ return new DefaultUserTaskAssignmentStrategyConfig(userTaskAssignmentStrategy);
+ }
+}
diff --git a/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerSpringTemplate.java b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerSpringTemplate.java
new file mode 100644
index 0000000000..088d7ad193
--- /dev/null
+++ b/kogito-codegen-modules/kogito-codegen-processes/src/main/resources/class-templates/usertask/UserTasksServiceProducerSpringTemplate.java
@@ -0,0 +1,67 @@
+/*
+ * 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 $Package$;
+
+import java.util.List;
+import org.kie.kogito.Application;
+import org.kie.kogito.internal.process.workitem.KogitoWorkItemHandler;
+import org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandler;
+import org.kie.kogito.jbpm.usertask.handler.UserTaskKogitoWorkItemHandlerProcessListener;
+import org.kie.kogito.process.ProcessService;
+import org.kie.kogito.process.Processes;
+import org.kie.kogito.process.impl.ProcessServiceImpl;
+import org.kie.kogito.usertask.UserTaskEventListenerConfig;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategyConfig;
+import org.kie.kogito.usertask.UserTaskAssignmentStrategy;
+import org.kie.kogito.usertask.UserTaskEventListener;
+import org.kie.kogito.usertask.impl.DefaultUserTaskEventListenerConfig;
+import org.kie.kogito.usertask.impl.DefaultUserTaskAssignmentStrategyConfig;
+import org.kie.kogito.usertask.impl.UserTaskServiceImpl;
+import org.kie.kogito.usertask.UserTaskService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class UserTaskServiceProducer {
+
+ @Bean
+ public UserTaskService userTaskService(Application application) {
+ return new UserTaskServiceImpl(application);
+ }
+
+ @Bean
+ public UserTaskEventListener userTaskListener(Processes processes) {
+ return new UserTaskKogitoWorkItemHandlerProcessListener(processes);
+ }
+
+ @Bean
+ public KogitoWorkItemHandler userTaskWorkItemHandler(Application application) {
+ return new UserTaskKogitoWorkItemHandler(application);
+ }
+
+ @Bean
+ public UserTaskEventListenerConfig userTaskEventListenerConfig(List<UserTaskEventListener> userTaskEventListener) {
+ return new DefaultUserTaskEventListenerConfig(userTaskEventListener);
+ }
+
+ @Bean
+ public UserTaskAssignmentStrategyConfig userTaskAssignmentStrategyConfig(List<UserTaskAssignmentStrategy> userTaskAssignmentStrategy) {
+ return new DefaultUserTaskAssignmentStrategyConfig(userTaskAssignmentStrategy);
+ }
+}
diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
index 72a8a4a6fc..c0d75bce39 100644
--- a/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
+++ b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
@@ -303,7 +303,7 @@ public abstract class PersistenceTest {
.queryParam("user", "user")
.queryParam("group", "agroup")
.when()
- .post("/AdHocProcess/{pId}/CloseTask")
+ .post("/AdHocProcess/{pId}/CloseTask/trigger")
.then()
.log().everything()
.statusCode(201)
diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/main/resources/AddedTask.bpmn2 b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/main/resources/AddedTask.bpmn2
new file mode 100644
index 0000000000..6d8f8618cd
--- /dev/null
+++ b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/main/resources/AddedTask.bpmn2
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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="_ENJmkGP9ED2iIdGE-n8pYg" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd http://www. [...]
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_PriorityInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_CommentInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_DescriptionInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_CreatedByInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_GroupIdInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_ContentInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_NotStartedReassignInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_NotCompletedReassignInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_NotStartedNotifyInputXItem" structureRef="Object"/>
+ <bpmn2:itemDefinition id="__74EA6719-7F99-48CD-A98E-17D422668B87_NotCompletedNotifyInputXItem" structureRef="Object"/>
+ <bpmn2:signal id="_-567202649" name="continue"/>
+ <bpmn2:collaboration id="_4DD91E78-A982-46F9-A427-611946D40403" name="Default Collaboration">
+ <bpmn2:participant id="_239FEF97-E424-41F3-B3E9-D626D7EC319D" name="Pool Participant" processRef="addedtask"/>
+ </bpmn2:collaboration>
+ <bpmn2:process id="AddedTask" drools:packageName="com.example" drools:version="1.0" drools:adHoc="false" name="addedtask" isExecutable="true" processType="Public">
+ <bpmn2:sequenceFlow id="_D0E6CA53-1ECE-4F8D-AAF0-829B30A2719F" sourceRef="_74EA6719-7F99-48CD-A98E-17D422668B87" targetRef="_1D65864A-96AF-44FC-92CE-2073B9FBA7D0">
+ <bpmn2:extensionElements>
+ <drools:metaData name="isAutoConnection.target">
+ <drools:metaValue><![CDATA[true]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ </bpmn2:sequenceFlow>
+ <bpmn2:sequenceFlow id="_FA3E1FF8-4894-47DA-90EB-DAB27BD7E925" sourceRef="_7C0F340A-57A6-40ED-A802-4C8A5B61B8E4" targetRef="_8F029B9C-9B3C-4907-8C68-69B30FD85A88">
+ <bpmn2:extensionElements>
+ <drools:metaData name="isAutoConnection.target">
+ <drools:metaValue><![CDATA[true]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ </bpmn2:sequenceFlow>
+ <bpmn2:sequenceFlow id="_2DFFEEA8-CA22-4076-A703-DB36A6471775" sourceRef="_1D65864A-96AF-44FC-92CE-2073B9FBA7D0" targetRef="_7C0F340A-57A6-40ED-A802-4C8A5B61B8E4">
+ <bpmn2:extensionElements>
+ <drools:metaData name="isAutoConnection.target">
+ <drools:metaValue><![CDATA[true]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ </bpmn2:sequenceFlow>
+ <bpmn2:sequenceFlow id="_916690AE-8B09-4FA5-BF0D-8638E01A7472" sourceRef="_9660EA72-BFEC-4FAE-B5C3-48513A420288" targetRef="_74EA6719-7F99-48CD-A98E-17D422668B87"/>
+ <bpmn2:sequenceFlow id="_C7A1A566-057F-4A80-B654-61270F82F365" sourceRef="_D7D85E86-FA30-43CB-9DB6-A3FC067049C1" targetRef="_9660EA72-BFEC-4FAE-B5C3-48513A420288"/>
+ <bpmn2:intermediateCatchEvent id="_1D65864A-96AF-44FC-92CE-2073B9FBA7D0">
+ <bpmn2:incoming>_D0E6CA53-1ECE-4F8D-AAF0-829B30A2719F</bpmn2:incoming>
+ <bpmn2:outgoing>_2DFFEEA8-CA22-4076-A703-DB36A6471775</bpmn2:outgoing>
+ <bpmn2:signalEventDefinition signalRef="_-567202649"/>
+ </bpmn2:intermediateCatchEvent>
+ <bpmn2:userTask id="_74EA6719-7F99-48CD-A98E-17D422668B87" name="HT">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[HT]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_916690AE-8B09-4FA5-BF0D-8638E01A7472</bpmn2:incoming>
+ <bpmn2:outgoing>_D0E6CA53-1ECE-4F8D-AAF0-829B30A2719F</bpmn2:outgoing>
+ <bpmn2:ioSpecification>
+ <bpmn2:dataInput id="_74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputX" drools:dtype="Object" itemSubjectRef="__74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputXItem" name="TaskName"/>
+ <bpmn2:dataInput id="_74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputX" drools:dtype="Object" itemSubjectRef="__74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputXItem" name="Skippable"/>
+ <bpmn2:inputSet>
+ <bpmn2:dataInputRefs>_74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputX</bpmn2:dataInputRefs>
+ <bpmn2:dataInputRefs>_74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputX</bpmn2:dataInputRefs>
+ </bpmn2:inputSet>
+ </bpmn2:ioSpecification>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[Task]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_74EA6719-7F99-48CD-A98E-17D422668B87_TaskNameInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:dataInputAssociation>
+ <bpmn2:targetRef>_74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputX</bpmn2:targetRef>
+ <bpmn2:assignment>
+ <bpmn2:from xsi:type="bpmn2:tFormalExpression"><![CDATA[false]]></bpmn2:from>
+ <bpmn2:to xsi:type="bpmn2:tFormalExpression"><![CDATA[_74EA6719-7F99-48CD-A98E-17D422668B87_SkippableInputX]]></bpmn2:to>
+ </bpmn2:assignment>
+ </bpmn2:dataInputAssociation>
+ <bpmn2:potentialOwner id="_ENPGIGP9ED2iIdGE-n8pYg">
+ <bpmn2:resourceAssignmentExpression id="_ENPGIWP9ED2iIdGE-n8pYg">
+ <bpmn2:formalExpression>mary</bpmn2:formalExpression>
+ </bpmn2:resourceAssignmentExpression>
+ </bpmn2:potentialOwner>
+ </bpmn2:userTask>
+ <bpmn2:endEvent id="_8F029B9C-9B3C-4907-8C68-69B30FD85A88">
+ <bpmn2:incoming>_FA3E1FF8-4894-47DA-90EB-DAB27BD7E925</bpmn2:incoming>
+ </bpmn2:endEvent>
+ <bpmn2:scriptTask id="_7C0F340A-57A6-40ED-A802-4C8A5B61B8E4" name="log process continuation" scriptFormat="http://www.java.com/java">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[log process continuation]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_2DFFEEA8-CA22-4076-A703-DB36A6471775</bpmn2:incoming>
+ <bpmn2:outgoing>_FA3E1FF8-4894-47DA-90EB-DAB27BD7E925</bpmn2:outgoing>
+ <bpmn2:script>System.out.println("Ending process " + kcontext.getProcessInstance().getId() + " [" + kcontext.getProcessInstance().getProcessName() + ", v" + kcontext.getProcessInstance().getProcessVersion() + "]");</bpmn2:script>
+ </bpmn2:scriptTask>
+ <bpmn2:scriptTask id="_9660EA72-BFEC-4FAE-B5C3-48513A420288" name="log process creation" scriptFormat="http://www.java.com/java">
+ <bpmn2:extensionElements>
+ <drools:metaData name="elementname">
+ <drools:metaValue><![CDATA[log process creation]]></drools:metaValue>
+ </drools:metaData>
+ </bpmn2:extensionElements>
+ <bpmn2:incoming>_C7A1A566-057F-4A80-B654-61270F82F365</bpmn2:incoming>
+ <bpmn2:outgoing>_916690AE-8B09-4FA5-BF0D-8638E01A7472</bpmn2:outgoing>
+ <bpmn2:script>System.out.println("Started process " + kcontext.getProcessInstance().getId() + " [" + kcontext.getProcessInstance().getProcessName() + ", v" + kcontext.getProcessInstance().getProcessVersion() + "]");</bpmn2:script>
+ </bpmn2:scriptTask>
+ <bpmn2:startEvent id="_D7D85E86-FA30-43CB-9DB6-A3FC067049C1">
+ <bpmn2:outgoing>_C7A1A566-057F-4A80-B654-61270F82F365</bpmn2:outgoing>
+ </bpmn2:startEvent>
+ </bpmn2:process>
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="addedtask">
+ <bpmndi:BPMNShape id="shape__D7D85E86-FA30-43CB-9DB6-A3FC067049C1" bpmnElement="_D7D85E86-FA30-43CB-9DB6-A3FC067049C1">
+ <dc:Bounds height="56" width="56" x="112" y="261"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__9660EA72-BFEC-4FAE-B5C3-48513A420288" bpmnElement="_9660EA72-BFEC-4FAE-B5C3-48513A420288">
+ <dc:Bounds height="102" width="154" x="248" y="238"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__7C0F340A-57A6-40ED-A802-4C8A5B61B8E4" bpmnElement="_7C0F340A-57A6-40ED-A802-4C8A5B61B8E4">
+ <dc:Bounds height="102" width="154" x="838" y="238"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__8F029B9C-9B3C-4907-8C68-69B30FD85A88" bpmnElement="_8F029B9C-9B3C-4907-8C68-69B30FD85A88">
+ <dc:Bounds height="56" width="56" x="1050" y="261"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__74EA6719-7F99-48CD-A98E-17D422668B87" bpmnElement="_74EA6719-7F99-48CD-A98E-17D422668B87">
+ <dc:Bounds height="102" width="154" x="462" y="238"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape id="shape__1D65864A-96AF-44FC-92CE-2073B9FBA7D0" bpmnElement="_1D65864A-96AF-44FC-92CE-2073B9FBA7D0">
+ <dc:Bounds height="56" width="56" x="681" y="261"/>
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge id="edge_shape__D7D85E86-FA30-43CB-9DB6-A3FC067049C1_to_shape__9660EA72-BFEC-4FAE-B5C3-48513A420288" bpmnElement="_C7A1A566-057F-4A80-B654-61270F82F365">
+ <di:waypoint x="140" y="289"/>
+ <di:waypoint x="325" y="289"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__9660EA72-BFEC-4FAE-B5C3-48513A420288_to_shape__74EA6719-7F99-48CD-A98E-17D422668B87" bpmnElement="_916690AE-8B09-4FA5-BF0D-8638E01A7472">
+ <di:waypoint x="325" y="289"/>
+ <di:waypoint x="539" y="289"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__1D65864A-96AF-44FC-92CE-2073B9FBA7D0_to_shape__7C0F340A-57A6-40ED-A802-4C8A5B61B8E4" bpmnElement="_2DFFEEA8-CA22-4076-A703-DB36A6471775">
+ <di:waypoint x="709" y="289"/>
+ <di:waypoint x="838" y="289"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__7C0F340A-57A6-40ED-A802-4C8A5B61B8E4_to_shape__8F029B9C-9B3C-4907-8C68-69B30FD85A88" bpmnElement="_FA3E1FF8-4894-47DA-90EB-DAB27BD7E925">
+ <di:waypoint x="915" y="289"/>
+ <di:waypoint x="1127" y="261"/>
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge id="edge_shape__74EA6719-7F99-48CD-A98E-17D422668B87_to_shape__1D65864A-96AF-44FC-92CE-2073B9FBA7D0" bpmnElement="_D0E6CA53-1ECE-4F8D-AAF0-829B30A2719F">
+ <di:waypoint x="539" y="289"/>
+ <di:waypoint x="681" y="289"/>
+ </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="_D7D85E86-FA30-43CB-9DB6-A3FC067049C1">
+ <bpsim:TimeParameters>
+ <bpsim:ProcessingTime>
+ <bpsim:NormalDistribution mean="0" standardDeviation="0"/>
+ </bpsim:ProcessingTime>
+ </bpsim:TimeParameters>
+ </bpsim:ElementParameters>
+ <bpsim:ElementParameters elementRef="_9660EA72-BFEC-4FAE-B5C3-48513A420288">
+ <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:ElementParameters elementRef="_7C0F340A-57A6-40ED-A802-4C8A5B61B8E4">
+ <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:ElementParameters elementRef="_74EA6719-7F99-48CD-A98E-17D422668B87">
+ <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>_ENJmkGP9ED2iIdGE-n8pYg</bpmn2:source>
+ <bpmn2:target>_ENJmkGP9ED2iIdGE-n8pYg</bpmn2:target>
+ </bpmn2:relationship>
+</bpmn2:definitions>
\ No newline at end of file
diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/test/java/org/kie/kogito/it/InfinispanPersistenceIT.java b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/test/java/org/kie/kogito/it/InfinispanPersistenceIT.java
index fd779ca575..cc668b0643 100644
--- a/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/test/java/org/kie/kogito/it/InfinispanPersistenceIT.java
+++ b/quarkus/integration-tests/integration-tests-quarkus-processes-persistence/integration-tests-quarkus-processes-infinispan/src/test/java/org/kie/kogito/it/InfinispanPersistenceIT.java
@@ -18,9 +18,84 @@
*/
package org.kie.kogito.it;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
import io.quarkus.test.junit.QuarkusIntegrationTest;
+import io.restassured.http.ContentType;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
@QuarkusIntegrationTest
class InfinispanPersistenceIT extends PersistenceTest {
+ private static final String USER_TASK_BASE_PATH = "/usertasks/instance";
+
+ @Test
+ public void testStartApprovalAuthorized() {
+ // start new approval
+ String id = given()
+ .body("{}")
+ .contentType(ContentType.JSON)
+ .when()
+ .post("/AddedTask")
+ .then()
+ .statusCode(201)
+ .body("id", notNullValue()).extract().path("id");
+ // get all active approvals
+ given()
+ .accept(ContentType.JSON)
+ .when()
+ .get("/AddedTask")
+ .then()
+ .statusCode(200)
+ .body("size()", is(1), "[0].id", is(id));
+
+ // get just started approval
+ given()
+ .accept(ContentType.JSON)
+ .when()
+ .get("/AddedTask/" + id)
+ .then()
+ .statusCode(200)
+ .body("id", is(id));
+
+ // tasks assigned in just started approval
+
+ String userTaskId = given()
+ .basePath(USER_TASK_BASE_PATH)
+ .queryParam("user", "mary")
+ .queryParam("group", "managers")
+ .contentType(ContentType.JSON)
+ .when()
+ .get()
+ .then()
+ .statusCode(200)
+ .extract()
+ .body()
+ .path("[0].id");
+
+ given()
+ .contentType(ContentType.JSON)
+ .basePath(USER_TASK_BASE_PATH)
+ .queryParam("transitionId", "complete")
+ .queryParam("user", "mary")
+ .queryParam("group", "managers")
+ .body(Collections.emptyMap())
+ .when()
+ .post("/{userTaskId}/transition", userTaskId)
+ .then()
+ .statusCode(200);
+ // get all active approvals
+ given()
+ .accept(ContentType.JSON)
+ .when()
+ .get("/AddedTask")
+ .then()
+ .statusCode(200)
+ .body("size()", is(1));
+ }
}
diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/AdHocFragmentsIT.java b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/AdHocFragmentsIT.java
index 083b39bec0..e0007fe853 100644
--- a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/AdHocFragmentsIT.java
+++ b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/AdHocFragmentsIT.java
@@ -64,7 +64,7 @@ class AdHocFragmentsIT {
.queryParam("user", "john")
.queryParam("group", "manager")
.when()
- .post("/AdHocFragments/{pid}/AdHocTask1", id)
+ .post("/AdHocFragments/{pid}/AdHocTask1/trigger", id)
.then()
.statusCode(201)
.header("Location", not(emptyOrNullString()))
diff --git a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java
index d5a5513a16..17cac753e5 100644
--- a/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java
+++ b/quarkus/integration-tests/integration-tests-quarkus-processes/src/test/java/org/kie/kogito/integrationtests/quarkus/TaskIT.java
@@ -20,22 +20,21 @@ package org.kie.kogito.integrationtests.quarkus;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.acme.travels.Traveller;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.kie.kogito.task.management.service.TaskInfo;
import org.kie.kogito.usertask.model.AttachmentInfo;
+import org.kie.kogito.usertask.model.CommentInfo;
import io.quarkus.test.junit.QuarkusIntegrationTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
-import jakarta.ws.rs.core.UriBuilder;
-
import static io.restassured.RestAssured.given;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchema;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -160,11 +159,10 @@ class TaskIT {
}
@Test
- @Disabled("Revisited after ht endpoints")
void testCommentAndAttachment() {
- Traveller traveller = new Traveller("pepe", "rubiales", "pepe.rubiales@gmail.com", "Spanish");
+ Traveller traveller = new Traveller("pepe", "rubiales", "pepe.rubiales@gmail.com", "Spanish", null);
- String processId = given()
+ given()
.contentType(ContentType.JSON)
.when()
.body(Collections.singletonMap("traveller", traveller))
@@ -176,154 +174,131 @@ class TaskIT {
String taskId = given()
.contentType(ContentType.JSON)
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.when()
- .get("/approvals/{processId}/tasks")
+ .get("/usertasks/instance")
.then()
.statusCode(200)
.extract()
.path("[0].id");
- final String commentId = given().contentType(ContentType.TEXT)
+ final String commentId = given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
- .body("We need to act")
- .post("/approvals/{processId}/firstLineApproval/{taskId}/comments")
+ .body(new CommentInfo("We need to act"))
+ .post("/usertasks/instance/{taskId}/comments")
.then()
- .statusCode(201)
+ .statusCode(200)
.extract()
.path("id");
final String commentText = "We have done everything we can";
- given().contentType(ContentType.TEXT)
+ given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .body(commentText)
- .put("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .body(new CommentInfo(commentText))
+ .put("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200);
assertEquals(commentText, given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .get("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200).extract().path("content"));
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .delete("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200);
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
- .queryParam("group", "managers")
- .pathParam("processId", processId)
- .pathParam("taskId", taskId)
- .pathParam("commentId", commentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
- .then()
- .statusCode(404);
-
- given().contentType(ContentType.JSON)
- .when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .get("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(404);
final String attachmentId = given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
- .body(new AttachmentInfo(UriBuilder.fromPath("pepito.txt").scheme("file").build(), "pepito.txt"))
- .post("/approvals/{processId}/firstLineApproval/{taskId}/attachments")
+ .body(new AttachmentInfo(URI.create("pepito.txt"), "pepito.txt"))
+ .post("/usertasks/instance/{taskId}/attachments")
.then()
- .statusCode(201)
+ .statusCode(200)
.extract()
.path("id");
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .body(new AttachmentInfo(UriBuilder.fromPath("/home/fulanito.txt").scheme("file").build()))
- .put("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .body(new AttachmentInfo(URI.create("file:/home/fulanito.txt")))
+ .put("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200);
given().contentType(
ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .get("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200).body("name", equalTo("fulanito.txt")).body("content", equalTo(
"file:/home/fulanito.txt"));
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .delete("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200);
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .get("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(404);
given().contentType(ContentType.JSON)
.when()
- .queryParam("user", "manager")
+ .queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .delete("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(404);
}
diff --git a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/AdHocFragmentsTest.java b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/AdHocFragmentsTest.java
index cec3f11a37..0fb04479a5 100644
--- a/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/AdHocFragmentsTest.java
+++ b/springboot/integration-tests/integration-tests-springboot-processes-it/src/test/java/org/kie/kogito/integrationtests/springboot/AdHocFragmentsTest.java
@@ -58,7 +58,7 @@ class AdHocFragmentsTest extends BaseRestTest {
.queryParam("user", "john")
.queryParam("group", "manager")
.when()
- .post("/AdHocFragments/{pid}/AdHocTask1", id)
+ .post("/AdHocFragments/{pid}/AdHocTask1/trigger", id)
.then()
.statusCode(201)
.header("Location", not(emptyOrNullString()))
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 970968e649..5da1e8e6cd 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
@@ -31,11 +31,11 @@ import java.util.stream.Stream;
import org.acme.travels.Address;
import org.acme.travels.Traveller;
import org.jbpm.util.JsonSchemaUtil;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.kie.kogito.task.management.service.TaskInfo;
import org.kie.kogito.usertask.model.AttachmentInfo;
+import org.kie.kogito.usertask.model.CommentInfo;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -98,7 +98,7 @@ public class TaskTest extends BaseRestTest {
@Test
void testJsonSchemaFiles() {
- long expectedJsonSchemas = 23;
+ long expectedJsonSchemas = 25;
Path jsonDir = Paths.get("target", "classes").resolve(JsonSchemaUtil.getJsonDir());
try (Stream<Path> paths = Files.walk(jsonDir)) {
long generatedJsonSchemas = paths
@@ -111,11 +111,10 @@ public class TaskTest extends BaseRestTest {
}
@Test
- @Disabled("Revisited after ht endpoints")
void testCommentAndAttachment() {
Traveller traveller = new Traveller("pepe", "rubiales", "pepe.rubiales@gmail.com", "Spanish", null);
- String processId = given()
+ given()
.contentType(ContentType.JSON)
.when()
.body(Collections.singletonMap("traveller", traveller))
@@ -129,37 +128,34 @@ public class TaskTest extends BaseRestTest {
.contentType(ContentType.JSON)
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.when()
- .get("/approvals/{processId}/tasks")
+ .get("/usertasks/instance")
.then()
.statusCode(200)
.extract()
.path("[0].id");
- final String commentId = given().contentType(ContentType.TEXT)
+ final String commentId = given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
- .body("We need to act")
- .post("/approvals/{processId}/firstLineApproval/{taskId}/comments")
+ .body(new CommentInfo("We need to act"))
+ .post("/usertasks/instance/{taskId}/comments")
.then()
- .statusCode(201)
+ .statusCode(200)
.extract()
.path("id");
final String commentText = "We have done everything we can";
- given().contentType(ContentType.TEXT)
+ given().contentType(ContentType.JSON)
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .body(commentText)
- .put("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .body(new CommentInfo(commentText))
+ .put("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200);
@@ -167,10 +163,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .get("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200).extract().path("content"));
@@ -178,10 +173,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .delete("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(200);
@@ -189,10 +183,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("commentId", commentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/comments/{commentId}")
+ .get("/usertasks/instance/{taskId}/comments/{commentId}")
.then()
.statusCode(404);
@@ -200,12 +193,11 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.body(new AttachmentInfo(URI.create("pepito.txt"), "pepito.txt"))
- .post("/approvals/{processId}/firstLineApproval/{taskId}/attachments")
+ .post("/usertasks/instance/{taskId}/attachments")
.then()
- .statusCode(201)
+ .statusCode(200)
.extract()
.path("id");
@@ -213,11 +205,10 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
.body(new AttachmentInfo(URI.create("file:/home/fulanito.txt")))
- .put("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .put("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200);
@@ -226,10 +217,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .get("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200).body("name", equalTo("fulanito.txt")).body("content", equalTo(
"file:/home/fulanito.txt"));
@@ -238,10 +228,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .delete("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(200);
@@ -249,10 +238,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .get("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .get("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(404);
@@ -260,10 +248,9 @@ public class TaskTest extends BaseRestTest {
.when()
.queryParam("user", "admin")
.queryParam("group", "managers")
- .pathParam("processId", processId)
.pathParam("taskId", taskId)
.pathParam("attachmentId", attachmentId)
- .delete("/approvals/{processId}/firstLineApproval/{taskId}/attachments/{attachmentId}")
+ .delete("/usertasks/instance/{taskId}/attachments/{attachmentId}")
.then()
.statusCode(404);
}
diff --git a/springboot/integration-tests/integration-tests-springboot-processes-persistence-it/integration-tests-springboot-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java b/springboot/integration-tests/integration-tests-springboot-processes-persistence-it/integration-tests-springboot-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
index 7ef8b40a8e..15c79f08f9 100644
--- a/springboot/integration-tests/integration-tests-springboot-processes-persistence-it/integration-tests-springboot-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
+++ b/springboot/integration-tests/integration-tests-springboot-processes-persistence-it/integration-tests-springboot-processes-persistence-common/src/test/java/org/kie/kogito/it/PersistenceTest.java
@@ -46,6 +46,7 @@ import static org.awaitility.Awaitility.await;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.emptyOrNullString;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -303,19 +304,31 @@ public abstract class PersistenceTest {
.extract()
.path("id");
- given().contentType(ContentType.JSON)
+ String location = given().contentType(ContentType.JSON)
.pathParam("pId", pId)
+ .queryParam("user", "user")
+ .queryParam("group", "agroup")
.when()
- .get("/AdHocProcess/{pId}")
+ .post("/AdHocProcess/{pId}/CloseTask/trigger")
.then()
- .statusCode(200);
+ .log().everything()
+ .statusCode(201)
+ .header("Location", notNullValue())
+ .extract()
+ .header("Location");
- given().contentType(ContentType.JSON)
- .pathParam("pId", pId)
+ String taskId = location.substring(location.lastIndexOf("/") + 1);
+
+ given()
+ .queryParam("user", "user")
+ .queryParam("group", "agroup")
+ .contentType(ContentType.JSON)
.when()
- .delete("/AdHocProcess/{pId}")
+ .body(Map.of("status", "closed"))
+ .post("/AdHocProcess/{pId}/CloseTask/{taskId}", pId, taskId)
.then()
- .statusCode(200);
+ .statusCode(200)
+ .body("status", equalTo("closed"));
given().contentType(ContentType.JSON)
.pathParam("pId", pId)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org