Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

JBPM-3848 - Auto assigning tasks to same actor when they are part of …

…a swimlane
  • Loading branch information...
commit 48ed6c67f7fd2a649021880d6738555757e1ca5a 1 parent e8fbea9
Maciej Swiderski mswiderski authored
2  jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/HumanTaskNodeInstance.java
View
@@ -49,6 +49,7 @@ protected String assignWorkItem(WorkItem workItem) {
SwimlaneContextInstance swimlaneContextInstance = getSwimlaneContextInstance(swimlaneName);
if (swimlaneContextInstance != null) {
actorId = swimlaneContextInstance.getActorId(swimlaneName);
+ workItem.setParameter("SwimlaneActorId", actorId);
}
// if no actor can be assigned based on the swimlane, check whether an
// actor is specified for this human task
@@ -56,6 +57,7 @@ protected String assignWorkItem(WorkItem workItem) {
actorId = (String) workItem.getParameter("ActorId");
if (actorId != null && swimlaneContextInstance != null) {
swimlaneContextInstance.setActorId(swimlaneName, actorId);
+ workItem.setParameter("SwimlaneActorId", actorId);
}
}
return actorId;
9 ...an-task/jbpm-human-task-core/src/main/java/org/jbpm/process/workitem/wsht/AbstractHTWorkItemHandler.java
View
@@ -146,6 +146,15 @@ protected ContentData createTaskContentBasedOnWorkItemParams(WorkItem workItem)
}
return content;
}
+
+ protected boolean isAutoClaim(WorkItem workItem, Task task) {
+ String swimlaneUser = (String) workItem.getParameter("SwimlaneActorId");
+ if (swimlaneUser != null && !"".equals(swimlaneUser) && task.getPeopleAssignments().getPotentialOwners().size() > 1) {
+ return true;
+ }
+
+ return false;
+ }
public abstract void executeWorkItem(WorkItem workItem, WorkItemManager manager);
38 ...ask/jbpm-human-task-core/src/main/java/org/jbpm/process/workitem/wsht/AsyncGenericHTWorkItemHandler.java
View
@@ -19,10 +19,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.kie.runtime.KnowledgeRuntime;
-import org.kie.runtime.StatefulKnowledgeSession;
-import org.kie.runtime.process.WorkItem;
-import org.kie.runtime.process.WorkItemManager;
import org.jbpm.eventmessaging.EventResponseHandler;
import org.jbpm.eventmessaging.Payload;
import org.jbpm.task.AsyncTaskService;
@@ -39,8 +35,13 @@
import org.jbpm.task.service.TaskClientHandler.GetContentResponseHandler;
import org.jbpm.task.service.TaskClientHandler.GetTaskResponseHandler;
import org.jbpm.task.service.responsehandlers.AbstractBaseResponseHandler;
+import org.jbpm.task.service.responsehandlers.BlockingTaskOperationResponseHandler;
import org.jbpm.task.utils.ContentMarshallerHelper;
import org.jbpm.task.utils.OnErrorAction;
+import org.kie.runtime.KnowledgeRuntime;
+import org.kie.runtime.StatefulKnowledgeSession;
+import org.kie.runtime.process.WorkItem;
+import org.kie.runtime.process.WorkItemManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -164,9 +165,14 @@ public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
Task task = createTaskBasedOnWorkItemParams(workItem);
ContentData content = createTaskContentBasedOnWorkItemParams(workItem);
connect();
- client.addTask(task, content, new TaskAddedHandler(workItem.getId()));
-
+ TaskAddedHandler taskAddedHandler = new TaskAddedHandler(workItem.getId());
+
+ if (isAutoClaim(workItem, task)) {
+ taskAddedHandler = new TaskAddedAutoClaimHandler(workItem.getId(), (String) workItem.getParameter("SwimlaneActorId"));
+ }
+
+ client.addTask(task, content, taskAddedHandler);
}
@Override
@@ -186,12 +192,14 @@ public void setOwningSessionOnly(boolean owningSessionOnly) {
private class TaskAddedHandler extends AbstractBaseResponseHandler implements TaskClientHandler.AddTaskResponseHandler {
private long workItemId;
+ private long taskId;
public TaskAddedHandler(long workItemId) {
this.workItemId = workItemId;
}
public void execute(long taskId) {
+ this.taskId = taskId;
}
@Override
@@ -211,6 +219,24 @@ public synchronized void setError(RuntimeException error) {
logger.error(logMsg.toString(), getError());
}
}
+
+ public long getTaskId() {
+ return this.taskId;
+ }
+ }
+
+ private class TaskAddedAutoClaimHandler extends TaskAddedHandler implements TaskClientHandler.AddTaskResponseHandler {
+
+ private String claimUser;
+
+ public TaskAddedAutoClaimHandler(long workItemId, String claimUser) {
+ super(workItemId);
+ this.claimUser = claimUser;
+ }
+
+ public void execute(long taskId) {
+ client.claim(taskId, claimUser, new BlockingTaskOperationResponseHandler());
+ }
}
private class TaskCompletedHandler extends AbstractBaseResponseHandler implements EventResponseHandler {
14 ...man-task/jbpm-human-task-core/src/main/java/org/jbpm/process/workitem/wsht/GenericHTWorkItemHandler.java
View
@@ -180,6 +180,9 @@ public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
connect();
try {
client.addTask(task, content);
+ if (isAutoClaim(workItem, task)) {
+ autoClaim(workItem.getId(), (String) workItem.getParameter("SwimlaneActorId"));
+ }
} catch (Exception e) {
if (action.equals(OnErrorAction.ABORT)) {
manager.abortWorkItem(workItem.getId());
@@ -209,6 +212,17 @@ public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
}
}
}
+
+ public void autoClaim(long workItemId, String claimUser) {
+ Task task = client.getTaskByWorkItemId(workItemId);
+ if (task != null) {
+ try {
+ client.claim(task.getId(), claimUser);
+ } catch (PermissionDeniedException e) {
+ logger.info(e.getMessage());
+ }
+ }
+ }
public boolean isOwningSessionOnly() {
return owningSessionOnly;
77 jbpm-test/src/test/java/org/jbpm/ProcessPersistenceHumanTaskOnLaneTest.java
View
@@ -0,0 +1,77 @@
+package org.jbpm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.InitialContext;
+import javax.transaction.UserTransaction;
+
+import org.kie.runtime.StatefulKnowledgeSession;
+import org.kie.runtime.process.ProcessInstance;
+import org.jbpm.task.Status;
+import org.jbpm.task.TaskService;
+import org.jbpm.task.query.TaskSummary;
+import org.jbpm.test.JbpmJUnitTestCase;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a sample file to test a process.
+ */
+public class ProcessPersistenceHumanTaskOnLaneTest extends JbpmJUnitTestCase {
+
+ private Logger testLogger = LoggerFactory.getLogger(ProcessPersistenceHumanTaskOnLaneTest.class);
+
+ public ProcessPersistenceHumanTaskOnLaneTest() {
+ super(true);
+ setPersistence(true);
+ }
+
+ @Test
+ public void testProcess() throws Exception {
+ StatefulKnowledgeSession ksession = createKnowledgeSession("HumanTaskOnLane.bpmn2");
+ TaskService taskService = getTaskService(ksession);
+
+ ProcessInstance processInstance = ksession.startProcess("UserTask");
+
+ assertProcessInstanceActive(processInstance.getId(), ksession);
+
+
+ // simulating a system restart
+ ksession = restoreSession(ksession, true);
+ taskService = getTaskService(ksession);
+
+ // let john execute Task 1
+ String taskUser = "john";
+ String locale = "en-UK";
+ List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner(taskUser, locale);
+ assertEquals(1, list.size());
+
+ TaskSummary task = list.get(0);
+ taskService.claim(task.getId(), taskUser);
+ taskService.start(task.getId(), taskUser);
+ taskService.complete(task.getId(), taskUser, null);
+
+
+
+ // simulating a system restart
+ ksession = restoreSession(ksession, true);
+ taskService = getTaskService(ksession);
+ List<Status> reservedOnly = new ArrayList<Status>();
+ reservedOnly.add(Status.Reserved);
+
+
+ list = taskService.getTasksAssignedAsPotentialOwnerByStatus(taskUser, reservedOnly, locale);
+ assertEquals(1, list.size());
+
+ task = list.get(0);
+ taskService.start(task.getId(), taskUser);
+ taskService.complete(task.getId(), taskUser, null);
+
+
+ assertProcessInstanceCompleted(processInstance.getId(), ksession);
+ }
+
+
+}
199 jbpm-test/src/test/resources/HumanTaskOnLane.bpmn2
View
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions id="Definition"
+ targetNamespace="http://www.example.org/MinimalExample"
+ typeLanguage="http://www.java.com/javaTypes"
+ expressionLanguage="http://www.mvel.org/2.0"
+ xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
+ xmlns:g="http://www.jboss.org/drools/flow/gpd"
+ xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
+ xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
+ xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
+ xmlns:tns="http://www.jboss.org/drools">
+
+ <process processType="Private" isExecutable="true" id="UserTask" name="User Task" >
+
+ <laneSet>
+ <lane name="MyLane" >
+ <flowNodeRef>_2</flowNodeRef>
+ <flowNodeRef>_3</flowNodeRef>
+ </lane>
+ </laneSet>
+ <!-- nodes -->
+ <startEvent id="_1" name="StartProcess" />
+ <userTask id="_2" name="Hello" >
+ <ioSpecification>
+ <dataInput id="_2_CommentInput" name="Comment" />
+ <dataInput id="_2_SkippableInput" name="Skippable" />
+ <dataInput id="_2_LocaleInput" name="Locale" />
+ <dataInput id="_2_TaskNameInput" name="TaskName" />
+ <dataInput id="_2_GroupIdInput" name="GroupId" />
+ <dataInput id="_2_PriorityInput" name="Priority" />
+ <inputSet>
+ <dataInputRefs>_2_CommentInput</dataInputRefs>
+ <dataInputRefs>_2_SkippableInput</dataInputRefs>
+ <dataInputRefs>_2_LocaleInput</dataInputRefs>
+ <dataInputRefs>_2_TaskNameInput</dataInputRefs>
+ <dataInputRefs>_2_GroupIdInput</dataInputRefs>
+ <dataInputRefs>_2_PriorityInput</dataInputRefs>
+ </inputSet>
+ <outputSet>
+ </outputSet>
+ </ioSpecification>
+ <dataInputAssociation>
+ <targetRef>_2_CommentInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_2_CommentInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_2_SkippableInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">false</from>
+ <to xsi:type="tFormalExpression">_2_SkippableInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_2_LocaleInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">en-UK</from>
+ <to xsi:type="tFormalExpression">_2_LocaleInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_2_TaskNameInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_2_TaskNameInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_2_GroupIdInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">PM,HR</from>
+ <to xsi:type="tFormalExpression">_2_GroupIdInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_2_PriorityInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_2_PriorityInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <potentialOwner>
+ <resourceAssignmentExpression>
+ <formalExpression></formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ </userTask>
+ <userTask id="_3" name="Goodbye" >
+ <ioSpecification>
+ <dataInput id="_3_CommentInput" name="Comment" />
+ <dataInput id="_3_SkippableInput" name="Skippable" />
+ <dataInput id="_3_LocaleInput" name="Locale" />
+ <dataInput id="_3_TaskNameInput" name="TaskName" />
+ <dataInput id="_3_GroupIdInput" name="GroupId" />
+ <dataInput id="_3_PriorityInput" name="Priority" />
+ <inputSet>
+ <dataInputRefs>_3_CommentInput</dataInputRefs>
+ <dataInputRefs>_3_SkippableInput</dataInputRefs>
+ <dataInputRefs>_3_LocaleInput</dataInputRefs>
+ <dataInputRefs>_3_TaskNameInput</dataInputRefs>
+ <dataInputRefs>_3_GroupIdInput</dataInputRefs>
+ <dataInputRefs>_3_PriorityInput</dataInputRefs>
+ </inputSet>
+ <outputSet>
+ </outputSet>
+ </ioSpecification>
+ <dataInputAssociation>
+ <targetRef>_3_CommentInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_3_CommentInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_3_SkippableInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">false</from>
+ <to xsi:type="tFormalExpression">_3_SkippableInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_3_LocaleInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">en-UK</from>
+ <to xsi:type="tFormalExpression">_3_LocaleInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_3_TaskNameInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_3_TaskNameInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_3_GroupIdInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression">PM,HR</from>
+ <to xsi:type="tFormalExpression">_3_GroupIdInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <dataInputAssociation>
+ <targetRef>_3_PriorityInput</targetRef>
+ <assignment>
+ <from xsi:type="tFormalExpression"></from>
+ <to xsi:type="tFormalExpression">_3_PriorityInput</to>
+ </assignment>
+ </dataInputAssociation>
+ <potentialOwner>
+ <resourceAssignmentExpression>
+ <formalExpression></formalExpression>
+ </resourceAssignmentExpression>
+ </potentialOwner>
+ </userTask>
+ <endEvent id="_4" name="EndProcess" >
+ <terminateEventDefinition />
+ </endEvent>
+
+ <!-- connections -->
+ <sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
+ <sequenceFlow id="_2-_3" sourceRef="_2" targetRef="_3" />
+ <sequenceFlow id="_3-_4" sourceRef="_3" targetRef="_4" />
+
+ </process>
+
+ <bpmndi:BPMNDiagram>
+ <bpmndi:BPMNPlane bpmnElement="UserTask" >
+ <bpmndi:BPMNShape bpmnElement="_1" >
+ <dc:Bounds x="16" y="16" width="48" height="48" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape bpmnElement="_2" >
+ <dc:Bounds x="96" y="16" width="100" height="48" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape bpmnElement="_3" >
+ <dc:Bounds x="228" y="16" width="100" height="48" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNShape bpmnElement="_4" >
+ <dc:Bounds x="360" y="16" width="48" height="48" />
+ </bpmndi:BPMNShape>
+ <bpmndi:BPMNEdge bpmnElement="_1-_2" >
+ <di:waypoint x="40" y="40" />
+ <di:waypoint x="146" y="40" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge bpmnElement="_2-_3" >
+ <di:waypoint x="146" y="40" />
+ <di:waypoint x="278" y="40" />
+ </bpmndi:BPMNEdge>
+ <bpmndi:BPMNEdge bpmnElement="_3-_4" >
+ <di:waypoint x="278" y="40" />
+ <di:waypoint x="384" y="40" />
+ </bpmndi:BPMNEdge>
+ </bpmndi:BPMNPlane>
+ </bpmndi:BPMNDiagram>
+
+</definitions>
Please sign in to comment.
Something went wrong with that request. Please try again.