说说 jBPM 流程定义语言(8)—— sub-process(子流程活动)
2018-03-06 11:12
816 查看
当我们的流程复杂到一定程度时,就需要按照一定规则把业务拆分成若干子流程,这样业务模块之间才能明晰易于划分。
jBPM4 提供了 sub-process – 子流程活动,这可以在 “ 主干流程 ” 定义中调用其他的流程定义,从而 “ 组装 ” 我们的流程定义 。在运行到子流程活动时,工作流引擎将创建一个子流程实例,然后等待直到完成,当子流程实例完成后,流程就会流向下一个节点。
sub-process 活动的属性:
sub-process 活动的元素:
sub-process 的 parameter-in – 子流程活动输入元素的属性:
sub-process 的 parameter-out – 子流程活动输出元素的属性:
sub-process 活动的 outcome 元素必须有与之相呼应的 outcome-value 元素,这个 outcome-value 元素被定义在子流程活动的流出转移( transition )中 。
sub-process transition 的 outcome-value 元素:
假设有这样一个场景,父流程中的一个节点是审查,而这个节点是通过子流程实现的:
jPDL:
这里引用了下面定义的子流程:
在实际的业务中,存在着各种各样的子流程,它们会被其他流程所引用。
jPDL:
测试代码:
注意:如果是在 eclipse 中使用 jBPM 的插件来生成的 jPDL ,jPDL 会默认生成 sub-process-id,这样就无法通过 id 来得到子流程的定义信息(因为我们在子流程中没有定义 ID,用的是 sub-process-key)。
jPDL:
子流程定义与之前的定义相同:
测试代码:
父流程的定义与上一个父流程定义相比,仅少了 outcome 属性:
jPDL:
jPDL:
测试代码:
jBPM4 提供了 sub-process – 子流程活动,这可以在 “ 主干流程 ” 定义中调用其他的流程定义,从而 “ 组装 ” 我们的流程定义 。在运行到子流程活动时,工作流引擎将创建一个子流程实例,然后等待直到完成,当子流程实例完成后,流程就会流向下一个节点。
sub-process 活动的属性:
属性 | 类型 | 默认值 | 是否必需 | 描述 |
---|---|---|---|---|
sub-process-id | 字符串 | 无 | sub-process-id 与 sub_process-key,必需其一 | 流程定义的 ID 标识,可以通过一个流程的 ID 去引用此流程定义的指定版本 。 |
sub-process-key | 字符串 | 无 | sub-process-id 与 sub_process-key,必需其一 | 流程 key 标识,通过 key 去引用流程定义,也就意味着引用了该流程定义的最新版本 。 注意,该流程定义的最新版本会在每次活动实例执行时计算得出 。 |
outcome | 表达式 | 无 | 当 sub-process 活动的 transition 元素具有 outcome-value 时必需 | 当子流程活动执行结束时执行的表达式 。 表达式值用来匹配流出转移中的 outcome-value 元素值,起到选择 sub-process 活动下一步流向的作用 。 |
元素 | 聚合关系 | 描述 |
---|---|---|
parameter-in | 0..* | 子流程输入参数。即声明一个变量,在创建子流程实例时传入。 |
parameter-out | 0..* | 子流程输出参数。即声明一个变量,在子流程实例结束时,返回父流程实例。 |
属性 | 类型 | 默认值 | 是否必需 | 描述 |
---|---|---|---|---|
subvar | 字符串 | 无 | 必需 | 被赋值的子流程变量的名称。 |
var | 字符串 | 无 | var 与 expr 必需二选一 | 从父流程中输入的变量名称。 |
expr | 字符串 | 无 | var 与 expr 必需二选一 | 此表达式会在父流程中被解析,结果值会被输入到对应的子流程变量中。 |
lang | 字符串 | EL 表达式 | 可选 | 表达式使用的脚本语言。 |
属性 | 类型 | 默认值 | 是否必需 | 描述 |
---|---|---|---|---|
var | 字符串 | 无 | 必需 | 输出的目标 – 父流程中的变量名称。 |
subvar | 字符串 | 无 | subvar 与 expr 必需二选一 | 子流程中需要被输出的变量名称。 |
expr | 字符串 | 无 | subvar 与 expr 必需二选一 | 此表达式会在子流程中被解析,结果会被传入到对应的父流程变量中。 |
lang | 12cbc 字符串 | EL 表达式 | 可选 | 表达式使用的脚本语言。 |
sub-process transition 的 outcome-value 元素:
元素 | 聚合关系 | 描述 |
---|---|---|
outcome-value | 0..1 | 它是一个值表达式 。 子流程活动结束时,如果子流程中某个转移的 outcome-value 值与子流程的 outcome 值相匹配,那么,父流程会通过此转移 。 注意:这个 outcome-value 值是在 transition 元素中定义的 。 |
1 流程变量
父子流程是通过流程变量来传递数据的:父流程在子流程启动把值输入,子流程结束时把值输出。假设有这样一个场景,父流程中的一个节点是审查,而这个节点是通过子流程实现的:
jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process key="SubProcessDocument" xmlns="http://jbpm.org/4.4/jpdl"> <start g="211,136,48,48" name="start1"> <transition to="审核"/> </start> <sub-process g="315,135,92,52" name="审核" sub-process-key="SubProcessReview"> <!-- 变量传入子流程 --> <parameter-in subvar="document" var="document"/> <!-- 子流程把变量 result 返回父流程的 reviewResult--> <parameter-out subvar="result" var="reviewResult"/> <transition to="等待"/> </sub-process> <state g="467,137,92,52" name="等待"/> </process>
这里引用了下面定义的子流程:
在实际的业务中,存在着各种各样的子流程,它们会被其他流程所引用。
jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process name="SubProcessReview" xmlns="http://jbpm.org/4.4/jpdl"> <start g="269,233,48,48" name="start1"> <transition to="同意"/> </start> <task assignee="deniro" g="384,232,107,52" name="同意"> <transition to="end1"/> </task> <end g="548,236,48,48" name="end1"/> </process>
测试代码:
//创建变量,并设置 Map<String, Object> variables = new HashMap<>(); variables.put("document", "This document"); //带父变量发起流程实例 ProcessInstance processInstance = executionService.startProcessInstanceByKey ("SubProcessDocument", variables); //获取用户任务列表 List<Task> taskList = taskService.findPersonalTasks("deniro"); Task task = taskList.get(0); //获取任务变量(来自父流程) String document = (String) taskService.getVariable(task.getId(), "document"); assertEquals("This document", document); //在子流程任务上设置新变量 result(实践一般来自于用户填写的表单) variables = new HashMap<>(); variables.put("result", "accept"); // result 作为子流程变量返回给父流程实例 taskService.setVariables(task.getId(), variables); taskService.completeTask(task.getId());//完成任务,结束子流程实例 processInstance = executionService.findProcessInstanceById(processInstance.getId()); //断言父流程已完成子流程活动,并到达了 wait 节点 assertNotNull(processInstance.findActiveExecutionIn("等待")); //验证父流程的 reviewResult 变量值(它是子流程的输出结果) String result = (String) executionService.getVariable(processInstance.getId(), "reviewResult"); assertEquals("accept", result);
注意:如果是在 eclipse 中使用 jBPM 的插件来生成的 jPDL ,jPDL 会默认生成 sub-process-id,这样就无法通过 id 来得到子流程的定义信息(因为我们在子流程中没有定义 ID,用的是 sub-process-key)。
2 决定父流程流出转移(使用 outcome 属性)
现在,我们使用 sub-process 活动的 outcome 属性来决定父流程的流出转移。jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process name="SubProcessDocument2" xmlns="http://jbpm.org/4.4/jpdl"> <start name="start1" g="113,224,48,48"> <transition to="审查"/> </start> <!-- 子流程活动的 outcome 属性引用名称为 result 的子流程变量--> <sub-process name="审查" sub-process-key="SubProcessReview" outcome="#{result}" g="226,220,92,52"> <!-- 如果 result 为“同意”,则流向此转移;其他情况与此类似--> <transition name="同意" to="下一步" g="275,173:28,-27"/> <transition name="需要完善" to="更新" g="-16,-22"/> <transition name="拒绝" to="关闭" g="274,313:28,-21"/> </sub-process> <state name="下一步" g="384,148,92,52"/> <state name="更新" g="387,221,92,52"/> <state name="关闭" g="388,289,92,52"/> </process>
子流程定义与之前的定义相同:
测试代码:
//带父变量发起流程实例 ProcessInstance processInstance = executionService.startProcessInstanceByKey ("SubProcessDocument2"); //获取用户任务列表 List<Task> taskList = taskService.findPersonalTasks("deniro"); Task task = taskList.get(0); //在子流程任务上设置新变量 result,这个值会被传递给 outcome 属性以决定父流程的走向 Map<String, Object> variables = new HashMap<>(); variables.put("result", "同意"); // result 作为子流程变量返回给父流程实例 taskService.setVariables(task.getId(), variables); taskService.completeTask(task.getId());//完成任务,结束子流程实例 processInstance = executionService.findProcessInstanceById(processInstance.getId()); //断言父流程已完成子流程活动,并到达了“下一步”节点 assertNotNull(processInstance.findActiveExecutionIn("下一步"));
3 决定父流程流出转移(使用子流程的 end 活动)
这种方法比 outcome 属性更容易理解。因为一个流程可以定义多个 end 活动,那么我们可以为子流程定义多个不同名称的 end 活动,这些 end 活动名称会自动与父流程的流出转移名称做同名关联。父流程的定义与上一个父流程定义相比,仅少了 outcome 属性:
jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process name="SubProcessDocument3" xmlns="http://jbpm.org/4.4/jpdl"> <start name="start1" g="113,224,48,48"> <transition to="审查"/> </start> <sub-process name="审查" sub-process-key="SubProcessReview2" g="226,220,92,52"> <transition name="同意" to="下一步" g="275,173:28,-27"/> <transition name="需要完善" to="更新" g="-16,-22"/> <transition name="拒绝" to="关闭" g="274,313:28,-21"/> </sub-process> <state name="下一步" g="384,148,92,52"/> <state name="更新" g="387,221,92,52"/> <state name="关闭" g="388,289,92,52"/> </process>
jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process name="SubProcessReview2" xmlns="http://jbpm.org/4.4/jpdl"> <start g="269,233,48,48" name="start1"> <transition to="同意"/> </start> <task assignee="deniro" g="384,232,107,52" name="同意"> <transition to="end1" name="需要完善" g="-23,-22"/> <transition name="同意" to="end2" g="439,178:38,-22"/> <transition name="拒绝" to="end3" g="442,339:30,-26"/> </task> <end g="548,236,48,48" name="end1"/> <end name="end2" g="550,154,48,48"/> <end name="end3" g="546,315,48,48"/> </process>
测试代码:
//带父变量发起流程实例 ProcessInstance processInstance = executionService.startProcessInstanceByKey ("SubProcessDocument3"); //获取用户任务列表 List<Task> taskList = taskService.findPersonalTasks("deniro"); Task task = taskList.get(0); // 让任务流向 “同意”转移 taskService.completeTask(task.getId(),"同意");//完成任务,结束子流程实例 processInstance = executionService.findProcessInstanceById(processInstance.getId()); //断言父流程已完成子流程活动,并到达了“下一步”节点 assertNotNull(processInstance.findActiveExecutionIn("下一步"));
相关文章推荐
- 说说 jBPM 流程定义语言(3)—— state 活动 (状态活动)
- 说说 jBPM 流程定义语言(7)—— task(人工任务活动)
- 说说 jBPM 流程定义语言(1)—— process
- 说说 jBPM 流程定义语言(6)—— end (结束活动)
- 说说 jBPM 流程定义语言(5)—— fork - join (分支、聚合活动)
- 说说 jBPM 流程定义语言(9)—— 自定义活动
- 说说 jBPM 流程定义语言(2)—— start 活动 (启动活动)
- 说说 jBPM 流程定义语言(11)—— 事件
- jBPM-4.4:主流程(process)与子流程(sub-process)之间交换数据
- jBPM流程定义语言(JPDL)
- 一步一步学JBPM(2)——JPDL流程定义语言
- JBPM4.4:API风格、管理(部署、删除、更改、查询(文件资源、活动坐标))流程定义
- JBPM4.4:流程定义语言和活动、事件
- 一、工单流程JBPM-------JPDL流程定义语言
- jbpm用户指南翻译:第16章 jBPM流程定义语言(JPDL)
- JBPM表达业务流程(流程定义语言)
- jBPM用户指南 第16章 jBPM流程定义语言 (转载)
- JBPM(三)--- JPDL 流程定义语言
- jBPM流程定义语言(JPDL)
- 一步一步学JBPM(2)——JPDL流程定义语言