用户任务

概览

用户任务(User task) 是分配给用户或用户组的一种任务类型,在业务流程中需要手动完成。 用户任务是业务流中不可或缺的内容,参与者可以通过执行特定操作、 做出决策或提供输入的方式和流程进行交互。

单一执行人和分组

在 BPMN 中,只有执行人才能执行其中的任务。 当我们说“任务分配给了某个用户组”, 其实是表示这里的一组 潜在的执行人,而不是说执行人是一个 UserGroup 对象。 分组的某个人通过 领取 任务而成为真正的执行人。

图形表示法

用户任务在图中显示为一个典型的任务(圆角矩形),左上角有一个小的用户图标。

user task
XML 表示

用户任务在 XML 中的定义如下。 其中 id 属性必需,name 属性可选。

<userTask id="user-task-01" name="User task" />

属性

在 BPMN 建模器中,可以为用户任务设置下列属性:

属性

描述

Id

元素的标识符。自动生成,但是可以自己修改为更有意义的内容,以便提高日志的可读性。

Name

任务的名称,最多 255 个字符。任务一般使用 “动词+名词” 的方式命名,例如 “批准订单” 或 “下载发票”。

Due date

任务必须完成的时限。参考 到期时间。

Business calendar name

用于计算时限的工作日历名称。参考 使用工作日历。

Assignee

任务的执行人或候选人。参考 分配用户。

Form

任务的表单。参考 用户任务流程表单。

Multi instance

参考 多实例。

Task listeners

任务生命周期事件触发的监听器。参考 设置任务监听器。

Notifications

给任务执行人发送的通知。仅在安装了 通知 扩展组件时显示。

Execution listeners

参考 执行监听器。

Extension properties

参考 扩展属性。

Asynchronous execution

参考 异步执行属性。

  • Asynchronous

  • Exclusive

  • Asynchronous leave

  • Asynchronous leave exclusive

Jmix 3.1+

Documentation

参考 文档。

到期时间

用户任务中的 due date 参数指定任务必须完成的截止日期。 该参数对于管理业务流程中的时间敏感型活动至关重要。

设置截止日期不会启动任何自动操作。需要手动配置后续的操作。

设置到期时间

Due date 支持两种类型的设置:

  • 固定日期:填写将来的一个到期时间。 (如果填写的是过去的时间,则该时间会被忽略,任务显示已过期)。

  • 时长:从任务创建开始计算的一个时长。

事实上,到期时间的字段是一个文本框,流程引擎在运行时对其内容进行解析。 支持以下格式:

  • ISO8601 格式的文本字符串,表示固定日期或持续时间。

  • 以下类型的流程变量:

    • java.lang.String — 必须包含 ISO8601 格式的值。

    • java.util.Date — 必须包含日期值。

  • 在运行时可以解析为上述类型之一的表达式,例如 $/{someDateVariable/}。

  • 变量值为 null 并不会导致错误。而是表示任务没有指定截止日期。

  • 流程部署期间不会验证该参数。 但不正确的值将在运行时导致错误。

ISO 8601 示例

  • 固定时期时间:

    • 2024-02-01T08:40:37

    • 2050-01-01

  • 时长:

    • PT20M - 20 分钟

    • PT5H - 5 小时

    • PT3D - 3 天

编程时处理到期时间

到期时间参数可以通过 Task 类的方法处理:

Task task = taskService.createTaskQuery()
                .taskId("taskId").singleResult(); (1)
task.getDueDate(); (2)
task.setDueDate(null); (3)
taskService.saveTask(task); (4)
1  — 通过 ID 获取任务
2  — 获取到期时间
3  — 设置新的到期时间为 null
4  — 保存任务对象。

因此,可以根据业务逻辑动态修改任务的到期时间。 例如,任务的执行人可以申请将任务延时处理。

使用工作日历

项目中如果安装了 工作日历 扩展组件, 在 Web BPM 建模器 的 General 部分会显示如下内容:

busines calendar

这里可以从下拉列表中选择一个已配置的工作日历。 此时,只能将截止日期设置为持续时长,并且将根据工作日历计算经过的时间。

例如,用户在下午 4:00 收到了任务。 在工作日历中,标准的工作时间设置为上午 10:00 至下午 6:00, 而截止日期参数设置为 3 小时 (PT3H)。

在考虑了工作日历后,截止日期不会设置为晚上的 7:00,而会设置为第二个工作日的早上 7:00。 使用了工作日历后,仅计算工作时间。

使用工作日历时,时长只能按小时和分钟设置,不能按天设置。

XML 表示

带截止时间的用户任务:

<userTask id="Activity_0gsy9yk" name="User task"
    flowable:dueDate="PT3H" (1)
    flowable:businessCalendarName="test-calendar"> (2)
. . .
</userTask>
1  — 时长类型的截止时间
2  — 工作日历属性

详情请参阅 工作日历 扩展组件。

分配用户

任务要有执行人才能最终完成。 一个任务只能有 一个 执行人,此用户称为 assignee。

assignee 属性可以为空,即,没有用户可以在任务列表中看到此任务。 当设置了潜在执行人或 candidates 的列表时,此类任务通常被视为 分组任务。 此外,还可以使用管理页面或以编程方式在运行时设置执行人。

