子流程是包含了一系列activities,网关,事件等的特殊Activity。
- 子流程允许分层设计Workflow,提供更高维度的流程图视角,隐藏子流程实现细节。
- 子流程会为事件创建一个新的作用域,像Message,Timer等事件不仅可以应用在Service上,还可以绑定在整个子流程上面。
嵌入式子流程 Embedded Subprocess
子流程也需要有一个启动事件和一个结束事件,BPMN2.0 支持省略两者,但是Camunda引擎暂时还不支持。另外,子流程当中的所有序列流都不可以越过子流程边界。
示例:
收到Boundary Event:
或Complete Subprocess
调用式子流程 Call Activity
调用子流程可以和主流程分属于不同的流程定义。嵌入式子流程和主流程定义在同一个BPMN文件中,而调用子流程可以是一个已知的流程,也可以单独进行定义部署。
示例:
1. 首先定义一个子流程名为 Local Test Subprocess ,版本1.0,并部署。
2. 在主流程当中定义调用
3. 调用子流程
Call Activity的定义需要保证一下两点:
- 必须使用子流程的Id来调用子流程,作为Called Element的值。
- 必须正确的指定子流程的版本。
- Lastest:使用最新版本
- Deployment:按照Deployment Id查找,必须是与主流程一起部署的子流程才可以使用
- Version:指定Version,此为Camunda维护,以1,2,3递增...
- Version Tag: 为用户自定义的BPMN Version Tag属性
Call Activity的变量传递
1. 子流程无法获得主流程作用域中的变量:
2. 但可以通过Variables in Mapping的方式传递变量到子流程(复制值传递):
3. 也可以通过Variables out Mapping的方式传递子流程变量到主流程:
把Price改为60
事件子流程 Event Subprocess
如下图所示,事件子流程没有传入序列流和传出序列流,它以一个Start Event开始, 并且事件订阅在主流程作用域当中一直存在。我们可以用之前文章提到的用Postman查询当前的事件订阅,并触发。
case 1. 将Price改为60,触发 Conditional Event
图中的 Conditional Start Event是实线,意味着它属于Interrupting Event,很明显它的触发会中止当前主流程,并且我们可以注意到此时的子流程和主流程处于同一个作用域,共享变量。
case 2. 触发 Non-Interrupting Message
虚线表示的Start Event属于Non-Interrupting模式,因此它不会中断当前流程,所以这种 Non-Interrupting模式子流程可以被多次触发。
事务子流程 Transaction Subprocess
BPMN当中的事务与程序中的事务并不完全相同。BPMN 事务本质上是依靠Compensation Event(补偿机制),Cancel Event等,从Workflow设计层面上来实现回滚的。
接下来,我们通过一个订单预定的例子,来演示BPMN中事务子流程的用法:
1. 初始化Count = 10, Money = 0.
2. 预定,Count - 1,到扣款阶段
3. 扣款失败,Throw Error Event
4. 触发Cancel End Event,同时Cancel End Event又会启动事务子流程当中的补偿机制,执行Count + 1
5. 补偿完成,触发子流程 Cancel Boundary Event,事务结束。
接下来,我们对该Workflow稍加修改,将扣款失败改为Error End Event, 可以看到,Error End Event 不会启动补偿机制而是直接中断子进程。