camunda-bpmn-用户任务(User Task)
dafengyiba 0.2112020.10.12 16:02:25字数 2,724阅读 8,065用户任务被用作给哪些需要人去完成的工作建模。当流程执行到用户任务时,一个新的任务被创建在任务列表里,任务将会分配给用户(user)或者组(group)
用户任务被定义成下面的xml,用户任务的id属性是必须的,名称属性是可选的
描述(Description):
用户任务可以有一个描述,事实上,BPMN2.0的所有元素都可以有一个描述。描述被定义在一个附件的documentation元素中。
<userTask id="theTask" name="Schedule meeting" >
<documentation>
Schedule an engineering meeting for next week with the new hire.
</documentation>
描述文本可以通过一下方式获取:
task.getDescription();
属性(Properties):
1.到期日期(Due Date):
每一个任务都有一个字段指明任务的到期时间,查询API可以用来查询任务到期日期在给定的时间之前或者之后
有一个扩展的属性,可以用来指定一个表达式,用来在task创建的时候初始化任务的到期时间。表达式的值应该能被解析为Java的Date或者ISO8601标准的时间字符串或者null。当使用ISO8601格式的字符串时,你也可以指定一个确切的时间点或者一个时间段,或者一个相对于任务创建的时间段。例如,可以使用之前流程表单中输入的时间,或者在之前的服务任务中技术的时间。
<userTask id="theTask" name="Important task" camunda:dueDate="${dateVariable}"/>
到期时间可以TaskService或者或者在TaskListeners中用通过的DelegateTask来修改到期时间
2.跟催时间(Follow Up Date):
每个任务都有一个字段指明任务的跟催时间,查询API可以用来查询任务跟催日期在一个给定时间之前或者之后
<userTask id="theTask" name="Important task" camunda:followUpDate="${dateVariable}"/>
3.用户分配(User Assignment):
用户任务可以直接分配给一个单个用户,一个用户列表,或者一个组列表
4.使用BPMN资源分配的任务(Assignment using BPMN Resource Assignments):
BPMN定义了一些可以在本地使用的赋值概念。作为一个更强大的代替方案,camunda还定义了一系列的定制扩展元素。
4.1.人的行为(Human Performer):
这是通过定义一个humanPerformer来实现的。humanPerformer定义需要一个事件上定义了用户的的resourceAssignmentExpression。目前只支持formalExpressions
只能将一个用户作为human performer分配给该任务。在引擎术语中,此用户称为受让人(assignee)。具有受让人(assignee)的任务在其他用户的任务列表中不可见,而可以在受让人(assignee)的所谓个人任务列表中找到。
直接分配给用户的任务可以通过TaskService获取到:
List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
4.2.潜在的拥有者(Potential Owner):
任务也可以放在所谓的候选任务人员列表中。在这个例子中,potentialOwner必须被使用。这个使用与humanPerformer类似。请注意,如意每个元素用这种方式表示,它要求指明定义的是一个用户或者是一个组。
<process ... >
...
<userTask id='theTask' name='important task' >
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(management)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
被定义成potential owner的任务,可以被查询:
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");
这会检索到所有的候选人叫kermit的任务。也就是说表达式包含kermit这个用户的任务。这也会检索到被分配给一个组的,且kermit是这个组的成员的任务(如果kermit是该组的成员,并且使用了identity组件)。用户的组是在运行时解析的,可以通过IdentityService管理这些组。
如果没有指明给定的文本是用户还是组,引擎默认是组。所以下面两个的结果是一致的:
<formalExpression>accountancy</formalExpression>
<formalExpression>group(accountancy)</formalExpression>
5.使用Camunda的扩展来进行用户分配(User Assignment using Camunda Extensions):
很明显,用户和组的分配是相当复杂的。为了避免这种复杂性,camunda进行了定制扩展。
5.1.分派人(Assignee):
assignee属性定制扩展允许直接分配一个用户任务给指定的人。
<userTask id="theTask" name="my task" camunda:assignee="kermit" />
这个与humanPerformer结构定义的一样的
5.2.候选人(Candidate Users):
这个candidateUsers属性定制扩展,允许一个用户作为一个任务的候选人
<userTask id="theTask" name="my task"
camunda:candidateUsers="kermit, gonzo" />
这个与potentialOwner结构定义是一样的,注意,这个属性不需要指名是user,因为这个属性只能指定人
5.3.候选组(Candidate Groups):
这个candidateGroups属性定制扩展,允许你定制一个候选组给一个任务
<userTask id="theTask" name="my task"
camunda:candidateGroups="management, accountancy" />
这个与potentialOwner机构定义是一样的,注意这个属性不用指名是group,因为这个属性只能是group
5.4.组合候选人和组(Combining Candidate Users and Groups):
candidateUsers属性和candidateGroups属性可以同时定义,在同一个用户任务中
6.基于数据和服务逻辑的分配(Assignment based on Data and Service Logic):
在上面的例子中,例如kermit或者management是一个常量,但是更多的情况下,在设计流程时,我们可能并不清楚知道指派人或者候选人,或者候选人或指派人需要通过从数据库中获取,此时我们可以使用表达式或者task listener来实现
分配表达式(Assignment Expressions):
分配表达式可以访问流程变量或者调用外部的bean和服务
6.1.使用流程变量(Using Process Variables):
流程变量对于基于提前收集和计算的数据的分配是非常有用的
下面是一个展示将用户任务分配给流程发起人的例子:
<startEvent id="startEvent" camunda:initiator="starter" />
<userTask id="task" name="Clarify Invoice" camunda:assignee="${ starter }"/>
首先camunda:initiator表达式是被用作绑定发起流程的用户id,然后表达式${ starter }检索这个值并且用做这个任务的assignee
它可以使用所有的在用户任务中可见的流程变量在这个表达式中
6.2.调用一个服务或者一个bean(Invoking a Service / Bean):
当使用spring或者CDI时,它可以委托给一个bean或者一个服务的实现。这种方式可以调用外部的复杂的分派逻辑,且不用显示的为它建模,且它调用的逻辑将会产生一个被用作分配的变量。
在下面这个例子中,assignee会通过调用基于spring或者CDI的bean的ldapService的findManagerOfEmployee()方法进行赋值。被传递的emp参数是一个流程变量。
<userTask id="task" name="My Task"
camunda:assignee="${ldapService.findManagerForEmployee(emp)}"/>
类似的方法可以分配候选users和groups:
<userTask id="task" name="My Task"
camunda:candidateUsers="${ldapService.findAllSales()}"/>
注意:只有在这个方法调用的返回类似是一个String或在一个Collection的时候才会生效(对于候选users和groups):
public class FakeLdapService {
public String findManagerForEmployee(String employee) {
return "Kermit The Frog";
}
public List<String> findAllSales() {
return Arrays.asList("kermit", "gonzo", "fozzie");
}
}
6.3.在listener中指派(Assignments in Listeners):
这也可以使用task listeners去进行指派。下面的例子展示了一个创建事件的task listener:
<userTask id="task1" name="My task" >
<extensionElements>
<camunda:taskListener event="create" class="org.camunda.bpm.MyAssignmentHandler" />
</extensionElements>
</userTask>
这个传递给TaskListener实现的委托任务,允许设置assignee和候选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");
...
}
}
注意:
通过TaskListener指派一个任务,或者设置任何其他属性,不会导致赋值或更新事件,除非使用TaskService方法执行这些操作。这是有意为之,以避免创建事件循环。
7.分派和鉴权服务(Assignments and Identity Service):
尽管camunda引擎提供了一个鉴权管理组件,并通过IdentityService对外暴露。但是它并不会检查被提供的用户是否被鉴权服务识别。当引擎被嵌入到应用中时,允许继承到已有的鉴权管理解决方案。
然而,你可以在service/bean或者listener通过查询数据库取使用鉴权服务。
你可以在鉴权服务的帮助下查询用户,例如下面的例子:
ProcessEngine processEngine = delegateTask.getProcessEngine();
IdentityService identityService = processEngine.getIdentityService();
List<User> managementUsers = identityService.createUserQuery()
.memberOfGroup("management")
.list();
User kermit = identityService.createUserQuery()
.userFirstName("kermit")
.singleResult();
8.报告BPMN的错误(Reporting Bpmn Error):
在用户任务操作过程中去报告一个业务异常,使用TaskService#handleBpmnError.它只会在任何是活动的状态下才会被调用。#handleBpmnError方法需要一个强制的参数:errorCode。这个errorCode是用来识别预定义的错误的。如果给定的errorCode不存在或者没有边界事件被定义,当前的活动实例会直接结束,错误不会被处理。
详见下面的例子:
Task task = taskService.createTaskQuery().taskName("Perform check").singleResult();
// ... business error appears
taskService.handleBpmnError(
task.getId(),
"bpmn-error-543", // errorCode
"Thrown BPMN Error during...", // errorMessage
variables);
一个错误码是bpmn-error-543的BPMN的错误将会被广播。如果存在一个带有这个错误码的边界事件,这个BPMN错误将会被捕获并处理。错误消息(errorMessage)和变量(variables)是可选的。他们可以添加额外的错误信息。变量将会传递给捕获到这个错误的执行。
9.报告BPMN的扩大(Reporting Bpmn Escalation):
Escalation详见扩大事件(Escalation Events)
在用户任务执行期间,可以通过TaskService#handleEscalation来报告扩大(escalation)。用户任务必须是活动的。在调用扩大时,必须要与一个escalationCode,这个编号是用来识别一个预定义的扩大的。如果给定的escalationCode不存在,一个流程引擎的错误会被抛出。
taskService.handleEscalation(
taskId,
"escalation-432", // escalationCode
variables);
这里一个编号为escalation-432的扩大被广播出去。如果没有带有这个扩大编码的边界事件,这个扩大就不会被捕获和处理。这个变量(variables)是可选的,变量可以传递给捕获扩大的执行。
10.完成(Completion):
完成是任务生命周期的一部分,与创建设置候选人等操作一起。(允许通过Java API操作)。通过传递变量完成一个任务,这个流程变量可以被选择性的检索:
taskService.complete(taskId, variables);
// or complete and retrieve the process variables
VariableMap processVariables = taskService
.completeWithVariablesInReturn(taskId, variables, shouldDeserializeValues);
11.表单(Forms):
可以通过使用camunda:formKey属性来提供信息呈现一个User Task表单:
<userTask id="someTask" camunda:formKey="someForm.html">
...
</userTask>
表单键是一个符号值,可以通过使用扩展属性formKey在BPMN XML文件中设置,并在运行时使用流程引擎API检索。
用Form Service检索表单的key(Retrieving the Form Key using the Form Service):
String formKey = formService.getTaskFormData(someTaskId).getFormKey();
用Task Service检索Form(Retrieving the Form using the Task Service):
当执行一个任务查询时,也是可以检索form key的。如果需要为完整的任务列表检索表单键,这是最有用的
List<Task> tasks = TaskService.createTaskQuery()
.assignee("jonny")
.initializeFormKeys() // must be invoked
.list();
for(Task task : tasks) {
String formKey = task.getFormKey();
}
注意:在TaskQuery对象上调用.initializeFormKeys()时非常必要的,为了确保form keys是被初始过的。
12.表单提交(Form submission):
当表单被提交时,是可以在返回参数中获取流程变量的:
VariableMap processVariables = formService.submitTaskFormWithVariablesInReturn(taskId, properties, shouldDeserializeValues);
// 如果不需要返回流程变量
formService.submitTaskForm(taskId, properties);
标签:或者,temp,一个,用户,任务,kermit,camunda,属性
From: https://www.cnblogs.com/harrychinese/p/16774326.html