Flowable入门系列文章10 - 基本配置四

Posted 分享牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flowable入门系列文章10 - 基本配置四相关的知识,希望对你有一定的参考价值。

1、映射的诊断上下文

Flowable支持SLF4j的Mapped Diagnostic Contexts功能。这些基本的信息会被传递到底层的记录器,以及将要记录的内容:

  • processDefinition ID为mdcProcessDefinitionID
  • processInstance Id为mdcProcessInstanceID
  • 执行ID为mdcExecutionId

这些信息都没有记录在默认情况下。记录器可以配置为以所需的格式显示它们,而不是通常记录的消息。例如在Log4j中,以下样本布局定义会使记录器显示上述信息:

log4j.appender.consoleAppender.layout.ConversionPattern=ProcessDefinitionId=%X{mdcProcessDefinitionID}
executionId=%X{mdcExecutionId} mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n

例如,当日志包含需要实时检查的信息时,这非常重要。

2、事件处理程序

Flowable引擎中的事件机制允许您在引擎内发生各种事件时得到通知。查看所有支持的事件类型,以查看可用事件的概述。

可以为特定类型的事件注册侦听器,而不是在发送任何类型的事件时得到通知。您可以通过配置添加引擎范围的事件侦听器,使用API在运行时添加引擎范围的事件侦听器,或者将事件侦听器添加到BPMN XML中的特定流程定义。

所有派发的事件都是一个子类型org.flowable.engine.common.api.delegate.event.FlowableEvent。该事件自曝(如果有的话)type,
executionId,processInstanceId和processDefinitionId。某些事件包含与发生的事件相关的附加上下文,可以在所有支持的事件类型列表中找到有关附加有效载荷的更多信息。

2.1、事件监听器的实现

事件监听器的唯一要求是实现org.flowable.engine.delegate.event.FlowableEventListener。下面是一个监听器的示例实现,它将接收到的所有事件输出到标准输出,但与作业执行相关的事件除外:

public class MyEventListener implements FlowableEventListener {
@Override
public void onEvent(FlowableEvent 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;
}
}

该isFailOnException()方法确定在onEvent(…)调度事件时该方法抛出异常时的行为。当false返回,异常被忽略。何时true返回,异常不会被忽略,冒泡,有效地使当前正在执行的命令失败。如果事件是API调用的一部分(或任何其他事务操作,例如作业执行),则事务将被
回滚。如果事件侦听器中的行为不是关键业务,则建议返回false。

Flowable提供了一些基本的实现来促进事件监听器的常见用例。这些可以用作基类或作为示例监听器实现:

  • org.flowable.engine.delegate.event.BaseEntityEventListener:事件侦听器基类,可用于侦听特定类型实体或所有实体的实体相关事件。它隐藏了类型检查,并提供了4个应该被覆盖的方法onCreate(…),onUpdate(…)以及onDelete(…)当一个实体被创建,更新或删除时。对于所有其他与实体相关的事件,onEntityEvent(…) 被调用。

2.2、配置和设置

如果在流程引擎配置中配置了事件侦听器,则在流程引擎启动时它将处于活动状态,并在引擎的后续重新启动后保持活动状态。

该属性eventListeners需要一个org.flowable.engine.delegate.event.FlowableEventListener实例列表。像往常一样,你可以声明一个内联的bean定义,或者使用一个ref现有的bean来代替。下面的代码片段将一个事件侦听器添加到任何事件分派时通知的配置中,而不管其类型如何:

<bean id="processEngineConfiguration"
class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="eventListeners">
<list>
<bean class="org.flowable.engine.example.MyEventListener" />
</list>
</property>
</bean>

要在发送某些类型的事件时收到通知,请使用typedEventListeners期望地图的属性。地图条目的关键是逗号分隔的事件名称(或单个事件名称)列表。map-entry的值是一个org.flowable.engine.delegate.event.FlowableEventListener实例列表。下面的代码片段将一个事件侦听器添加到配置中,当作业执行成功或失败时会收到通知。

<bean id="processEngineConfiguration"
class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
...
<property name="typedEventListeners">
<map>
<entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
<list>
<bean class="org.flowable.engine.example.MyJobEventListener" />
</list>
</entry>
</map>
</property>
</bean>

调度事件的顺序由听众添加的顺序决定。首先,所有正常的事件侦听器都eventListeners按照它们在其中定义的顺序被调用(属性)list。之后typedEventListeners,如果调度了正确类型的事件,则会调用所有类型的事件侦听器(属性)。

2.3、在运行时添加监听器

