You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 28 Next »

Intro

This concept is meant to illustrate what is needed in technical terms in order to implement the new UX Pulse concept with particular reference to the workflow.

Problem

At the moment, work items or tasks as we will call them from now on (work item is very jBPM specific) are treated like any informational Pulse message (i.e. errors, warnings) and there's no way to know what the status of a given item is, unless one tries to perform an action on it. What's worse, one can delete a work item without handling it, which might basically break the workflow, leaving a process pending forever, unless some other user in the same group the task has been assigned to, takes it over. 

The UX concept puts special emphasis on the handling of workflow tasks, how to display their current state (i.e. who's in charge, whether it has been already handled or not, what the outcome was, etc.), how to perform the necessary actions so that each workflow process can be successfully carried through. It also worth mentioning that, as specified in the UX concept "The user does not see the entire work flow and its current state in Pulse - there's actually a separate app for that".

 

Workflow and Pulse interaction

Here we briefly sketch how Workflow works and how it currently interacts with Pulse 

Workflow
  • workflow process defined as bpmn 2.0 (Business Process Model and Notation) file
  • each process is registered by name at startup and made available to the workflow engine, see /modules/workflow/workflows
  • each step in the workflow is a workitem defined in a wid (work item definition, a jBPM specific file), e.g. MgnlDefinitions.wid
  • each work item is mapped to a work item handler. Handlers are under workItemHandlers nodes, eg. /modules/workflow-jbpm/workItemHandlers
  • handlers implement WorkItemHandler, they are a Java class executed at runtime when the workflow reaches the corresponding work item or step
  • workflows are launched via commands, e.g. /modules/workflow/workflows/activate which has a workflow property referring to the name of the workflow to launch
Interaction example with Pulse
  • activation workflow is defined as SimpleActivation.bpmn 

  • its first workitem is called publishNotification which maps to a NotificationWorkItemHandler class
  • when activation workflow is started, publishNotification is executed
  • publishNotification populates a map of arbitrary data with
    • the work item id 
    • the process id this work item belongs to
    • who started the process
    • who's been assigned to
    • the path to activate
    • if activation is recursive
    • publication date in case of scheduled activation
    • the message view to handle the item in Pulse
  • publishNotification creates a Message with the above data and sends it to Pulse
  • user opens the message in Pulse and decides to approve or reject
    • in either case a CompleteTaskAction is triggered and the decision is passed back to the workflow engine in a results map

Tasks inbox

Of the many new things introduced by the Pulse UX concept, it was agreed that the first thing to tackle, which would solve most of the problems currently affecting the workflow, is the new Tasks inbox. As illustrated by the mockup below, the main novelty is the sub tabs (all items, not started, ongoing, done) introducing filters displaying the status of the each task assigned to the current user or the group he or she is part of. An additional status column has been introduced too.

 

  • we want to be able to display tasks independent of the presence of an underlying workflow engine
    • i.e a one-shot task (e.g. a short translation assignment given to a particular user) for which setting up a whole workflow process would be overkill.
  • we want to be able to retrieve the status of a given task
  • ideally we would like the list to be updated automatically as new tasks arrive, are taken, updated or completed. 

jBPM User Task or Magnolia Task?

As the plain messages we currently use don't work well with tasks, we figured out two options

  1. Using jBPM User Tasks
    • PRO
      • would be the "proper" way to implement manual tasks in jBPM (we currently fake them with a Service Task, that is a task usually performed by an automated system, which sends a message to Pulse) 
      • we'd take advantage of all the properties already available there, such as groupId, actorId, comment, etc., no need to reinvent the wheel
    • CONTRA
      • no clear documentation on how to integrate it - one is basically left with the source code only. TODO verify that this claim is actually true
      • what about tasks independent of a workflow engine presence?
      • how to make the workflow engine aware of Magnolia groups and users?
  2. Extending the Message class into a generic Task
    • PRO
      • would handle any type of task, regardless of a workflow engine presence
      • easier to persist and query, most of the job already being done by the MessageStore API
    • CONTRA
      • would make our workflow solution still rely on our "fake" UserTask

A basic sequence diagram showing how Workflow and Pulse can collaborate.

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.

org.jbpm.runtime.manager.impl.DefaultRegisterableItemsFactory
    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
HTWorkItemHandler
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. 

How is a human task completed (manager.completeWorkItem()) and the process signaled to proceed?

org.jbpm.services.task.wih.ExternalTaskEventListener#processTaskState


 

 

  • No labels