执行人来源

在 Jmix BPM 中,执行人来源(assignee source)是指一种在流程中选择用户作为任务执行人的机制。 有三种选项:

Expression

- 表达式。必须返回字符串,包含 username。

Process variable

- 流程变量。指向一个 User 实体的流程变量。

User provider

- 一个特定的 Java 类,带有返回 username 的方法。

assignee sources

表达式

表达式是默认的执行人来源。 需要编写一个表达式来获取执行人的 username。 例如,User 实体存在名为 manager 的流程变量中,则表达式可以是 ${manager.username}:

assign by expression
XML 表示
<userTask id="user-task-01" name="User task"
    flowable:assignee="${manager.username}"
    jmix:assigneeSource="expression"
    jmix:assigneeValue="${manager.username}" />

如果需要将一个任务直接分配给特定的用户,这里可以直接写该用户的 username:

assigne by expression direct

另外,也可以调用 Spring bean 的方法返回 username:

${smpl_MyBean.evaluateManager(methodParam1, 'methodParam2')}

流程变量

如果选择 Process variable 执行人源,则属性面板中将显示一个 ComboBox。其中可以选择 Entity 类型的字段和流程变量,这些实体类还要求实现了 UserDetails 接口。

预置的 initiator 变量

预置的 initiator 流程变量可以在建模时用来分配任务。包含启动流程的用户实体:

assignee initiator
XML 表示

下面是使用流程变量分配任务的示例:

<userTask id="user-task-01" name="User task"
    camunda:assignee="${initiator.username}"
    jmix:assigneeSource="processVariable"
    jmix:assigneeValue="initiator" />

如果流程是通过 API 或消息/信号启动的,则 initiator 变量未定义。 贸然使用会导致运行时错误。

可以通过下面的应用程序属性禁用 initiator 变量:

jmix.bpm.process-initiator-variable-enabled=false

还可以修改发起人属性的名称:

jmix.bpm.process-initiator-variable-name=manager

User Provider

如果需要通过复杂的逻辑确定任务的执行人,则建议使用 User provider. 此时,系统会加载已有的 user provider Java 类以供选择:

selecting user provider

User Provider 中需要包含一个或多个 String 返回类型的方法。 方法获取在建模器中指定的参数值,并返回可以作为任务执行人的用户名。

XML 表示

使用 User provider 的用户任务:

<userTask id="user-task" name="User task" jmix:assigneeSource="userProvider" jmix:assigneeValue="smpl_MyUserProvider">
  <extensionElements>
    <jmix:springBean beanName="smpl_MyUserProvider" methodName="getUser" />
  </extensionElements>
</userTask>

User provider 类是一个普通的 Spring bean,带有 @UserProvider 注解。 下面是一个 user provider 的示例,其中的方法会根据用户 email 的流程变量从数据库加载用户。

@UserProvider(value = "smpl_MyUserProvider", description = "Returns a user with the specified email")
public class MyUserProvider {

    @Autowired
    private DataManager dataManager;

    public String getUserByEmail(String parameter) {
        return dataManager.load(User.class)
                .query("select u from smpl_User u where u.email = :email")
                .parameter("email", parameter)
                .one()
                .getUsername();
    }
}

在 UserProvider 类中可以实现任意的业务逻辑。 例如,可以从角色或部门中选择一个不太忙的用户;选择下一个轮到的用户;或者从候选人里选择一个随机用户等。

编程式分配任务

如需编程式设置任务的执行人,可以使用 TaskService 的 setAssignee 方法。示例:

Task task = taskService.createTaskQuery()
                       .taskId("taskId")
                       .singleResult(); (1)

taskService.setAssignee(task.getId(), "jane"); (2)
1 通过 Query API 获取任务
2 通过 username 指定执行人

获取特定用户以分配的任务,可以用 TaskService 的下列方法:

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("jane") (1)
    .list();
1 username

候选用户和组

候选(Candidates) 表示可以领取/完成任务的用户和用户组(groups)。 当一个任务有多个候选人时,该任务会在所有候选人的任务列表展示。 第一个领取任务的候选人变成任务的执行人,并可以完成任务。 之后,其他候选人的任务列表中该任务不可见。

这里 “groups” 表示一组 User group 的编码。

领取组内任务

一种常见的情况是,我们不需要某个特定的用户去执行任务。 例如,对于一个经理来说,具体那个会计对他下达的命令做出决定并不重要。

在这种情况下,Jmix BPM 可以将任务分配给 候选人组 — 其中的任何成员都可以成为任务的执行人。 但该成员必须先领取任务。 领取任务是用户对任务所有权的一个操作。

有多个候选人的的任务会显示在每个候选人组任务(Group tasks)菜单的 我的任务(My tasks) 视图中。

my tasks claim

在任何候选人领取任务后,该任务将移至此用户的 已分配任务(Assigned tasks) 列表中,并从其他候选人的 组任务 表中移除。

claiming form