通过使用API(RuntimeService),可以添加和删除其他事件侦听器到引擎:

/**
* Adds an event-listener which will be notified of ALL events by the dispatcher.
* @param listenerToAdd the listener to add
*/
void addEventListener(FlowableEventListener 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(FlowableEventListener listenerToAdd, FlowableEventType... 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(FlowableEventListener listenerToRemove);

请注意,引擎重新启动时,在运行时添加的侦听器不会被保留。

2.4、将侦听器添加到流程定义

可以将侦听器添加到特定的流程定义中。只能针对与流程定义相关的事件以及与以特定流程定义启动的流程实例相关的所有事件来调用侦听器。可以使用完全限定的类名定义侦听器实现,该表达式解析为实现侦听器接口的bean,或者可以配置为引发消息/信号/错误BPMN事件。

监听器执行用户定义的逻辑

下面的代码片段为进程定义添加了2个监听器。第一个侦听器将接收任何类型的事件,而侦听器实现则基于完全合格的类名称。第二个侦听器仅在作业成功执行或失败时通知,使用beans在流程引擎配置属性中定义的侦听器。

<process id="testEventListeners">
<extensionElements>
<flowable:eventListener class="org.flowable.engine.test.MyEventListener" />
<flowable:eventListener delegateExpression="${testEventListener}"
events="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" />
</extensionElements>
...
</process>

对于与实体相关的事件,也可以将侦听器添加到只有当某个实体类型发生实体事件时才通知的流程定义。下面的代码展示了如何实现这一点。它可以用于所有实体事件(第一个示例)或仅用于特定事件类型(第二个示例)。

<process id="testEventListeners">
<extensionElements>
<flowable:eventListener class="org.flowable.engine.test.MyEventListener" entityType="task" />
<flowable:eventListener delegateExpression="${testEventListener}" events="ENTITY_CREATED" entityType="task" />
</extensionElements>
...
</process>

为支持的值entityType是:attachment,comment,execution,identity-link,job,process-instance,process-definition,task。

听众抛出BPMN事件

处理事件的另一种方式是抛出一个BPMN事件。请记住,将BPMN事件与某些类型的Flowable事件类型相关联才是有意义的。例如,在删除流程实例时抛出BPMN事件将导致错误。下面的片段展示了如何在process-instance中引发一个信号,向外部进程(global)抛出一个信号,在process-instance内部抛出一个消息事件,并在process-instance内部抛出一个错误事件。除了使用classor之外delegateExpression,throwEvent还使用属性,以及特定于所引发事件类型的附加属性。

<process id="testEventListeners">
<extensionElements>
<flowable:eventListener throwEvent="signal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<flowable:eventListener throwEvent="globalSignal" signalName="My signal" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<flowable:eventListener throwEvent="message" messageName="My message" events="TASK_ASSIGNED" />
</extensionElements>
</process>
<process id="testEventListeners">
<extensionElements>
<flowable:eventListener throwEvent="error" errorCode="123" events="TASK_ASSIGNED" />
</extensionElements>
</process>

如果需要额外的逻辑来决定是否抛出BPMN事件,则可以扩展Flowable提供的侦听器类。通过覆盖isValidEvent(FlowableEvent event) in
your subclass, the BPMN-event throwing can be prevented. The classes involved are
+org.flowable.engine.test.api.event.SignalThrowingEventListenerTest,
org.flowable.engine.impl.bpmn.helper.MessageThrowingEventListener和
org.flowable.engine.impl.bpmn.helper.ErrorThrowingEventListener。

关于流程定义的监听器的注释

  • 事件侦听器只能在process元素上声明,作为子元素extensionElements。在这个过程中,听众不能被定义为单独的活动。
  • 表达式中使用的表达式delegateExpression不能访问执行上下文,因为其他表达式(例如在网关中)具有。他们只能引用beans在流程
    引擎配置的属性中定义的bean,或者在使用Spring(并且beans属性不存在)的情况下,引用任何实现了监听器接口的spring-bean。
  • 当使用class侦听器的属性时,将只创建该类的单个实例。确保侦听器实现不依赖于成员字段或确保多个线程/上下文的安全使用。
  • 当在events属性中使用非法事件类型或使用非法throwEvent值时,部署流程定义时将引发异常(部署失败)。当非法值class或
    delegateExecution提供(或者不存在的类,不存在的豆参考或不执行侦听接口的委托),异常将当该过程开始时引发(或当该流程定
    义的第一个有效事件是派遣给听众)。确保引用的类位于类路径中,并且表达式解析为有效的实例。

2.5、通过API调度事件

我们通过API打开事件分派机制,允许您将自定义事件分配给引擎中注册的任何侦听器。建议(尽管不强制)仅FlowableEvents使用类型进行调度CUSTOM。调度事件可以使用以下方法完成RuntimeService:

/**
* Dispatches the given event to any listeners that are registered.
* @param event event to dispatch.
*
* @throws FlowableException if an exception occurs when dispatching the event or
* when the {@link FlowableEventDispatcher} is disabled.
* @throws FlowableIllegalArgumentException when the given event is not suitable for dispatching.
*/
void dispatchEvent(FlowableEvent event);

2.6、支持的事件类型

下面列出的是所有可能在引擎中发生的事件类型。每个类型都对应于一个枚举值org.flowable.engine.common.api.delegate.event.FlowableEventType。

表1.支持的事件
事件名称描述事件类
ENGINE_CREATED这个监听器所附的进程引擎已经被创建,并且已经准备好进行API调用。org.flowable…FlowableEvent
ENGINE_CLOSED此侦听器所附的进程引擎已关闭。对引擎的API调用不再可能。org.flowable…FlowableEvent
ENTITY_CREATED一个新的实体被创建。新的实体包含在事件中。org.flowable…FlowableEntityEvent
ENTITY_INITIALIZED一个新的实体已经创建并完全初始化。如果任何儿童是创建实体的一部分,则在创建/初始化子实体而不是ENTITY_CREATE事件之后,该事件将被解雇。org.flowable…FlowableEntityEvent
ENTITY_UPDATED现有实体已更新。更新的实体包含在事件中。org.flowable…lowableEntityEvent
ENTITY_DELETED现有的实体被删除。被删除的实体包含在事件中。org.flowable…FlowableEntityEvent
ENTITY_SUSPENDED现有的实体被暂停。暂停的实体包含在事件中。将派发ProcessDefinitions,ProcessInstances和Tasks。org.flowable…FlowableEntityEvent
ENTITY_ACTIVATED现有的实体被激活。激活的实体包含在事件中。将派发ProcessDefinitions,ProcessInstances和Tasks。org.flowable…FlowableEntityEvent
JOB_EXECUTION_SUCCESS工作已成功执行。该事件包含已执行的作业。rg.flowable…FlowableEntityEvent
JOB_EXECUTION_FAILURE作业的执行失败。事件包含已执行的作业和异常。org.flowable…FlowableEntityEvent 和org.flowable…FlowableExceptionEvent
JOB_RETRIES_DECREMENTED由于作业失败,作业重试次数已减。该事件包含已更新的作业。org.flowable…FlowableEntityEvent
TIMER_SCHEDULED计时器作业已创建并计划在将来的某个时间点执行。org.flowable…FlowableEntityEvent
TIMER_FIRED一个计时器已经被解雇了。该事件包含已执行的作业。org.flowable…FlowableEntityEvent
JOB_CANCELED工作已被取消。该事件包含被取消的作业。在新的流程定义部署中,可以通过API调用取消作业,完成任务并取消关联的边界计时器。org.flowable…FlowableEntityEvent
ACTIVITY_STARTED活动正在开始执行org.flowable…FlowableActivityEvent
ACTIVITY_COMPLETED活动已成功完成org.flowable… FlowableActivityEvent
ACTIVITY_CANCELLED一项活动将被取消。活动取消有三个原因(MessageEventSubscriptionEntity,SignalEventSubscriptionEntity,TimerEntity)。org.flowable… FlowableActivityCancelledEvent
ACTIVITY_SIGNALED一个活动收到一个信号org.flowable…FlowableSignalEvent
ACTIVITY_MESSAGE_RECEIVED活动收到消息。在活动收到消息之前分派。收到时,将根据类型(边界事件或事件子进程启动事件)为此活动分派a ACTIVITY_SIGNAL或ACTIVITY_STARTED将被分派,org.flowable…FlowableMessageEvent
ACTIVITY_MESSAGE_WAITING一个活动创建了一个消息事件订阅,正在等待接收。org.flowable…FlowableMessageEvent
ACTIVITY_MESSAGE_CANCELLED已经创建消息事件订阅的活动被取消,因此接收消息不会再触发该特定消息。org.flowable…FlowableMessageEvent
ACTIVITY_ERROR_RECEIVED活动已收到错误事件。在活动处理实际错误之前分派。该事件activityId包含对错误处理活动的引用。如果错误已成功传递,则该事件将随后是ACTIVITY_SIGNALLED事件或ACTIVITY_COMPLETE涉及的活动。org.flowable…FlowableErrorEvent
UNCAUGHT_BPMN_ERROR未捕获的BPMN错误已被抛出。该过程没有任何处理这个特定的错误。事件activityId将是空的。org.flowable…FlowableErrorEvent
ACTIVITY_COMPENSATE一项活动即将得到补偿。该事件包含将被执行以进行补偿的活动的标识。org.flowable…FlowableActivityEvent
VARIABLE_CREATED一个变量已经创建。事件包含变量名称,值和相关的执行和任务(如果有的话)。org.flowable…FlowableVariableEvent
VARIABLE_UPDATED现有变量已更新。该事件包含变量名称,更新的值和相关的执行和任务(如果有的话)。org.flowable…FlowableVariableEvent
VARIABLE_DELETED现有的变量已被删除。该事件包含变量名称,最后一个已知值以及相关的执行和任务(如果有的话)。org.flowable…FlowableVariableEvent
TASK_ASSIGNED任务已分配给用户。该事件包含任务org.flowable…FlowableEntityEvent
TASK_CREATED一项任务已经创建。这是ENTITY_CREATE事件发生后。如果任务是进程的一部分,则在执行任务侦听器之前将触发此事件。org.flowable…FlowableEntityEvent
TASK_COMPLETED一项任务已经完成。这是在ENTITY_DELETE事件之前发出的。如果任务是流程的一部分,那么在流程进行之前,该事件将被触发,并且之后是一个ACTIVITY_COMPLETE事件,针对表示已完成任务的活动。org.flowable…FlowableEntityEvent
PROCESS_CREATED流程实例已经创建。所有的基本属性已经设置,但变量还没有。org.flowable…FlowableEntityEvent
PROCESS_STARTED流程实例已经启动。启动先前创建的流程实例时调度。事件PROCESS_STARTED在关联的事件ENTITY_INITIALIZED之后和变量设置完成后分派。org.flowable…FlowableEntityEvent
PROCESS_COMPLETED一个进程已经完成,意味着进程实例的所有执行已经停止。在最后一个活动ACTIVITY_COMPLETED 事件之后分派。进程在达到进程实例没有进行任何转换的状态时完成。org.flowable…FlowableEntityEvent
PROCESS_COMPLETED_WITH_TERMIN ATE_END_EVENT通过到达终止结束事件完成了一个过程。org.flowable…FlowableProcessTerminatedEvent
PROCESS_CANCELLED一个进程已被取消。在从运行时删除流程实例之前分派。例如,可以通过API调用RuntimeService.deleteProcessInstance,通过呼叫活动中断边界事件来取消流程实例…org.flowable…FlowableCancelledEvent
MEMBERSHIP_CREATED用户已被添加到组中。该事件包含涉及的用户和组的ID。org.flowable…FlowableMembershipEvent
MEMBERSHIP_DELETED用户已从组中删除。该事件包含涉及的用户和组的ID。org.flowable…FlowableMembershipEvent
MEMBERSHIPS_DELETED所有成员将被从一个组中删除。这个事件在成员被移除之前被抛出,所以他们仍然可以访问。MEMBERSHIP_DELETED出于性能原因,如果所有成员一次被删除,则不会抛出任何个人事件。org.flowable…FlowableMembershipEvent

所有ENTITY_*事件都与引擎内的实体相关。下面的列表显示了哪些实体事件分派给哪些实体:

  • ENTITY_CREATED, ENTITY_INITIALIZED, ENTITY_DELETED:附件,评论,部署,执行,组,IdentityLink,作业,模型,
    ProcessDefinition,ProcessInstance,任务,用户。
  • ENTITY_UPDATED:附件,部署,执行,组,IdentityLink,作业,模型,ProcessDefinition,ProcessInstance,任务,用户。
  • ENTITY_SUSPENDED, ENTITY_ACTIVATED:ProcessDefinition,ProcessInstance / Execution,任务。

上面文章来自盘古BPM研究院:http://vue.pangubpm.com/
文章翻译提交:https://github.com/qiudaoke/flowable-userguide
了解更多文章可以关注微信公众号:

以上是关于Flowable入门系列文章10 - 基本配置四的主要内容,如果未能解决你的问题,请参考以下文章

Flowable入门系列文章20 - 基本的Flowable概念一

Flowable入门系列文章7 - 基本配置一

Flowable入门系列文章8 - 基本配置二

Flowable入门系列文章22 - 基本的Flowable概念三

Flowable入门系列文章21 - 基本的Flowable概念二

Flowable入门系列文章34 - Activity解读 10