中间捕获事件
- 所有中间捕获事件都使用同样的方式定义:
<intermediateCatchEvent id="myIntermediateCatchEvent" >
<XXXEventDefinition/>
</intermediateCatchEvent>
-
中间捕获事件的定义:
- 唯一标识(流程范围内)
- 一个结构为XXXEventDefinition的XML子元素(TimerEventDefinition)定义了中间捕获事件的类型
定时中间捕获事件
描述
- 定时中间事件作为一个监听器
- 当执行到达捕获事件节点,就会启动一个定时器.当定时器触发(比如,一段时间之后),流程就会沿着定时中间事件的外出节点继续执行
图形标记
- 定时器中间事件显示成标准中间捕获事件, 内部是一个定时器小图标:
XML内容
- 定时器中间事件定义为标准中间捕获事件. 指定类型的子元素为timerEventDefinition元素
<intermediateCatchEvent id="timer">
<timerEventDefinition>
<timeDuration>PT5M</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
信号中间捕获事件
- 中间捕获信号事件,通过引用信号定义来捕获相同信号名称的信号
-
信号中间捕获事件与其它事件(比如错误事件)不同:
- 信号不会在捕获之后被消费
- 如果有两个激活的信号边界事件捕获相同的信号事件,两个边界事件都会被触发,即便在不同的流程实例中
图形标记
- 中间信号捕获事件显示为一个普通的中间事件(圆圈套圆圈),内部有一个信号小图标.信号小图标是白色的(无填充),表示捕获的意思
XML内容
- 信号中间事件定义为普通的中间捕获事件. 对应类型的子元素是signalEventDefinition元素
<intermediateCatchEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" />
</intermediateCatchEvent>
消息中间捕获事件
描述
- 中间捕获消息事件,捕获特定名称的消息
图形标记
- 中间捕获消息事件显示为普通中间事件(圆圈套圆圈),内部是一个消息小图标.消息图标是白色的(无填充),表示捕获的意思
XML内容
- 消息中间事件定义为标准中间捕获事件. 指定类型的子元素是messageEventDefinition元素
<intermediateCatchEvent id="message">
<messageEventDefinition signalRef="newCustomerMessage" />
</intermediateCatchEvent>
内部触发事件
- 所有内部触发事件的定义都是一样的:
<intermediateThrowEvent id="myIntermediateThrowEvent" >
<XXXEventDefinition/>
</intermediateThrowEvent>
-
内部触发事件定义包含:
- 唯一标识(流程范围)
- 使用格式为XXXEventDefinition的XML子元素(比如signalEventDefinition等)定义中间触发事件的类型
中间触发空事件
-
空中间触发事件流程图,用于表示流程中的某个状态
- 可以添加执行监听器:
<intermediateThrowEvent id="noneEvent">
<extensionElements>
<activiti:executionListener class="org.activiti.engine.test.bpmn.event.IntermediateNoneEventTest$MyExecutionListener" event="start" />
</extensionElements>
</intermediateThrowEvent>
- 可以添加自己的代码,把事件发送给BAM工具或DWH.引擎不会为这个事件做任何事情,它直接径直通过
信号中间触发事件
描述
- 信号中间触发事件为定义的信号抛出一个信号事件
- 在activiti中,信号会广播到所有激活的处理器中.信号可以通过同步和异步方式发布
-
默认配置下,信号是同步发送的:
- 抛出事件的流程实例会等到信号发送给所有捕获流程实例才继续执行
- 捕获流程实例也会在触发流程实例的同一个事务中执行
- 如果某个监听流程出现了技术问题(抛出异常),所有相关的实例都会失败
-
信号也可以异步发送:
- 会在到达抛出信号事件后决定哪些处理器是激活的
- 对这些激活的处理器,会保存一个异步提醒消息(任务),并发送给jobExecutor
-
默认配置下,信号是同步发送的:
图形标记
- 中间信号触发事件显示为普通中间事件(圆圈套圆圈),内部又一个信号小图标,信号图标是黑色的(有填充),表示触发的意思
XML内容
- 消息中间事件定义为标准中间触发事件. 指定类型的子元素是signalEventDefinition元素
<intermediateThrowEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" />
</intermediateThrowEvent>
- 异步信号事件如下:
<intermediateThrowEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" activiti:async="true" />
</intermediateThrowEvent>
补偿中间触发事件
描述
- 用来触发补偿
-
触发补偿:
- 补偿可以由特定节点或包含补偿事件的作用域触发
- 补偿是通过分配给节点的补偿处理器来完成的
- 当补偿由节点触发,对应的补偿处理器会根据节点成功完成的次数执行相同次数
- 如果补偿由当前作用域触发,当前作用域的所有节点都会执行补偿,也包含并发分支
- 补偿的触发是继承式的:
- 如果执行补偿的节点是子流程,补偿会作用到子流程中包含的所有节点
- 如果子流程是内嵌节点,补偿会递归触发
- 补偿不会传播到流程的上层
- 如果补偿在子流程中触发,不会传播到子流程范围外
- bpmn规范定义,由节点触发的流程只会作用到子流程同一级别
- activiti的补偿执行次序与流程执行顺序相反: 最后完成的节点会最先执行补偿
- 补偿中间触发事件可以用来补偿成功完成的事务性子流程
- ==注意:==
- 如果补偿被一个包含子流程的作用域触发,子流程还包含了关联补偿处理器的节点, 如果它已经成功完成了,补偿只会传播到子流程
-
如果子流程中的节点也完成了,并关联了补偿处理器,如果子流程包含的这些节点还没有完成,就不会执行补偿处理器
这个流程中,我们有两个并发分支,一个分支是内嵌子流程,一个是使用信用卡节点.假设两个分支都启动了,第一个分支等待用户完成审核预定任务.第二个分支执行使用信用卡节点, 并发生了一个错误,这导致取消预定事件,并触发补偿.这时,并发子流程还没有结束,意味着补偿事件不会传播给子流程, 所以取消旅店预定这个补偿处理器不会执行.如果用户任务(就是内嵌子流程)在取消预定之前完成了,补偿就会传播给内嵌子流程
-
流程变量:
- 当补偿内嵌子流程时,用来执行补偿处理器的分支可以访问子流程的本地流程实例,因为这时是子流程完成的分支
- 为了实现这个功能,流程变量的快照会分配给分支(为执行子流程而创建的分支)有以下限制条件:
- 补偿处理器无法访问子流程内部创建的,添加到同步分支的变量
- 分配给分支的流程变量在继承关系上层的(分配给流程实例的流程变量没有包含在快照中):补偿触发时,补偿处理器通过它们所在的地方访问这些流程变量
- 变量快照只用于内嵌子流程,不适用其他节点
已知限制:
1. waitForCompletion="false"还不支持。当补偿使用中间触发补偿事件触发时, 事件没有等待,在补偿成功结束后
2. 补偿自己由并发分支执行。并发分支的执行顺序与被补偿的节点完成次序相反。 未来activiti可能支持选项来顺序执行补偿
3. 补偿不会传播给callActivity调用的子流程实例
图形标记
- 中间补偿触发事件显示为标准中间事件(圆圈套圆圈),内部是一个补偿小图标.补偿图标是黑色的(有填充),表示触发的意思
XML内容
- 补偿中间事件定义为普通的中间触发事件. 对应类型的子元素是compensateEventDefinition元素
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition />
</intermediateThrowEvent>
- 可选参数activityRef可以用来触发特定作用域/节点的补偿
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition activityRef="bookHotel" />
</intermediateThrowEvent>