可以通过为一些特定的事件注册监听器达到监听事件触发的目的。注册监听器方式:1.通过配置添加;2.使用运行时API添加;3.BPMN XML中添加。
所有事件都是org.activiti.engine.delegate.event.ActivitiEvent的子类。
1.事件监听实现
实现事件监听的唯一要求,是实现org.activiti.engine.delegate.event.ActivitiEventListener接口,举例:
打印所有接收到的事件,事件异常关联job-execution
public class MyEventListener implements ActivitiEventListener {
@Override
public void onEvent(ActivitiEvent event) {
switch (event.getType()) {
case JOB_EXECUTION_SUCCESS:
System.out.println("A job well done!");
break;
case JOB_EXECUTION_FAILURE:
System.out.println("A job has failed...");
break;
default:
System.out.println("Event received: " + event.getType());
}
}
@Override
public boolean isFailOnException() {
// The logic in the onEvent method of this listener is not critical, exceptions
// can be ignored if logging fails...
return false;
}
}
事件触发时执行 onEvent(..)方法,当 onEvent(..)方法中抛出异常时,执行 isFailOnException()方法。若 isFailOnException()方法返回
false
,忽视该异常,否则当前指令执行失败。如果事件是事务中的一部分,该事务回滚。如果事件监听中的行为不是业务关键,建议返回
false。
Activiti提供一些基础的接口实现来方便常用的事件监听,这些实现类也可以当做基类使用,如org.activiti.engine.delegate.event.BaseEntityEventListener。
2.配置中添加监听
流程引擎配置中添加的事件监听,在流程引擎启动时就激活,而且在会保持激活状态。
配置文件中既可使用内联bean,也可使用ref来关联已定义的bean。
2.1通过 eventListeners
属性,配置实现org.activiti.engine.delegate.event.ActivitiEventListener
接口的事件监听器的实例列表
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="eventListeners">
<list>
<bean class="org.activiti.engine.example.MyEventListener" />
</list>
</property>
</bean>
2.2 监听指定类型事件,可使用typedEventListeners
,配置该属性,需要一个使用逗号隔开的映射条目确定要监听的事件类型,监听器列表中的实例须实现org.activiti.engine.delegate.event.ActivitiEventListener
。
<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>
执行顺序按照配置文件中的添加顺序执行,限制性
eventListeners
,再执行
typedEventListeners
。
3.使用RuntimeService添加/删除监听。
/**
* Adds an event-listener which will be notified of ALL events by the dispatcher.
* @param listenerToAdd the listener to add
*/
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
*/
void removeEventListener(ActivitiEventListener listenerToRemove);
注意:引擎重启后,使用RuntimeService添加的监听也失效。
4.流程定义中添加监听
可在特定的流程定义中添加监听。与流程定义相关的事件,以及与流程实例相关的所有事件,才会调用该类监听。这些事件都是与特定的流程定义一起启动的。
Listeners executing user-defined logic
下面代码片段中添加两个监听,第一个监听使用标准的类名,监听所有类型的事件;第二个使用表达式,通过已经beans
在中定义的监听来实现对成功和失败事件的监听。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener class="org.activiti.engine.test.MyEventListener" />
<activiti:eventListener delegateExpression="${testEventListener}" events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
</extensionElements>
...
</process>
事件关联实体,也可通过在流程定义中添加如下配置完成对特定实体类型的事件监听。支持的实体类型:
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>
...
</process>
Listeners throwing BPMN events
控制事件转发的另一种方式是抛出BPMN事件,但只有抛出特定工作流类型的BPMN事件才有意义。
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<activiti:eventListener throwEvent="globalSignal" 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事件,可通过继承工作流提供的监听类实现。通过重写子类中的
isValidEvent(ActivitiEvent event)方法,可以阻止BPMN事件抛出。
Notes on listeners on a process-definition
1.事件监听器只能在process元素中定义,例如子元素extensionElements;监听器不能在流程的单个活动中定义;
2.delegateExpression
中的表达式不能访问执行上下文;该类表达式只能引用配置文件或者spring中实现监听接口的bean;
3.使用监听器类属性时,都是在创建时采用单例创建,须确保监听器实现不依赖于成员字段,或确保多线程/上下文的安全使用。
4.使用非法的事件属性或者非法的抛出事件,部署流程定义时会抛出异常,事件部署失败;非法的类或者delegateExecution
出现,会在流程启动时(或流程定义的第一个合法事件被处理时)抛出异常。须确保引用的类在classpath下且表达式可被处理为合法实例。
使用API处理事件
activiti通过API开放了事件处理机制,允许处理在引擎中注册的监听器事件。推荐使用RuntimeService只处理ActivitiEvents
中CUSTOM类型的事件。
/**
* Dispatches the given event to any listeners that are registered.
* @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);