Flowable getting started series article 42 - user tasks

1. Description

A user task is used to simulate work that needs to be done by people. When the process execution reaches such a user task, a new task is created in the task list of any user or group assigned to the task.

2. Graphical representation

The user task is visualized as a typical task (rounded rectangle), with a small user icon in the upper left corner.

3. XML representation

User tasks are defined in XML as follows. The ID is a required attribute and the name attribute is optional.

<userTask id="theTask" name="Important task" />

User tasks can also have a description. In fact, any BPMN 2.0 element can have a description. The description is defined by adding document elements.

<userTask id="theTask" name="Schedule meeting" >
<documentation>
	Schedule an engineering meeting for next week with the new hire.
</documentation>

The description text can be obtained from the task in standard Java mode:

 task.getDescription()

4. Deadline

Each task has a field indicating the due date of the task. The query API can be used to query tasks that expire before or after a given date.

There is an activity extension that allows you to specify an expression in the task definition to set the initial expiration date when the task is created. The expression should always resolve to java.util.Date, java.util.String (ISO8601 formatted), ISO8601 time duration (for example, PT50M), or null. For example, you can use the date entered in the previous form in the process, or the date calculated in the previous service task. If duration is used, the expiration date is calculated based on the current time and incremented by a given time period. For example, when "PT30M" is used as dueDate, the task will be completed within 30 minutes from now.

<userTask id="theTask" name="Important task" flowable:dueDate="${dateVariable}"/>

The deadline of a task can also be changed by using TaskService or TaskListener to use pass through.

5. User assignment

User tasks can be assigned directly to users. This is done by defining a humanPerformer child element. Such a human performer definition requires a resource assignment expression that actually defines the user. Currently only formalExpressions are supported.

<process >
...
<userTask id='theTask' name='important task' >
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>kermit</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>

Only one user can be assigned as a human performer of a task. In mobile terms, this user is referred to as the assignee. Tasks with assignees are not visible in other people's task list and can be found in the assignee's personal task list.

Tasks directly assigned to users can be obtained through TaskService, as shown below:

 List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();

Tasks can also be placed in the candidate's task list. In this case, you must use the potentialOwner structure. The usage is similar to the humanPerformer construct. Please note that it is necessary to
Specify whether it is a user or a group defined for each element in the formal expression (the engine cannot guess this).

<process >
...
<userTask id='theTask' name='important task' >
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(management)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>

