Page History
...
A sequence diagram showing a TaskManager between Workflow and Pulse
jBPM User Tasks
What is a User Task?
From the official jBPM documentation:
Processes can also involve tasks that need to be executed by human actors. A User Task represents an atomic task to be executed by a human actor. It should have one incoming connection and one outgoing connection. User Tasks can be used in combination with Swimlanes to assign multiple human tasks to similar actors. Refer to the chapter on human tasks for more details. A User Task is actually nothing more than a specific type of service node (of type "Human Task"). A User Task contains the following properties:
Instead of using human tasks for interacting with human actors Magnolia decided to leave this concept out and use Service Tasks for sending messages to The Pulse.
But what exactly is the difference between a Service Tasks and Human Tasks?
From a technical point of view: None.
Both Tasks are handled by a WorkItemHandler which implement the same interface.
When modelling your process it does matter. A User Task gives you much more possibilities to set parameters tailored for user interactions:
Further more User Tasks allow defining Swim lanes inside your process. A swim lane allows you to define multiple steps or user tasks inside your process to be automatically assigned to the first user who picks up the first task of the swim lane.
Human Task WorkItemHandler
The handler is simply registered in the RegisterableItemsFactory
using Human Task
as identifier. Magnolia's 5.3 version of workflow already provides a custom class called RegisteredItemsFactory
.
Code Block | ||||
---|---|---|---|---|
| ||||
public Map<String, WorkItemHandler> getWorkItemHandlers(RuntimeEngine runtime) {
WorkItemHandler handler = getHTWorkItemHandler(runtime);
defaultHandlers.put("Human Task", handler);
...
}
protected WorkItemHandler getHTWorkItemHandler(RuntimeEngine runtime) {
ExternalTaskEventListener listener = new ExternalTaskEventListener();
LocalHTWorkItemHandler humanTaskHandler = new LocalHTWorkItemHandler();
humanTaskHandler.setRuntimeManager(((RuntimeEngineImpl)runtime).getManager());
if (runtime.getTaskService() instanceof EventService) {
((EventService)runtime.getTaskService()).registerTaskEventListener(listener);
}
...
}
|
What the Handler does internally is:
- create a Task based on the parameters provided by the workItem
- create the ContentData based on parameters from the workItem (? This data is then altered by the user executing the task and later on appended as result map to the process)
- add the task to the TaskService
- claim the task is the task is part of a swim lane, otherwise an actor would have to manually claim it
Code Block | ||||
---|---|---|---|---|
| ||||
public class LocalHTWorkItemHandler extends AbstractHTWorkItemHandler {
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
Task task = createTaskBasedOnWorkItemParams(ksessionById, workItem);
ContentData content = createTaskContentBasedOnWorkItemParams(ksessionById, workItem);
try {
long taskId = ((InternalTaskService) runtime.getTaskService()).addTask(task, content);
if (isAutoClaim(workItem, task)) {
runtime.getTaskService().claim(taskId, (String) workItem.getParameter("SwimlaneActorId"));
}
}
...
}
} |
At this point the WorkitemHandler is finished. It does not complete the WorkItem and for now the process is paused at this stage. Even more the whole execution of the task is decoupled from the process execution and has a completely separated life cycle. This lifecycle is taken care of by the TaskService
.
TaskService
UML showing the default jBPM implementation
This diagram shows how User Tasks are persisted in JPA.
...