领取任务是,用户必须打开任务并执行以下操作之一:

  • 领取并继续(Claim and resume) - 用户成为任务执行人,任务表单将以正常模式重新打开,该用户可以继续填写表单。

  • 领取并关闭(Claim and close) - 用户成为任务执行人后关闭表单;该用户可以稍后在任务列表的 已分配任务 部分中找到该任务:

my tasks claimed task

编程式领取任务

通过 API 也可以为用户领取任务:

taskService.claim("taskId", "userId");

在建模器中设置候选人

点击下图所示的按钮可以编辑候选人组:

web modeler candidate groups

在打开的 候选人组编辑器 中,可以选择组的来源:

candidate groups sources
  • User groups - 从列表中选择用户组

  • User groups provider — 选择一个能返回用户组列表的特定 Java 类。

  • Expression — 从表达式返回用户组列表,例如,使用之前定义的流程变量。

用户组设置

If you have chosen a User groups option as a source, you can select any from existing user groups:

selecting candidate grouos

用户组 Provider

如果需要通过复杂的逻辑设置候选人组,最好选择 User groups provider 选项。

selecting user group provider

这种方式可以选择已创建的带有 @UserGroupListProvider 注解的一个 Java bean。 Bean 必须实现一个或多个返回 List<String> 表示用户组编码的方法。

@UserGroupListProvider 注解有两个属性:

  • value — 在建模器中显示的名称。

  • description — 方法说明,可选。

示例:

@UserGroupListProvider(value="allGroups",
                       description = "Returns a list of all groups")
public class MyGroupListProvider {

    @Autowired
    private UserGroupService userGroupService;

    public List<String> getAllUserGroups() {
        List<UserGroup> allUserGroups = userGroupService.getAllUserGroups();
        if (!allUserGroups.isEmpty()) {
            return allUserGroups.stream().map(UserGroup::getCode).toList();
        } else {
            return Collections.emptyList();
        }
    }
}

参阅 用户组 章节了解更多内容。

表达式设置

设置 BPMN 参数最通用的方法是表达式。 候选组也可以使用该方法:

candidate groups expression

候选用户选项

在 Web BPM 建模器 中设置候选用户与设置候选组类似。 以下是可以选择的来源:

candidate users options
  • Users — 从列表中选择用户

  • Users provider --选择一个能返回用户名列表的特定 Java 类。

  • Expression — 从表达式返回用户名列表。

用户列表 Provider

与 用户组 Provider 类似,可以通过编程方式获取候选用户列表, 对应的 Spring bean 需要带 @UserListProvider 注解:

candidate user list provider

示例:

@UserListProvider(value = "smpl_UserListProviderDemo",
                  description = "Get all users")
public class UserListProviderDemo {

    @Autowired
    private DataManager dataManager;
    @Autowired
    private SystemAuthenticator authenticator;

    public List<String> getAllUsers() {
        authenticator.begin();
        try {
            List<User> users = dataManager.load(User.class).all().list();
            return users.stream().map(User::getUsername).toList();
        } finally {
            authenticator.end();
        }
    }
}

表达式设置

可以使用流程模型中最通用的参数设置方法 — 表达式:

candidate users expression

例如,使用下面的表达式可以获取流程发起人的用户名:

${initiator.username}

同一个用户任务可以同时定义候选用户和候选用户组。

用户任务流程表单

用户任务可以配置一个 流程表单,协助执行人输入任务所需的数据。收集的数据可以在之后的流程中传递。

多实例

用户任务可以是多实例的。 详情请参阅 多实例活动 部分。

设置任务监听器

Jmix BPM 中的用户任务支持通过任务监听器对特定的事件执行自定义逻辑。 在用户任务触发特定的事件时, 任务监听器中的 Java 类或表达式将执行。

task listeners field

用户任务支持的事件监听器包括:

  • create:当用户任务创建时触发

  • assignment:当用户任务分配给一个用户或用户组时触发

  • complete:当完成用户任务时触发。

  • delete:当删除用户任务时触发。

如需为用户任务配置监听器,可以在 BPMN XML 中使用 flowable:taskListener 扩展元素, 或者用 addTaskListener Java API。

任务监听器为用户任务提供了一种强大的扩展机制, 可以在流程中集成自定义逻辑。 例如发送通知、更新外部系统, 或根据用户任务生命周期中的事件做额外的验证等等。

XML 表示
<userTask id="approve-invoice" name="Approve invoice" jmix:assigneeSource="expression">
  <extensionElements>
    . . .
    <flowable:taskListener class="com.company.demo.listener.ApproverAssignment" (1)
                           event="assignment" /> (2)
  </extensionElements>
 . . .
</userTask>
1 任务监听器类
2 任务事件

详情请参阅 任务监听器。

文档

为了给用户提供额外的信息,在 BPMN 中可以使用 documentation 参数,或在 API 中使用 description。 描述的长度不能超过 4000 个字符。

documentation 字段的原来用法是分析师在建模时为流程写的说明。 但是在 用户任务 中,可以作为任务的说明,告诉用户该如何完成任务。

该字段在属性面板的底部。

可以在每次修改流程后都更新一下 documentation 字段。 这是为用户提供及时准确信息的最简单方法。