Tasks defined using the potential owner construct can be retrieved in the following ways (or TaskQuery usage similar to the assignee's task):

List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");

This will retrieve all tasks for which kermit is a candidate user, in other words, the formal expression contains the user (kermit). If kermit is a member of the group and uses Flowable to identify the component,
This will also retrieve all tasks assigned to the group to which kermit is a member (for example, group (Administration)). The user's group is resolved at run time, which can be done through IdentityService
Administration.

If no details are given about whether the given text string is a user or a group, the engine defaults to a group. The following is the same as when announcing the grouping (Accounting).

<formalExpression>accountancy</formalExpression>

6. Flow extension for task assignment

Obviously, the assignment of users and groups is quite troublesome for assigning uncomplicated use cases. To avoid these complexities, custom extensions on user tasks are possible.

  • Assignee attribute: this custom extension allows a given user to be directly assigned to a task.
<userTask id="theTask" name="my task" flowable:assignee="kermit" />

This is exactly the same as using the humanPerformer construct defined above.

  • candidateUsers property: this custom extension makes a given user a candidate for a task.
<userTask id="theTask" name="my task" flowable:candidateUsers="kermit, gonzo" />

This is exactly the same as using the potentialOwner structure defined above. Note that, as in the case of a potential owner construct, there is no need to use a user (kermit) declaration because this attribute can only be used by users.

  • candidateGroups property: this custom extension makes a given component a candidate for a task.
<userTask id="theTask" name="my task" flowable:candidateGroups="management, accountancy" />

This is exactly the same as using the potentialOwner structure defined above. Note that, as in the case of a potential owner construct, it is not necessary to use a group (administrative) declaration because this attribute only
Can be used for groups.

  • Both candidate users and candidate groups can be defined on the same user task.

Note: Although Flowable provides an identity management component exposed through IdentityService, it does not check whether the identity component knows the provided user. This is to allow Flowable to integrate with existing identity management solutions when embedding applications.

7. Custom identity link type

The BPMN standard supports a single assigned user or human performer or a group of users that constitute a pool of potential users, as defined in user assignments. In addition, Flowable defines the extended attribute element of a user task, which can represent the assignee or candidate of the task.

The supported Flowable identity link types are:

public class IdentityLinkType {
	/* Flowable native roles */
	public static final String ASSIGNEE = "assignee";
	public static final String CANDIDATE = "candidate";
	public static final String OWNER = "owner";
	public static final String STARTER = "starter";
	public static final String PARTICIPANT = "participant";
}

The BPMN standard and the Flowable example authorization IDs are users and groups. As described in the previous section, the Flowable identity management implementation is not suitable for production use, but should be extended according to the supported authorization scheme.

If you need other link types, you can define a custom resource as an extension element using the following syntax:

<userTask id="theTask" name="make profit">
<extensionElements>
<flowable:customResource flowable:name="businessAdministrator">
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(management)</formalExpression>
</resourceAssignmentExpression>
</flowable:customResource>
</extensionElements>
</userTask>

The custom link expression is added to the TaskDefinition class:

protected Map<String, Set<Expression>> customUserIdentityLinkExpressions =
        new HashMap<String, Set<Expression>>();
protected Map<String, Set<Expression>> customGroupIdentityLinkExpressions =
        new HashMap<String, Set<Expression>>();
public Map<String, Set<Expression>> getCustomUserIdentityLinkExpressions() {
        return customUserIdentityLinkExpressions;
        }
public void addCustomUserIdentityLinkExpression(
        String identityLinkType, Set<Expression> idList) {
        customUserIdentityLinkExpressions.put(identityLinkType, idList);
        }
public Map<String, Set<Expression>> getCustomGroupIdentityLinkExpressions() {
        return customGroupIdentityLinkExpressions;
        }
public void addCustomGroupIdentityLinkExpression(
        String identityLinkType, Set<Expression> idList) {
        customGroupIdentityLinkExpressions.put(identityLinkType, idList);
        }

These are populated at run time by the UserTaskActivityBehavior handleAssignments method.

Finally, the IdentityLinkType class must be extended to support custom identification link types:

package com.yourco.engine.task;
public class IdentityLinkType extends org.flowable.engine.task.IdentityLinkType {
	public static final String ADMINISTRATOR = "administrator";
	public static final String EXCLUDED_OWNER = "excludedOwner";
}

8. Custom assignment via task listener

If the previous method is not enough, you can use the task listener to delegate to the custom assignment logic on the create event:

<userTask id="task1" name="My task" >
<extensionElements>
<flowable:taskListener event="create" class="org.flowable.MyAssignmentHandler" />
</extensionElements>
</userTask>

Pass the DelegateTask to the TaskListener for execution. You can set the assignee and candidate users / groups:

public class MyAssignmentHandler implements TaskListener {
	public void notify(DelegateTask delegateTask) {
		// Execute custom identity lookups here
		// and then for example call following methods:
		delegateTask.setAssignee("kermit");
		delegateTask.addCandidateUser("fozzie");
		delegateTask.addCandidateGroup("management");
		...
	}
}

When using Spring, you can use the custom assignment properties described above and delegate to Spring beans using a task listener with an expression that listens for task creation events. In the following example, the assignee will call the Spring bean on the setup. The emp parameter passed is a procedure variable >. findManagerOfEmployeeldapService

<userTask id="task" name="My Task" flowable:assignee="${ldapService.findManagerForEmployee(emp)}"/>

The same applies to candidate users and groups:

<userTask id="task" name="My Task" flowable:candidateUsers="${ldapService.findAllSales()}"/>

Note that this only works if the return type of the called method is String or Collection (for candidate users and groups):

public class FakeLdapService {
	public String findManagerForEmployee(String employee) {
		return "Kermit The Frog";
	}
	public List<String> findAllSales() {
		return Arrays.asList("kermit", "gonzo", "fozzie");
	}
}

The above article is from Pangu BPM Research Institute: http://vue.pangubpm.com/
Article translation submission: https://github.com/qiudaoke/flowable-userguide
For more articles, you can focus on WeChat official account:

Tags: Java Flowable oa bpm

Posted on Sun, 31 Oct 2021 19:29:49 -0400 by Arez