可以为对应的事件类型注册监听器,在这个类型的任何时间触发时都会收到提醒。 你可以添加引擎范围的事件监听器通过, 添加引擎范围的事件监听器在运行阶段使用API, 或添加 event-listener 到。
所有分发的事件,都是org.activiti.engine.delegate.event.ActivitiEvent 的子类。事件包含(如果有效)type,executionId,processInstanceId 和processDefinitionId。 对应的事件会包含事件发生时对应上下文的额外信息, 这些额外的载荷可以在所有支持的事件类型中找到。
实现事件监听器的唯一要求是实现org.activiti.engine.delegate.event.ActivitiEventListener。 西面是一个实现监听器的例子,它会把所有监听到的事件打印到标准输出中,包括job执行的事件异常:
isFailOnException() 方法决定了当事件分发时,onEvent(..) 方法抛出异常时的行为。 这里返回的是 false,会忽略异常。 当返回 true 时,异常不会忽略,继续向上传播,迅速导致当前命令失败。 当事件是一个 API 调用的一部分时(或其他事务性操作,比如 job 执行), 事务就会回滚。当事件监听器中的行为不是业务性时,建议返回 false。 activiti 提供了一些基础的实现,实现了事件监听器的常用场景。可以用来作为基类或监听器实现的样例:
- org.activiti.engine.delegate.event.BaseEntityEventListener: 这个事件监听器的基
类可以用来监听实体相关的事件,可以针对某一类型实体,也可以是全部实体。 它隐藏了
类型检测,并提供了三个需要重写的方法:onCreate(..), onUpdate(..) 和 onDelete(..),当实
体创建,更新,或删除时调用。对于其他实体相关的事件,会调用 onEntityEvent(..)。
Configuration and setup 配置和安装
把事件监听器配置到流程引擎配置中时,会在流程引擎启动时激活,并在引擎启动启动中持续工作着。
eventListeners 属性需要org.activiti.engine.delegate.event.ActivitiEventListener 的队列。 通常,我们可以声明一个内部的bean定义,或使用 ref 引用已定义的 bean。 下面的代码,向配置添加了一个事件监听器,任何事件触发时都会提醒它,无论事件是什么类型:
...
<property name="eventListeners">
<list>
<bean class="org.activiti.engine.example.MyEventListener" />
</list>
</property>
</bean>
为了监听特定类型的事件,可以使用 typedEventListeners 属性,它需要一个 map 参数。 map
的 key 是逗号分隔的事件名(或单独的事件名)。 map 的 value
是 org.activiti.engine.delegate.event.ActivitiEventListener 队列。 下面的代码演示了向配置中添加一个事件监听器,可以监听 job 执行成功或失败:
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="typedEventListeners">
<map>
<entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
<list>
<bean class="org.activiti.engine.example.MyJobEventListener" />
</list>
</entry>
</map>
</property>
</bean>
可以通过API(RuntimeService)在运行阶段添加或删除额外的事件监听器
/**
* Adds an event-listener which will be notified of ALL events by the dispatcher.
*/
void addEventListener(ActivitiEventListener listenerToAdd);
/**
* Adds an event-listener which will only be notified when an event occurs, which type is in the given types.
* @param listenerToAdd the listener to add
* @param types types of events the listener should be notified for
*/
void addEventListener(ActivitiEventListener listenerToAdd, ActivitiEventType... types);
/**
* Removes the given listener from this dispatcher. The listener will no longer be notified,
* regardless of the type(s) it was registered for in the first place.
* @param listenerToRemove listener to remove
*/
注意运行期添加的监听器引擎重启后就消失了
Adding listeners to process definitions 添加监听到流程定义
可以为特定流程定义添加监听器。监听器只会监听与这个流程定义相关的事件,以及这个流程定义上发起的所有流程实例的事件。 监听器实现可以使用,全类名定义,引用实现了监听器接口的表达式,或配置为抛出一个message/signal/error 的 BPMN 事件。
Listeners executing user-defined logic 让监听器执行用户定义的逻辑
下面代码为一个流程定义添加了两个监听器。第一个监听器会接收所有类型的事件,它是通过全类名定义的。 第二个监听器只接收作业成功或失败的事件,它使用了定义在流程引擎配置中的 beans 属性中的一个 bean。
对于实体相关的事件,也可以设置为针对某个流程定义的监听器,实现只监听发生在某个流程定义上的某个类型实体事件。 下面的代码演示了如何实现这种功能。可以用于所有实体事件(第一个例子),也可以只监听特定类型的事件(第二个例子)
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener class="org.activiti.engine.test.MyEventListener" entityType="task" />
<activiti:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
</extensionElements>
...
</process>
entityType 支持的值有:attachment, comment, execution,identity-link, job, process-instance,
process-definition, task。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener class="org.activiti.engine.test.MyEventListener" entityType="task" />
<activiti:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
</extensionElements>
...
Listeners throwing BPMN events
[试验阶段]
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
</extensionElements>
</process>
如果需要声明额外的逻辑,是否抛出 BPMN 事件,可以扩展 activiti 提供的监听器类。在子类中重写 isValidEvent(ActivitiEvent event), 可以防止抛出 BPMN 事件。对应的类是
org.activiti.engine.test.api.event.SignalThrowingEventListenerTest,
org.activiti.engine.impl.bpmn.helper.MessageThrowingEventListener 和
org.activiti.engine.impl.bpmn.helper.ErrorThrowingEventListener.
Notes on listeners on a process-definition 流程定义中监听器的注意事项
- 事件监听器只能声明在 process 元素中,作为 extensionElements 的子元素。 监听器不能定义在流程的单个 activity 下。
- delegateExpression 中的表达式无法访问 execution 上下文,这与其他表达式不同(比如 gateway )。 它只能引用定义在流程引擎配置的beans 属性中声明的 bean,或者使用 spring(未使用 beans 属性)中所有实现了监听器接口的 spring-bean。
- 在使用监听器的 class 属性时,只会创建一个实例。记住监听器实现不会依赖成员变量,确认是多线程安全的。
- 当一个非法的事件类型用在 events 属性或 throwEvent 中时,流程定义发布时就会抛出异常。(会导致部署失败)。如果 class 或delegateExecution 由问题(类不存在,不存在的 bean 引用,或代理类没有实现监听器接口),会在流程启动时抛出异常(或在第一个有效的流程定义事件被监听器接收时)。所以要保证引用的类正确的放在 classpath 下,表达式也要引用一个有效的实例。
我们提供了通过 API 使用事件机制的方法,允许大家触发定义在引擎中的任何自定义事件。
建议(不强制)只触发类型为 CUSTOM 的 ActivitiEvents。可以通过RuntimeService 触发事件:
/**
* @param event event to dispatch.
*
* @throws ActivitiException if an exception occurs when dispatching the event or when the {@link ActivitiEventDispatcher}
* is disabled.
* @throws ActivitiIllegalArgumentException when the given event is not suitable for dispatching.
*/
void dispatchEvent(ActivitiEvent event);
下面是引擎中可能出现的所有事件类型。每个类型都对应 org.activiti.engine.delegate.event.ActivitiEventType 中的一个枚举值
Table 1. Supported events
引擎内部所有 ENTITY_* 事件都是与实体相关的。下面的列表展示了实体事件与实体的对应关
系:
- ENTITY_CREATED, ENTITY_INITIALIZED, ENTITY_DELETED: Attachment, Comment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.
- ENTITY_UPDATED: Attachment, Deployment, Execution, Group, IdentityLink, Job, Model, ProcessDefinition, ProcessInstance, Task, User.
只有事件被发送,对应的引擎内的监听器才会被通知到。你有很多引擎 - 在同一个数据库运行 - 事件只会发送给注册到对应引擎的监听器。其他引擎发生的事件不会发送给这个监听器,无论实际上它们运行在同一个或不同的JVM中。
对应的事件类型(对应实体)都包含对应的实体。根据类型或事件,这些实体不能再进行更新(比如,当实例以被删除)。可能的话,使用事件提供的 EngineServices 来以安全的方式来操作引擎。即使如此,你需要小心的对事件对应的实体进行更新/操作。