您的位置:首页 > 产品设计 > 产品经理

说说 jBPM 流程定义语言(8)—— sub-process(子流程活动)

2018-03-06 11:12 816 查看
当我们的流程复杂到一定程度时,就需要按照一定规则把业务拆分成若干子流程,这样业务模块之间才能明晰易于划分。

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 活动下一步流向的作用 。
sub-process 活动的元素:

元素聚合关系描述
parameter-in0..*子流程输入参数。即声明一个变量,在创建子流程实例时传入。
parameter-out0..*子流程输出参数。即声明一个变量,在子流程实例结束时,返回父流程实例。
sub-process 的 parameter-in – 子流程活动输入元素的属性:

属性类型默认值是否必需描述
subvar字符串必需被赋值的子流程变量的名称。
var字符串var 与 expr 必需二选一从父流程中输入的变量名称。
expr字符串var 与 expr 必需二选一此表达式会在父流程中被解析,结果值会被输入到对应的子流程变量中。
lang字符串EL 表达式可选表达式使用的脚本语言。
sub-process 的 parameter-out – 子流程活动输出元素的属性:

属性类型默认值是否必需描述
var字符串必需输出的目标 – 父流程中的变量名称。
subvar字符串subvar 与 expr 必需二选一子流程中需要被输出的变量名称。
expr字符串subvar 与 expr 必需二选一此表达式会在子流程中被解析,结果会被传入到对应的父流程变量中。
lang12cbc
字符串
EL 表达式可选表达式使用的脚本语言。
sub-process 活动的 outcome 元素必须有与之相呼应的 outcome-value 元素,这个 outcome-value 元素被定义在子流程活动的流出转移( transition )中 。

sub-process transition 的 outcome-value 元素:

元素聚合关系描述
outcome-value0..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("下一步"));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: