Flowable核心事件详细解释说明并附上示例代码
Flowable的核心事件类型
下表列出引擎中的所有事件类型。每种类型对应org.flowable.engine.common.api.delegate.event.FlowableEventType
中的一个枚举值。
事件名称 | 说明 | 事件类 |
---|---|---|
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…FlowableEntityEvent |
ENTITY_DELETED | 实体已经删除。该实体包含在本事件里。 | org.flowable…FlowableEntityEvent |
ENTITY_SUSPENDED | 实体已经暂停。该实体包含在本事件里。ProcessDefinitions(流程定义), ProcessInstances(流程实例)与Tasks(任务)会分发本事件。 | org.flowable…FlowableEntityEvent |
ENTITY_ACTIVATED | 实体已经激活。该实体包含在本事件里。ProcessDefinitions, ProcessInstances与Tasks会分发本事件。 | org.flowable…FlowableEntityEvent |
JOB_EXECUTION_SUCCESS | 作业已经成功执行。该作业包含在本事件里。 | org.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 | 节点收到了一个消息。事件在节点接收消息前分发。节点接收消息后,会为该节点分发 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 | 节点将要被补偿(compensate)。该事件包含将要执行补偿的节点id。 | org.flowable…FlowableActivityEvent |
MULTI_INSTANCE_ACTIVITY_STARTED | 多实例节点开始执行 | org.flowable…FlowableMultiInstanceActivityEvent |
MULTI_INSTANCE_ACTIVITY_COMPLETED | 多实例节点成功完成 | org.flowable…FlowableMultiInstanceActivityEvent |
MULTI_INSTANCE_ACTIVITY_CANCELLED | 多实例节点将要取消。多实例节点的取消有三个原因(MessageEventSubscriptionEntity, SignalEventSubscriptionEntity, TimerEntity)。 | org.flowable…FlowableMultiInstanceActivityCancelledEvent |
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_TERMINATE_END_EVENT | 流程已经到达终止结束事件(terminate 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 |
流程引擎事件
ENGINE_CREATED 事件
深入解释:
ENGINE_CREATED
事件在Flowable工作流引擎的实例被完全创建并初始化后触发。这包括了所有必要的组件(如数据库连接、缓存、任务管理器等)的初始化和配置。这个事件是引擎启动过程中最后一个主要阶段,标志着引擎已经准备好接受和执行流程定义及其实例。
高级应用示例:
- 动态配置加载:在引擎创建时,根据外部配置文件或环境变量动态加载配置信息。这可以包括数据库连接参数、任务监听器、流程执行监听器等的配置。
- 插件注册:在引擎启动时,自动注册和初始化Flowable的插件系统。这些插件可以扩展引擎的功能,如添加新的任务类型、实现自定义的行为等。
- 流程模板部署:如果系统依赖于预定义的流程模板,可以在引擎创建时自动部署这些模板到引擎中,以便流程实例可以基于这些模板创建。
ENGINE_CLOSED 事件
深入解释:
ENGINE_CLOSED
事件在Flowable工作流引擎的实例被关闭时触发。这通常发生在应用程序停止运行或引擎需要被重启以应用更改时。关闭过程可能包括关闭数据库连接、释放系统资源、停止后台线程等。ENGINE_CLOSED
事件是引擎生命周期中的最后一个阶段,标志着引擎已经完全停止并准备被销毁。
高级应用示例:
- 资源清理:在引擎关闭前,确保所有由引擎占用的资源都被正确释放。这可能包括数据库连接池、内存缓存、文件句柄等。
- 未完成任务处理:在引擎关闭前,遍历所有未完成的任务和流程实例,并决定它们的处理方式。这可能包括将它们保存到持久化存储中以便在引擎重启后恢复,或者向相关人员发送通知。
- 统计和日志记录:在引擎关闭时,记录引擎的运行时间和性能指标,以及任何重要的日志信息。这些信息可以用于监控、调试或性能优化。
总结
在Flowable中有效利用这些事件可以显著提升工作流引擎的灵活性和可扩展性。通过自定义事件,可以轻松地集成外部系统、执行复杂的业务逻辑;通过ENGINE_CREATED
和ENGINE_CLOSED
事件,可以在引擎的生命周期中执行必要的初始化和清理操作,确保系统的稳定运行。在实际应用中,结合具体的业务场景和需求,合理选择和运用这些事件,可以构建出高效、可靠且易于维护的工作流解决方案。
实体相关事件
引擎中所有的 ENTITY_\*
事件都与实体关联。下表列出每个实体分发的实体事件:
流程实体创建
ENTITY_CREATED
解释:当一个新的Flowable实体(如流程定义、流程实例、任务等)被创建时触发。这是实体生命周期的开始。
高级应用示例:
- 在流程定义创建时,自动检查并设置特定的权限控制,确保只有授权用户才能启动该流程。
- 使用事件监听器记录新创建的实体到审计日志中,包括创建者、时间戳和IP地址等详细信息。
流程实体初始化
ENTITY_INITIALIZED
解释:虽然Flowable官方文档不直接提及ENTITY_INITIALIZED
作为标准事件(可能是特定环境下的自定义或误解),我们可以理解为某个实体在创建后需要进一步初始化(比如设置初始属性)的过程完成后触发的事件。
高级应用示例(假设场景):
- 在任务创建并初始化(如设置任务优先级、分配人)后,自动发送通知给任务分配人。
- 初始化完成后,根据特定条件自动调整流程实例的路由逻辑。
流程实体更新
ENTITY_UPDATED
解释:当Flowable中的实体(如任务状态、流程变量等)被更新时触发。
高级应用示例:
- 实时监控流程变量的变化,如果某个关键变量达到特定阈值,则触发自动审批流程。
- 当任务状态更新为“已完成”时,自动触发后续任务或流程的启动。
流程实体删除
ENTITY_DELETED
解释:当Flowable中的实体被删除时触发。
高级应用示例:
- 在删除流程定义前,检查是否有正在运行的流程实例,如果有,则阻止删除或先终止所有实例。
- 删除任务时,自动更新相关报表或分析数据,以反映最新的任务状态。
流程实体挂起
ENTITY_SUSPENDED
解释:当Flowable中的流程实例、流程定义或任务被挂起时触发。挂起意味着实体暂时不会继续执行。
高级应用示例:
- 在挂起流程实例时,自动通知所有参与者流程已暂停,并说明原因。
- 实现基于时间或条件的自动恢复机制,当条件满足时自动恢复挂起的流程实例。
流程实体激活
ENTITY_ACTIVATED
解释:与ENTITY_SUSPENDED
相反,当Flowable中的挂起实体被激活时触发。
高级应用示例:
- 在激活流程实例时,自动发送通知给所有等待的参与者,告知他们可以继续进行。
- 根据流程状态,在激活时自动调整流程路由或执行特定操作。
通用的事件类型
自定义事件
自定义事件(CUSTOM
事件类似概念)的解释
-
在Flowable工作流引擎中,虽然
CUSTOM
事件本身并不是一个直接由Flowable引擎预定义的标准事件类型(如ACTIVITY_COMPLETED
、PROCESS_STARTED
等),但Flowable提供了强大的事件监听和扩展机制,允许开发者定义和触发自定义事件(CUSTOM
),以满足复杂的业务需求。以下是对自定义事件(我们可以称之为CUSTOM
事件的类似概念)的深入解释及高级应用示例。在Flowable中,自定义事件通常不是通过预定义的事件类型直接实现的,而是通过以下几种方式实现:
- 自定义监听器:开发者可以实现
DelegateExecutionListener
、TaskListener
等接口来创建自定义监听器,这些监听器可以监听流程执行过程中的特定事件(如流程启动、任务完成等),并在这些事件发生时执行自定义逻辑。这些自定义逻辑可以包括触发自定义事件,即所谓的CUSTOM
事件。 - 服务任务(Service Task):在BPMN流程中,服务任务允许执行Java代码或调用外部服务。开发者可以在服务任务中定义自定义逻辑,包括触发自定义事件。
- 边界事件:在某些情况下,开发者可以使用边界事件(如错误边界事件)来监听并响应特定类型的错误或条件,这些也可以被视为一种自定义事件的触发机制。
- 全局脚本任务:Flowable支持在流程中使用脚本(如JavaScript),这些脚本可以在流程执行时执行任意代码,包括触发自定义事件。
高级应用示例
假设我们有一个复杂的订单处理流程,其中包括多个审批步骤和可能的异常处理场景。我们可以利用自定义事件来优化这个流程,以下是一个高级应用示例:
场景描述
在订单处理流程中,当订单金额超过一定阈值时,需要触发一个自定义的
HIGH_VALUE_ORDER_REVIEW
事件,以便进行高级别的审核。实现步骤
-
定义自定义事件:
在Flowable中,虽然不直接定义CUSTOM
事件类型,但我们可以定义一个接口或类来表示这个自定义事件,或者简单地通过流程变量或日志记录来标记事件的发生。 -
使用服务任务触发事件:
在BPMN流程中,我们可以添加一个服务任务来检查订单金额。如果金额超过阈值,则在服务任务中触发自定义事件。这可以通过修改流程变量、发送消息到消息队列、调用外部服务或记录日志来实现。@Override public void execute(DelegateExecution execution) throws Exception { Integer orderAmount = (Integer) execution.getVariable("orderAmount"); Integer threshold = 10000; // 假设阈值为10000 if (orderAmount > threshold) { // 触发自定义事件,例如:记录日志、发送消息等 execution.setVariable("isHighValueOrder", true); // 假设有消息服务来发送事件 messageService.send("HIGH_VALUE_ORDER_REVIEW", orderId); } }
-
监听自定义事件:
在Flowable之外,我们可以设置一个监听器来监听自定义事件的触发。这个监听器可以是一个消息队列的消费者、一个REST API的端点或一个定时检查日志的脚本。当监听到HIGH_VALUE_ORDER_REVIEW
事件时,执行相应的逻辑,如通知高级审批员。 -
流程集成:
确保自定义事件触发逻辑与Flowable流程无缝集成,以便在流程执行过程中实时响应自定义事件。
通过上述步骤,我们可以在Flowable工作流引擎中实现类似
CUSTOM
事件的自定义事件机制,以支持复杂的业务流程需求。这种机制为高级流程开发工程师提供了强大的灵活性和控制能力。 - 自定义监听器:开发者可以实现
流程执行事件
流程开始事件
ACTIVITY_STARTED
当流程执行到某个活动时,并且该活动已经开始执行(即,它已经被分配给了某个执行者,或者是一个自动活动已经开始执行),ACTIVITY_STARTED
事件会被触发。这个事件是活动生命周期的起点,标志着活动正式进入执行阶段。
高级应用示例:
- 日志记录:在活动开始时记录详细的日志信息,包括活动的名称、类型、执行者、开始时间等。这些信息对于后续的监控、审计和调试非常有用。
- 资源分配:如果活动需要特定的资源(如外部系统的访问权限、数据库连接等),可以在活动开始时分配这些资源。
- 通知发送:向执行者或相关方发送通知,告知他们某个活动已经开始执行。
流程完成事件
ACTIVITY_COMPLETED
:
当某个活动成功完成其执行(无论是人工任务由执行者完成,还是自动活动按照预定逻辑执行完毕),ACTIVITY_COMPLETED
事件会被触发。这个事件标志着活动生命周期的结束,并且流程可能会根据活动的完成状态来决定下一步的执行路径。
高级应用示例:
- 结果处理:捕获活动的执行结果,并根据结果进行后续处理。例如,如果活动是一个表单填写任务,可以在任务完成后收集表单数据并进行处理。
- 性能监控:记录活动的执行时间、成功率等性能指标,用于监控和优化流程的执行效率。
- 触发后续流程:根据活动的完成状态触发其他流程或子流程的执行。例如,一个销售流程的订单确认活动完成后,可以触发发货流程的开始。
流程取消事件
ACTIVITY_CANCELLED
:
在某些情况下,如果活动在执行过程中被取消(可能是由于流程被取消、活动超时、执行者拒绝执行任务等原因),ACTIVITY_CANCELLED
事件会被触发。这个事件表示活动没有按照预期完成,而是被提前终止了。
高级应用示例:
- 资源回收:在活动被取消时,释放由该活动占用的资源,如文件句柄、数据库连接等。
- 通知发送:向执行者或相关方发送通知,告知他们某个活动已被取消。
- 异常处理:在活动被取消时执行特定的异常处理逻辑,如记录错误日志、触发补偿流程等。
总结
ACTIVITY_STARTED
、ACTIVITY_COMPLETED
和 ACTIVITY_CANCELLED
事件为Flowable工作流引擎的开发者提供了在活动生命周期的关键阶段执行自定义逻辑的能力。通过监听这些事件并编写相应的处理逻辑,开发者可以实现复杂的业务逻辑、增强流程的可监控性和可维护性,以及提高系统的整体性能和可靠性。
信号事件
概念解释:
- ACTIVITY_SIGNAL_WAITING:通常表示一个活动正在等待接收一个信号以继续执行。
- ACTIVITY_SIGNALED:表示活动已经接收到信号并准备继续执行。
高级应用示例:
在Flowable中,信号(Signal)是一种全局作用域的事件,可以用于在流程实例之间或内部传递信息。开发者可以使用RuntimeService.signalEventReceived(String signalName)
方法来触发信号事件。
- 示例:假设有一个订单处理流程,在订单支付成功后需要触发库存更新流程。可以在订单支付成功节点发送一个“支付成功”信号,库存更新流程中的信号捕获节点接收到该信号后继续执行库存更新操作。
补偿事件
概念解释:
- ACTIVITY_COMPENSATE:通常与补偿边界事件相关,表示需要执行补偿逻辑以撤销或回滚之前活动的结果。
高级应用示例:
在Flowable中,补偿边界事件可以为所依附的节点附加补偿处理器,当补偿边界事件触发时,执行其连接的补偿处理器。
- 示例:在请假流程中,如果经理审批了请假申请但随后需要撤销该审批,可以设置一个补偿边界事件来触发撤销操作,如更新数据库中的请假状态、发送通知给员工等。
条件等待和接收
概念解释:
- ACTIVITY_CONDITIONAL_WAITING:表示活动正在等待某个条件成立以继续执行。
- ACTIVITY_CONDITIONAL_RECEIVED:表示活动已经接收到条件成立的消息,并准备继续执行。
高级应用示例:
在Flowable中,条件通常通过排他网关(Exclusive Gateway)和表达式(Expression)来实现。
- 示例:在订单处理流程中,可以根据订单金额的大小选择不同的处理路径。使用排他网关和表达式来判断订单金额,当条件满足时(如订单金额大于某个阈值),流程会沿着满足条件的路径继续执行。
升级事件
概念解释:
- ACTIVITY_ESCALATION_WAITING 和 ACTIVITY_ESCALATION_RECEIVED:这些事件通常与任务的升级相关,表示任务在等待升级处理或已经接收到升级处理的响应。
高级应用示例:
在Flowable中,可以通过配置任务的升级规则(如超时时间、升级对象等)来实现任务的自动升级。
- 示例:在客户服务流程中,如果某个客户请求在指定时间内未得到响应,可以将其升级给更高级别的客服人员处理。
消息事件
概念解释:
- ACTIVITY_MESSAGE_WAITING、ACTIVITY_MESSAGE_RECEIVED 和 ACTIVITY_MESSAGE_CANCELLED:这些事件与消息传递相关,分别表示活动在等待接收消息、已接收到消息以及消息被取消的状态。
高级应用示例:
在Flowable中,消息事件可以通过消息中间件或内部消息传递机制来实现。
- 示例:在订单发货流程中,当仓库准备好货物后,可以发送一个“货物已备好”的消息给发货部门。发货部门接收到消息后继续执行发货操作。如果因为某种原因需要取消发货,可以发送一个取消消息来中断发货流程。
错误事件
概念解释:
- ACTIVITY_ERROR_RECEIVED:表示活动已经接收到一个错误事件,并准备根据错误进行相应的处理。
高级应用示例:
在Flowable中,错误事件通常用于处理流程执行过程中出现的异常情况。
- 示例:在支付流程中,如果支付接口返回错误,可以捕获该错误事件并触发相应的补偿逻辑(如退款操作)或通知相关人员进行处理。
注意
由于Flowable的标准事件枚举中可能不包含上述所有直接命名的事件,因此在实际应用中,开发者可能需要通过监听特定类型的活动或任务事件,并结合流程定义中的逻辑来间接实现这些高级功能。此外,Flowable提供了丰富的API和扩展点,允许开发者根据业务需求自定义事件监听器和处理逻辑。
多实例事件
多实例活动开始事件
- MULTI_INSTANCE_ACTIVITY_STARTED
- 解释:此事件在多实例活动开始时触发。在BPMN(Business Process Model and Notation)中,多实例活动允许一个活动并行或顺序执行多次。当这样的活动开始执行其第一个实例时,会触发此事件。
- 应用示例:在一个审批流程中,可能有多个审批者需要并行审批同一个申请。当审批活动开始(即第一个审批者开始审批)时,可以触发此事件来记录审批流程的启动时间或进行其他初始化操作。
多实例活动完成事件
- MULTI_INSTANCE_ACTIVITY_COMPLETED
- 解释:此事件在多实例活动的所有实例都完成时触发。即当所有并行或顺序执行的活动实例都达到完成状态时,会触发此事件。
- 应用示例:在审批流程中,当所有审批者都完成审批后,可以触发此事件来执行后续操作,如发送审批结果通知、更新系统状态等。
多实例活动特定情况事件
- MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION
- 解释:此事件在Flowable 6.3及以后版本中引入,用于表示多实例活动在满足特定条件时完成。与
MULTI_INSTANCE_ACTIVITY_COMPLETED
不同,此事件可能涉及更复杂的完成逻辑,如基于特定条件筛选完成的实例。 - 应用示例:在一个需要特定数量审批通过的流程中,只有当达到一定的“同意”票数时,才认为审批活动完成。此时,可以触发
MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION
事件来执行后续操作。
多实例活动取消事件
- MULTI_INSTANCE_ACTIVITY_CANCELLED
- 解释:此事件在多实例活动被取消时触发。活动取消可以由多种原因引起,如流程实例的取消、边界事件的触发或流程逻辑中的特定条件。
- 应用示例:在审批流程中,如果某个审批环节被取消(如申请人撤销申请),则所有未完成的审批实例都将被取消。此时,可以触发此事件来执行清理操作,如撤销已分配的任务、释放资源等。
示例场景:请假审批流程
假设有一个请假审批流程,其中包括多个审批者(如部门经理、人力资源部门)需要并行审批请假申请。
- 流程设计:
- 使用Flowable Designer或Flowable Web Modeler创建BPMN 2.0流程定义。
- 在流程中设置一个多实例用户任务,指定多个审批者作为候选用户。
- 设置完成条件和取消条件(如所有审批者都同意则完成,申请人撤销申请则取消)。
- 事件监听与响应:
- 监听
MULTI_INSTANCE_ACTIVITY_STARTED
事件,记录审批流程的开始时间。 - 监听
MULTI_INSTANCE_ACTIVITY_COMPLETED
和MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION
事件,根据审批结果执行后续操作(如发送通知、更新系统状态)。 - 监听
MULTI_INSTANCE_ACTIVITY_CANCELLED
事件,执行清理操作(如撤销已分配的任务、释放资源)。
- 监听
- 自定义逻辑:
- 实现自定义的FlowableEventListener或DelegateExecutionListener来响应这些事件。
- 在监听器中编写逻辑来处理流程状态的变化,如更新数据库记录、发送邮件通知等。
高级应用示例
示例 1: 多实例用户任务完成时发送通知
当所有用户都完成了他们的任务(即多实例用户任务完成时),发送一封电子邮件通知给所有参与者。
代码实现(使用Java Delegate作为监听器):
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
public class MultiInstanceCompletedListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
// 检查是否为多实例活动完成事件
if (execution.getEventName().equals(ExecutionListener.EVENTNAME_MULTI_INSTANCE_ACTIVITY_COMPLETED)) {
// 发送通知逻辑(这里使用伪代码)
sendCompletionNotification(execution);
}
}
private void sendCompletionNotification(DelegateExecution execution) {
// 获取参与者列表、流程变量等信息
// ...
// 发送电子邮件或其他通知
// ...
}
}
在BPMN文件中,你需要将此监听器添加到多实例活动的“完成”边界事件上(尽管Flowable的BPMN模型可能不直接支持将监听器附加到多实例完成事件上,但你可以通过监听整个流程实例的结束或使用其他机制来实现)。
示例 2: 基于条件的多实例完成
假设你有一个多实例服务任务,每个实例都需要达到一定的条件(如处理成功)才能被认为是完成的。当所有实例都满足条件并完成时,执行特定操作。
这通常需要通过自定义逻辑来实现,比如在服务任务中设置标志位,并在流程中的某个点(如使用边界事件监听器或流程结束监听器)检查这些标志位。
注意:由于Flowable没有直接提供MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION
事件,你需要自己管理条件检查和逻辑执行。
结论
在Flowable中处理多实例活动的事件时,开发者需要利用Flowable提供的监听器、委托(Delegates)和脚本功能来编写自定义逻辑。由于BPMN规范的限制和Flowable的具体实现,某些高级功能可能需要通过创造性的解决方案来实现。
历史活动实例事件
历史活动实例创建
- HISTORIC_ACTIVITY_INSTANCE_CREATED
- 含义:此事件在流程执行过程中,当一个新的活动实例被创建时触发。这里的活动实例可以是用户任务、服务任务、脚本任务等BPMN中的任何活动。
- 应用:该事件对于审计、监控和流程优化非常重要。通过监听此事件,开发者可以记录活动实例的创建时间、创建者、活动类型等关键信息,用于后续的分析和报告。
历史活动实例完成
- HISTORIC_ACTIVITY_INSTANCE_ENDED
- 含义:此事件在流程执行过程中,当一个活动实例完成时触发。无论是正常完成还是被取消,只要活动实例的执行状态变为结束,就会触发此事件。
- 应用:与
HISTORIC_ACTIVITY_INSTANCE_CREATED
类似,此事件也用于审计、监控和流程优化。通过监听此事件,开发者可以获取活动实例的完成时间、完成者、执行结果等信息,进一步分析流程的执行效率和性能。
高级应用示例
- 流程性能分析
- 应用场景:在复杂的业务流程中,开发者可能需要分析各个活动实例的执行时间,以识别瓶颈和优化流程。
- 实现方式:通过监听
HISTORIC_ACTIVITY_INSTANCE_CREATED
和HISTORIC_ACTIVITY_INSTANCE_ENDED
事件,记录每个活动实例的创建和结束时间。然后,计算每个活动实例的执行时间,并将其存储在数据库中或进行实时分析。基于这些数据,开发者可以生成性能报告,识别出执行时间较长的活动实例,并采取相应的优化措施。
- 流程异常监控
- 应用场景:在流程执行过程中,可能会出现异常情况,如活动实例被意外取消或执行失败。
- 实现方式:通过监听
HISTORIC_ACTIVITY_INSTANCE_ENDED
事件,并检查活动实例的结束状态(如是否被取消或执行失败),开发者可以及时发现并处理这些异常情况。例如,当检测到某个关键活动实例被取消时,可以自动触发补偿流程或发送警报通知相关人员。
- 流程审计
- 应用场景:在需要遵守特定法规或行业标准的业务流程中,开发者可能需要记录流程执行的详细历史信息以供审计。
- 实现方式:通过监听
HISTORIC_ACTIVITY_INSTANCE_CREATED
和HISTORIC_ACTIVITY_INSTANCE_ENDED
事件,开发者可以记录每个活动实例的创建时间、完成时间、执行者、执行结果等关键信息。这些信息可以存储在数据库中,并在需要时进行检索和查询,以满足审计要求。
总结
HISTORIC_ACTIVITY_INSTANCE_CREATED
和HISTORIC_ACTIVITY_INSTANCE_ENDED
是Flowable工作流引擎中非常重要的历史事件,它们为开发者提供了强大的机制来监控和响应流程执行过程中活动实例的创建和结束。通过合理利用这些事件,开发者可以实现流程性能分析、异常监控和审计等功能,从而优化流程执行效率、提高业务处理能力和满足合规性要求。
历史和审计事件
历史流程实例创建
- HISTORIC_PROCESS_INSTANCE_CREATED
- 高级解释:当一个新的流程实例被创建时,
HISTORIC_PROCESS_INSTANCE_CREATED
事件被触发。这个事件不仅表示流程实例的开始,还允许开发者在流程实例的生命周期早期就介入,记录或处理与流程实例创建相关的元数据。这些元数据可能包括流程定义ID、启动者、启动时间、业务键(如果有的话)等。 - 应用场景:开发者可以利用这个事件来初始化流程实例的特定历史记录属性,比如设置自定义的审计字段或标记特定的流程实例以供后续分析。此外,还可以根据流程实例的创建触发外部系统的操作,如数据同步、资源预留或通知发送。
- 高级解释:当一个新的流程实例被创建时,
历史流程实例完成
- HISTORIC_PROCESS_INSTANCE_ENDED
- 高级解释:当一个流程实例完成其执行(无论是正常结束还是异常终止)时,
HISTORIC_PROCESS_INSTANCE_ENDED
事件被触发。这个事件为开发者提供了在流程实例生命周期结束时进行清理、分析或报告的机会。通过检查流程实例的结束状态、持续时间、涉及的任务和变量等信息,开发者可以深入了解流程的执行情况和性能。 - 应用场景:开发者可以利用这个事件来生成流程执行的摘要报告,包括流程的执行时间、关键路径、瓶颈分析等信息。此外,还可以根据流程实例的结束状态触发后续操作,如发送完成通知、更新外部系统状态、执行清理任务等。在自动化测试和持续集成环境中,这个事件还可以用于验证流程执行的结果是否符合预期。
- 高级解释:当一个流程实例完成其执行(无论是正常结束还是异常终止)时,
高级应用示例
示例1:流程实例性能监控与优化
在一个大型组织中,可能需要监控和优化关键业务流程的性能。高级流程开发工程师可以编写一个监听器来监听 HISTORIC_PROCESS_INSTANCE_ENDED
事件。每当流程实例结束时,监听器会收集流程执行的详细信息,如持续时间、等待时间、活动执行次数等,并将这些信息存储到数据库中。
然后,开发者可以使用这些数据来生成报告,分析哪些流程步骤是瓶颈,哪些活动执行效率较低,以及哪些流程实例频繁失败。基于这些分析结果,开发者可以优化流程设计、调整资源分配或改进流程执行策略,以提高整体流程性能。
示例2:流程实例审计与合规性检查
在某些行业(如金融、医疗等)中,流程实例的审计和合规性检查至关重要。高级流程开发工程师可以编写一个监听器来监听 HISTORIC_PROCESS_INSTANCE_CREATED
和 HISTORIC_PROCESS_INSTANCE_ENDED
事件。当流程实例创建时,监听器会记录关键的元数据,如流程定义、启动者、业务键等。当流程实例结束时,监听器会再次检查这些元数据,并与其他系统(如CRM、ERP等)中的数据进行比对,以验证流程执行是否符合法规要求和公司政策。
如果发现任何不合规的情况,监听器可以触发警报或通知,以便及时采取措施进行纠正。通过这种方式,组织可以确保所有业务流程都符合法规要求和内部政策,降低法律风险和合规成本。
当然,下面我将为HISTORIC_PROCESS_INSTANCE_CREATED
和HISTORIC_PROCESS_INSTANCE_ENDED
事件添加代码实现的示例。在Flowable中,这通常涉及编写一个自定义的监听器(Listener)或使用现有的监听器框架来响应这些事件。
示例:流程实例性能监控与优化
步骤 1: 创建监听器类
首先,你需要创建一个实现了Flowable监听器接口的类。在这个例子中,我们将监听流程实例的创建和结束事件。
import org.flowable.engine.delegate.event.FlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableEvent;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.runtime.ProcessInstance;
public class ProcessInstancePerformanceListener implements FlowableEngineEventListener {
@Override
public void onEvent(FlowableEvent event) {
if (event instanceof FlowableEntityEventImpl) {
FlowableEntityEventImpl entityEvent = (FlowableEntityEventImpl) event;
Object entity = entityEvent.getEntity();
if (entity instanceof ProcessInstance) {
ProcessInstance processInstance = (ProcessInstance) entity;
if (event.getType().equals(FlowableEngineEventType.PROCESS_CREATED)) {
// 处理流程实例创建事件
handleProcessInstanceCreated(processInstance);
} else if (event.getType().equals(FlowableEngineEventType.PROCESS_COMPLETED)) {
// 注意:HISTORIC_PROCESS_INSTANCE_ENDED 在 Flowable 中通常不直接作为事件类型出现,
// 但 PROCESS_COMPLETED 可以在流程完成时触发,并且可用于类似目的
handleProcessInstanceEnded(processInstance);
}
}
}
}
private void handleProcessInstanceCreated(ProcessInstance processInstance) {
// 记录流程实例创建的元数据,例如启动时间、启动者等
System.out.println("Process Instance Created: " + processInstance.getId() + ", Started by: " + processInstance.getStartUserId());
// 这里可以添加代码将信息存储到数据库或日志系统中
}
private void handleProcessInstanceEnded(ProcessInstance processInstance) {
// 分析流程实例的执行情况,如持续时间、涉及的任务等
long duration = System.currentTimeMillis() - processInstance.getStartTime().getTime();
System.out.println("Process Instance Ended: " + processInstance.getId() + ", Duration: " + duration + " ms");
// 在这里,你可以计算更复杂的性能指标,如等待时间、执行时间分布等
// 并将这些信息存储到性能监控系统中
}
// 确保注册此监听器到 Flowable 引擎配置中
// 这通常通过配置文件、编程方式或Spring框架来完成
}
注意:FlowableEngineEventType.PROCESS_CREATED
实际上并不是 Flowable API 中的直接事件类型。Flowable 使用 PROCESS_STARTED
来表示流程实例的开始。但是,为了说明如何响应流程实例的创建和结束,我在上面的示例中使用了 PROCESS_CREATED
和 PROCESS_COMPLETED
作为伪代码。你应该使用 FlowableEngineEventType.PROCESS_STARTED
来监听流程实例的启动,并使用 FlowableEngineEventType.PROCESS_COMPLETED
来监听流程实例的完成。
步骤 2: 注册监听器
将监听器注册到Flowable引擎中,这取决于你的应用是如何配置Flowable的。如果你使用的是Spring Boot,可以通过配置类来注册监听器。
import org.flowable.spring.boot.ProcessEngineAutoConfiguration;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FlowableConfig extends ProcessEngineAutoConfiguration {
@Autowired
private SpringProcessEngineConfiguration processEngineConfiguration;
@Bean
public void registerProcessInstancePerformanceListener() {
ProcessInstancePerformanceListener listener = new ProcessInstancePerformanceListener();
processEngineConfiguration.getEventDispatcher().addEventListener(listener);
}
}
在这个配置类中,我们创建了一个 ProcessInstancePerformanceListener
的Bean,并将其添加到Flowable的事件分发器中。这样,每当流程实例被创建或完成时,监听器就会被触发。
请注意,这个示例是基于Spring Boot的,如果你的应用不是基于Spring Boot的,注册监听器的方式将会有所不同。你可能需要在Flowable引擎的配置文件中直接添加监听器
控制流转移事件
SEQUENCEFLOW_TAKEN
在Flowable工作流引擎中,SEQUENCEFLOW_TAKEN
事件是一个关键的事件类型,它标志着流程控制流(也称为序列流)的转移。当流程执行从一个活动(Activity)转移到另一个活动时,就会触发这个事件。这个事件为开发者提供了在流程执行过程中介入和修改行为的机会,从而实现了更高级的工作流逻辑。
事件含义
- SEQUENCEFLOW_TAKEN:当流程执行路径(即序列流)从一个活动节点到另一个活动节点时触发。这包括从开始事件到第一个活动、从一个活动到另一个活动、以及从活动到结束事件的转移。
- 事件上下文:此事件通常包含有关触发转移的序列流的详细信息,如序列流的ID、源活动ID、目标活动ID等。此外,还可能包含与流程实例、任务实例或执行实例相关的其他信息。
监听器与处理器
- 事件监听器:开发者可以注册事件监听器来监听
SEQUENCEFLOW_TAKEN
事件。这些监听器可以是Java类,它们实现了Flowable提供的特定接口(如TaskListener
、ExecutionListener
或更通用的EventListener
),并定义了当事件发生时应该执行的方法。 - 处理器逻辑:在监听器的方法中,开发者可以编写自定义逻辑来响应事件。这可能包括更新数据库、发送通知、验证数据、修改流程变量等。
高级应用示例
示例 1:动态路由
在某些情况下,流程的执行路径可能需要根据运行时数据动态决定。通过使用SEQUENCEFLOW_TAKEN
事件监听器,开发者可以在流程执行过程中检查流程变量或外部数据,并根据这些数据动态地选择下一个活动。
实现步骤:
- 定义一个包含多个序列流和条件表达式的网关(如排他网关)。
- 注册一个
SEQUENCEFLOW_TAKEN
事件监听器,该监听器在网关之前执行。 - 在监听器中,根据流程变量或外部数据源的值,动态地设置网关的条件表达式或修改流程变量以影响路由决策。
示例 2:性能监控与日志记录
为了监控流程执行的性能并记录详细的日志,开发者可以使用SEQUENCEFLOW_TAKEN
事件来记录每次序列流转移的时间戳和相关信息。
实现步骤:
- 注册一个
SEQUENCEFLOW_TAKEN
事件监听器。 - 在监听器中,记录当前时间戳、序列流ID、源活动ID、目标活动ID以及任何其他相关信息。
- 将这些信息存储到数据库、日志文件或消息队列中,以便后续分析和报告。
示例 3:安全性与权限检查
在涉及敏感数据或需要特定权限的流程中,开发者可以在序列流转移时执行安全性或权限检查。
实现步骤:
- 注册一个
SEQUENCEFLOW_TAKEN
事件监听器,该监听器在访问敏感数据或执行需要权限的活动之前执行。 - 在监听器中,检查当前用户的权限或角色,并验证他们是否有权执行下一步操作。
- 如果用户没有适当的权限,则可以通过抛出异常、记录错误或重定向流程执行来阻止操作。
结论
SEQUENCEFLOW_TAKEN
事件是Flowable工作流引擎中一个非常有用的特性,它允许开发者在流程执行过程中介入并修改行为。通过利用这个事件,开发者可以实现更高级的工作流逻辑,如动态路由、性能监控、日志记录以及安全性与权限检查等。这些高级应用示例展示了SEQUENCEFLOW_TAKEN
事件在复杂工作流场景中的潜力和价值。
流程变量事件
在Flowable工作流引擎中,VARIABLE_CREATED
、VARIABLE_UPDATED
、VARIABLE_DELETED
是与流程变量变化相关的事件,这些事件允许开发者在流程执行过程中监听并响应流程变量的创建、更新和删除操作。这对于需要基于流程变量状态变化执行特定逻辑的高级流程开发来说非常重要。
1. 流程变量
在Flowable中,流程变量是存储在流程执行实例(ProcessInstance
)或任务实例(Task
)中的键值对数据,用于在流程执行期间传递数据。流程变量可以是任何可序列化的Java对象。
2. 事件监听
当流程变量发生变化时(即被创建、更新或删除),Flowable会触发相应的事件。开发者可以通过实现自定义的事件监听器来监听这些事件,并在事件发生时执行自定义逻辑。
3. 监听器类型
对于流程变量相关的事件,开发者通常会实现 ExecutionListener
或 TaskListener
(尽管对于变量变化,ExecutionListener
更常见),但Flowable还提供了更细粒度的监听机制,如通过Java Delegate或Expression监听特定事件。然而,直接监听VARIABLE_CREATED
、VARIABLE_UPDATED
、VARIABLE_DELETED
这样的事件可能需要依赖Flowable的内部事件分发机制或自定义扩展。
高级应用示例
由于Flowable标准API中可能不直接提供VARIABLE_CREATED
、VARIABLE_UPDATED
、VARIABLE_DELETED
事件的监听接口,我们可以通过以下几种方式来实现类似的功能:
示例 1:使用 ExecutionListener
监听任务或流程节点
虽然这不是直接监听变量变化,但可以在任务或流程节点执行前后检查变量状态。
public class VariableChangeListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) throws Exception {
// 假设我们在这个节点后检查某个变量的变化
String variableName = "someVariable";
Object oldValue = execution.getPreviousVariable(variableName);
Object newValue = execution.getVariable(variableName);
if (oldValue == null && newValue != null) {
// 变量被创建
System.out.println("Variable " + variableName + " created with value: " + newValue);
} else if (oldValue != null && !oldValue.equals(newValue)) {
// 变量被更新
System.out.println("Variable " + variableName + " updated from " + oldValue + " to " + newValue);
} // 注意:直接检测变量删除比较复杂,因为删除后newValue将为null,但无法区分是未被设置还是已被删除
}
}
示例 2:自定义行为或扩展
如果需要更精确地控制变量变化的监听,可能需要考虑自定义Flowable的行为或扩展。这通常涉及对Flowable的源代码进行修改或编写自定义插件。
示例 3:使用外部监听机制
另一种方法是使用外部系统(如数据库触发器、消息队列监听器等)来监听流程变量表的变化。这需要在Flowable数据库表(如ACT_RU_VARIABLE
)上设置触发器或定期轮询这些表以检测变化。
注意
- 直接监听
VARIABLE_CREATED
、VARIABLE_UPDATED
、VARIABLE_DELETED
事件可能需要Flowable的特定版本或自定义扩展支持。 - 在实际应用中,应仔细考虑性能和一致性问题,因为频繁地检查或监听变量变化可能会对系统性能产生影响。
- 变量删除的检测可能比较困难,因为一旦变量被删除,就没有直接的方法来区分它是从未被设置还是被明确删除。
任务生命周期事件
在Flowable工作流引擎中,TASK_CREATED
、TASK_ASSIGNED
、TASK_COMPLETED
、TASK_OWNER_CHANGED
、TASK_PRIORITY_CHANGED
、TASK_DUEDATE_CHANGED
、TASK_NAME_CHANGED
等事件是Flowable为开发者提供的用于响应任务相关状态变化的强大机制。这些事件允许开发者在任务生命周期的关键点上插入自定义逻辑,以实现复杂的业务规则、通知机制或数据同步。
- TASK_CREATED:当任务在流程执行过程中被创建时触发。这通常发生在流程到达一个用户任务节点时。
- TASK_ASSIGNED:当任务被分配给某个用户或组时触发。这可以是在任务创建时自动分配,也可以是在任务创建后通过某种方式(如API调用、用户操作等)进行分配。
- TASK_COMPLETED:当任务被用户或系统完成时触发。这标志着任务执行周期的结束,并可能影响流程的后续执行。
- TASK_OWNER_CHANGED:当任务的拥有者(即分配给哪个用户或组)发生变化时触发。这可能是由于重新分配、权限变更或其他业务逻辑导致的。
- TASK_PRIORITY_CHANGED:当任务的优先级发生变化时触发。优先级的变化可能会影响任务的执行顺序或提醒机制。
- TASK_DUEDATE_CHANGED:当任务的到期日期发生变化时触发。到期日期的变化对于跟踪任务进度和确保按时完成任务至关重要。
- TASK_NAME_CHANGED:当任务的名称发生变化时触发。这可能是由于流程变更、用户输入或其他业务规则导致的。
高级特性
- 监听器(Listeners):Flowable允许开发者为这些事件注册监听器。监听器可以是Java类(实现特定的监听器接口),也可以是表达式(如Spring表达式语言)。
- 条件表达式:在某些情况下,开发者可能希望仅在满足特定条件时触发监听器逻辑。Flowable支持在监听器配置中使用条件表达式来实现这一点。
- 异步处理:为了提高性能,Flowable允许将某些事件处理逻辑异步执行。这意味着当事件发生时,相关的监听器逻辑不会立即执行,而是会被放入一个队列中,由专门的线程或进程稍后处理。
高级应用示例
示例 1:使用监听器实现任务通知
当任务被分配给某个用户时(TASK_ASSIGNED
事件),开发者可以注册一个监听器来发送通知(如电子邮件、短信或应用内通知)给用户。这有助于确保用户及时了解他们需要完成的任务。
public class TaskAssignedListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
// 获取任务分配的用户ID
String userId = delegateTask.getAssignee();
// 发送通知给用户(这里只是示例,实际实现可能涉及邮件发送、消息推送等)
System.out.println("Sending notification to user " + userId + " for task " + delegateTask.getId());
// ... 发送通知的具体实现 ...
}
}
// 在BPMN文件中配置此监听器以监听TASK_ASSIGNED事件
示例 2:使用条件表达式和监听器实现优先级调整
假设有一个业务规则,要求当某个特定条件满足时(如任务已经延迟),自动提高任务的优先级(TASK_CREATED
或TASK_ASSIGNED
事件时检查)。开发者可以注册一个监听器,并在其中使用条件表达式来检查是否满足提高优先级的条件。
public class PriorityAdjustmentListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
// 假设有一个方法来检查任务是否已经延迟
boolean isLate = checkIfTaskIsLate(delegateTask);
// 如果任务已经延迟,则提高优先级
if (isLate) {
int newPriority = delegateTask.getPriority() + 1; // 假设优先级越高,数值越大
delegateTask.setPriority(newPriority);
System.out.println("Adjusting priority of task " + delegateTask.getId() + " to " + newPriority);
}
}
// 检查任务是否延迟的具体实现(这里只是示例)
private boolean checkIfTaskIsLate(DelegateTask delegateTask) {
// ... 实现检查逻辑 ...
return false; // 示例返回false
}
}
// 在BPMN文件中配置此监听器,并可能使用条件表达式来限制其触发条件
注意:在上面的示例中,checkIfTaskIsLate
方法是一个占位符,你需要根据实际的业务逻辑来实现它。
流程生命周期事件
- PROCESS_CREATED:当一个新的流程实例被创建时触发。这通常发生在流程定义被启动,但流程中的任何活动(如任务)都尚未执行时。
- PROCESS_STARTED:当流程实例中的第一个活动(如用户任务、服务任务等)被执行时触发。这标志着流程实际执行的开始。
- PROCESS_COMPLETED:当流程实例中的所有活动都成功执行完毕,并且流程达到了一个正常结束状态时触发。
- PROCESS_COMPLETED_WITH_TERMINATE_END_EVENT:当流程通过终止结束事件(Terminate End Event)完成时触发。这表示流程被立即终止,并且不会执行后续的任何活动或子流程。
- PROCESS_COMPLETED_WITH_ERROR_END_EVENT:当流程因为某个错误而通过错误结束事件(Error End Event)完成时触发。这通常用于处理异常情况。
- PROCESS_COMPLETED_WITH_ESCALATION_END_EVENT:当流程因为某种原因(如超时、特定条件满足等)触发升级(Escalation)流程,并通过升级结束事件完成时触发。这允许在出现特定问题时采取更高级别的应对措施。
- PROCESS_CANCELLED:当流程实例被取消时触发。取消操作可以由用户发起,也可以通过流程中的特定逻辑(如取消边界事件)触发。
高级应用示例
示例 1:使用监听器记录流程执行统计信息
当流程完成(PROCESS_COMPLETED
)时,开发者可以注册一个监听器来记录流程的执行时间、执行路径、参与者等信息。这些信息可以用于生成流程执行的统计报告,帮助组织了解流程的性能和效率。
public class ProcessCompletedListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
// 获取流程实例ID和流程定义ID
String processInstanceId = execution.getProcessInstanceId();
String processDefinitionId = execution.getProcessDefinitionId();
// 计算流程执行时间(这里需要额外的逻辑来获取开始时间)
long duration = calculateDuration(processInstanceId); // 假设此方法已实现
// 记录流程执行统计信息(这里可能是写入数据库、日志文件或发送消息到消息队列)
recordProcessStatistics(processInstanceId, processDefinitionId, duration);
}
// ... 实现calculateDuration和recordProcessStatistics方法的细节 ...
}
// 在BPMN文件中为流程结束事件配置此监听器
示例 2:处理错误结束事件
当流程因为错误而结束(PROCESS_COMPLETED_WITH_ERROR_END_EVENT
)时,开发者可以注册一个监听器来捕获错误信息,并根据错误类型执行特定的恢复或补偿操作。
public class ErrorEndEventListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
// 获取错误信息(这里假设错误信息以变量的形式存储在流程上下文中)
String errorMessage = (String) execution.getVariable("errorMessage");
// 根据错误类型执行不同的逻辑
if (errorMessage.contains("特定错误代码")) {
handleSpecificError(execution, errorMessage);
} else {
handleGeneralError(execution, errorMessage);
}
}
private void handleSpecificError(DelegateExecution execution, String errorMessage) {
// ... 执行针对特定错误的恢复或补偿操作 ...
}
private void handleGeneralError(DelegateExecution execution, String errorMessage) {
// ... 执行一般性的错误处理逻辑 ...
}
}
// 在BPMN文件中为错误结束事件配置此监听器
示例 3:取消流程实例
在某些情况下,组织可能需要取消正在执行的流程实例(例如,当用户请求取消订单或任务时)。PROCESS_CANCELLED
事件可以与自定义的取消逻辑一起使用,以安全地停止流程执行并清理相关资源。
// 假设有一个API端点用于接收取消请求
@PostMapping("/cancel-process")
public ResponseEntity<String> cancelProcess(@RequestParam String processInstanceId) {
try {
// 调用Flowable API来取消流程实例
runtimeService.deleteProcessInstance(processInstanceId, "Cancelled by user");
// 可以在这里添加额外的逻辑,比如通知参与者流程已被取消
// ...
return ResponseEntity.ok("Process instance " + processInstanceId + " has been cancelled successfully.");
} catch (FlowableException e) {
// 处理Flowable抛出的异常
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to cancel process instance: " + e.getMessage());
}
}
// 注意:在实际应用中,直接删除流程实例可能会导致数据不一致或丢失,特别是当流程实例与外部系统或服务有交互时。
// 更安全的做法可能是设置流程实例的状态为“已取消”,并在后续的流程活动中检查此状态以决定是否继续执行。
// 这可以通过更新流程实例的某个变量或使用Flowable的自定义状态功能来实现。
// 示例:通过更新流程变量来标记流程实例为已取消
// runtimeService.setVariable(processInstanceId, "isCancelled", true);
// 随后,在BPMN流程定义中,可以在每个任务或服务任务之前添加边界事件或网关逻辑来检查"isCancelled"变量的值,
// 如果为true,则可以通过发送消息到用户或执行其他清理操作来结束流程分支。
// 总结,Flowable工作流引擎的事件机制为开发者提供了在流程生命周期的关键节点上插入自定义逻辑的能力,
// 通过合理使用这些事件和相关的API,可以构建出高度灵活和可扩展的业务流程解决方案。
// 提醒:上述示例代码是基于Flowable API的简化表示,具体实现时需要根据Flowable的版本和配置进行调整。
这些高级应用示例展示了如何在Flowable工作流引擎中利用流程生命周期事件来实现复杂的业务逻辑和流程控制。通过注册监听器、处理错误、取消流程实例等方式,开发者可以确保流程的执行符合业务需求,并在必要时采取适当的应对措施。
异步事件处理
在Flowable中,某些事件处理可能需要执行耗时的操作,比如与外部系统的集成、复杂的计算或数据持久化。为了避免阻塞流程执行线程,Flowable支持异步事件处理。通过使用异步执行器(Async Executor),可以将这些耗时的操作异步执行,从而保持流程引擎的高性能和响应性。
// 假设你有一个耗时的操作需要异步执行
@Async
public void performLongRunningTask(DelegateExecution execution) {
// 执行耗时的操作,如调用外部API、数据库查询等
// ...
// 操作完成后,可以更新流程变量或触发其他流程事件
// execution.setVariable("result", result);
// runtimeService.signal(execution.getId());
}
// 注意:@Async注解是Spring框架提供的,用于声明异步方法。
// 如果你的应用没有集成Spring,你需要使用Flowable的Async Executor配置来实现异步执行。
// 在BPMN中,你可以通过服务任务(Service Task)调用这个异步方法,但需要注意确保方法能够正确地从DelegateExecution中获取所需的信息,并在完成后更新流程状态。
事件驱动的业务架构
Flowable的事件机制非常适合构建事件驱动的业务架构。在这种架构中,业务流程的变化(如流程启动、任务完成、错误发生等)会触发相应的事件,这些事件随后被监听器捕获并处理。监听器可以执行各种操作,如更新数据库、发送通知、触发其他流程等。
为了有效地管理这些事件和监听器,你可以使用事件总线(Event Bus)或消息队列(如RabbitMQ、Kafka)来解耦事件的产生者和消费者。Flowable可以配置为将事件发布到这些外部系统,而监听器则可以订阅这些事件并作出响应。
监听器的高级配置
Flowable允许你为不同的流程元素(如用户任务、服务任务、边界事件等)配置监听器。除了基本的执行监听器(Execution Listener)外,Flowable还支持任务监听器(Task Listener)、变量监听器(Variable Listener)等。
- 任务监听器:可以在任务创建、分配、完成等时刻触发,用于执行与任务相关的操作,如发送通知、更新任务属性等。
- 变量监听器:可以在流程变量被创建、更新或删除时触发,用于监控流程执行过程中的数据变化。
通过合理配置这些监听器,你可以对流程执行过程中的各个环节进行精细控制,并在需要时插入自定义逻辑。
监控和日志记录
为了确保流程执行的透明度和可追溯性,Flowable提供了强大的监控和日志记录功能。你可以使用Flowable的REST API或管理界面来查看流程实例、任务、历史记录等信息。
此外,你还可以在监听器或自定义服务中添加日志记录逻辑,以记录流程执行过程中的关键事件和决策点。这些日志信息对于问题排查、性能分析和业务审计都非常重要。
结论
Flowable工作流引擎的事件机制为开发者提供了强大的工具来响应和处理流程执行过程中的状态变化。通过合理利用这些事件和相关的API、监听器、异步执行器等功能,你可以构建出灵活、可扩展且易于维护的业务流程解决方案。同时,结合事件驱动的业务架构、监控和日志记录等最佳实践,你可以进一步提高流程执行的效率和可靠性。
流程实例开始和流程实例完成
在Flowable工作流引擎中,虽然CASE_STARTED
和CASE_ENDED
并不是Flowable直接提供的标准事件类型(Flowable主要围绕BPMN 2.0流程实例进行,而CASE
可能指的是更通用的业务案例或某种特定领域的用例),但我们可以将这些概念映射到Flowable中的PROCESS_STARTED
(即流程实例开始)和PROCESS_COMPLETED
(即流程实例完成)事件上。
- (
CASE_STARTED
类比于PROCESS_STARTED
): 当一个BPMN流程实例被启动时,Flowable会触发PROCESS_STARTED
事件。这允许开发者在流程实例的生命周期早期就介入,执行诸如初始化资源、设置监控、记录日志等任务。 CASE_ENDED
(类比于PROCESS_COMPLETED
): 当一个BPMN流程实例成功完成其所有活动并达到结束状态时,Flowable会触发PROCESS_COMPLETED
事件。这允许开发者执行后处理任务,如清理资源、更新业务数据、发送通知等。
高级应用示例
假设我们有一个业务流程,该流程在启动时需要自动向外部系统发送一个启动通知,并在完成时发送一个完成通知。我们可以使用Flowable的事件监听器来实现这一点。
1. 创建事件监听器
import org.flowable.engine.delegate.event.FlowableEvent;
import org.flowable.engine.delegate.event.FlowableEventListener;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.runtime.ProcessInstance;
public class CaseNotificationListener implements FlowableEventListener {
@Override
public void onEvent(FlowableEvent event) {
if (event instanceof FlowableEntityEventImpl) {
FlowableEntityEventImpl entityEvent = (FlowableEntityEventImpl) event;
Object entity = entityEvent.getEntity();
if (entity instanceof ProcessInstance) {
ProcessInstance processInstance = (ProcessInstance) entity;
if (event.getType().equals(org.flowable.engine.delegate.event.FlowableEngineEventType.PROCESS_STARTED)) {
notifyCaseStarted(processInstance);
} else if (event.getType().equals(org.flowable.engine.delegate.event.FlowableEngineEventType.PROCESS_COMPLETED)) {
notifyCaseEnded(processInstance);
}
}
}
}
private void notifyCaseStarted(ProcessInstance processInstance) {
// 发送启动通知到外部系统
System.out.println("Case started: " + processInstance.getId());
// 这里可以替换为实际的通知发送逻辑
}
private void notifyCaseEnded(ProcessInstance processInstance) {
// 发送完成通知到外部系统
System.out.println("Case ended: " + processInstance.getId());
// 这里可以替换为实际的通知发送逻辑
}
// 省略isFailOnException和onException方法,因为它们在这个示例中不是必需的
}
2. 注册事件监听器
在Flowable配置中注册这个监听器,确保它能够接收到Flowable引擎发出的事件。这可以通过编程方式在Java配置中完成,也可以通过Flowable的配置文件(如果有的话)来完成。
// 假设这是你的Flowable配置类的一部分
@Autowired
private RuntimeService runtimeService;
@PostConstruct
public void registerListeners() {
CaseNotificationListener listener = new CaseNotificationListener();
runtimeService.addEventListener(listener, org.flowable.engine.delegate.event.FlowableEngineEventType.PROCESS_STARTED, org.flowable.engine.delegate.event.FlowableEngineEventType.PROCESS_COMPLETED);
}
注意:上面的@PostConstruct
注解用于确保在Spring容器完全初始化之后注册监听器。但是,如果你使用的是Flowable的Spring Boot Starter,并且你的监听器是一个Bean,那么你可能不需要手动注册监听器,因为Spring Boot的自动配置可能会为你处理这个问题(取决于你的Flowable版本和配置)。
注意事项
- 确保你的Flowable版本与上述代码示例兼容。
- 如果你的应用是基于Spring Boot的,并且你正在使用Flowable的Spring Boot Starter,那么你可能需要稍微调整配置方式以符合Spring Boot的自动配置特性。
- 在生产环境中,你可能需要将通知发送逻辑替换为与你的外部系统或消息队列集成的实际代码。
流程多实例和子流程事件
在Flowable工作流引擎中,实际上并没有直接名为STAGE_STARTED
和STAGE_ENDED
的标准事件。不过,这些概念可以映射到BPMN 2.0规范中的Multi-Instance
(多实例)活动或子流程(Subprocess)的开始和结束。在BPMN中,并没有直接定义“阶段”(Stage)作为一个元素,但我们可以使用多实例循环或子流程来模拟多个阶段的执行。
STAGE_STARTED和STAGE_ENDED
- 多实例活动(Multi-Instance Activity): 当一个活动(如用户任务、服务任务等)被配置为多实例时,它会对某个集合中的每个元素执行一次。每次迭代开始时,可以视为一个“阶段”的开始;当迭代完成时,可以视为该“阶段”的结束。
- 子流程(Subprocess): 子流程可以被视为一个更大的流程中的一个独立阶段。子流程的开始和结束可以分别视为一个阶段的开始和结束。
高级应用示例
假设我们有一个业务流程,其中包含多个阶段,每个阶段都通过子流程来模拟。我们将实现一个事件监听器,该监听器在子流程开始和结束时执行特定的逻辑。
1. 定义子流程
在BPMN XML或Flowable Modeler中定义包含多个子流程的流程。每个子流程代表一个阶段。
2. 创建事件监听器
我们可以监听ACTIVITY_STARTED
和ACTIVITY_COMPLETED
事件来分别模拟STAGE_STARTED
和STAGE_ENDED
。
import org.flowable.engine.delegate.event.FlowableEvent;
import org.flowable.engine.delegate.event.FlowableEventListener;
import org.flowable.engine.delegate.event.impl.FlowableActivityEventImpl;
public class StageEventListener implements FlowableEventListener {
@Override
public void onEvent(FlowableEvent event) {
if (event instanceof FlowableActivityEventImpl) {
FlowableActivityEventImpl activityEvent = (FlowableActivityEventImpl) event;
if (activityEvent.getActivityType().equals("subProcess")) { // 假设我们通过活动类型来识别子流程
String activityId = activityEvent.getActivityId();
String processInstanceId = activityEvent.getProcessInstanceId();
if (event.getType().equals(org.flowable.engine.delegate.event.FlowableEngineEventType.ACTIVITY_STARTED)) {
notifyStageStarted(activityId, processInstanceId);
} else if (event.getType().equals(org.flowable.engine.delegate.event.FlowableEngineEventType.ACTIVITY_COMPLETED)) {
notifyStageEnded(activityId, processInstanceId);
}
}
}
}
private void notifyStageStarted(String activityId, String processInstanceId) {
// 发送阶段开始通知
System.out.println("Stage started: " + activityId + " in process " + processInstanceId);
// 这里可以替换为实际的通知发送逻辑
}
private void notifyStageEnded(String activityId, String processInstanceId) {
// 发送阶段结束通知
System.out.println("Stage ended: " + activityId + " in process " + processInstanceId);
// 这里可以替换为实际的通知发送逻辑
}
// 省略isFailOnException和onException方法
}
3. 注册事件监听器
与之前的示例类似,你需要在Flowable配置中注册这个监听器,以便它能够接收到引擎发出的事件。
@Autowired
private RuntimeService runtimeService;
@PostConstruct
public void registerListeners() {
StageEventListener listener = new StageEventListener();
runtimeService.addEventListener(listener,
org.flowable.engine.delegate.event.FlowableEngineEventType.ACTIVITY_STARTED,
org.flowable.engine.delegate.event.FlowableEngineEventType.ACTIVITY_COMPLETED);
}
注意事项
- 确保你的Flowable版本与上述代码示例兼容。
- 在实际应用中,你可能需要根据活动的其他属性(如名称、类型等)来更精确地识别哪些活动代表你的“阶段”。
- 如果你使用的是Flowable的Spring Boot Starter,并且你的监听器是一个Bean,那么Spring Boot的自动配置可能会为你处理监听器的注册。但是,最好还是明确地在你的配置中注册监听器,以确保它按预期工作。
- 在生产环境中,你应该将通知发送逻辑替换为与你的外部系统或消息队列集成的实际代码。
流程多租户事件
在Flowable工作流引擎中,CHANGE_TENANT_ID
并不是一个标准的事件类型,因为BPMN 2.0 规范或Flowable API本身并不直接定义这样的事件。然而,Flowable 支持多租户(Multi-Tenancy),允许在同一个数据库实例中运行多个独立的流程实例,每个实例都属于不同的租户。
多租户事件
CHANGE_TENANT_ID
在Flowable中实现多租户时,每个租户通常会有一个唯一的标识符(即租户ID),用于在数据库层面隔离不同租户的数据。流程实例、任务、变量等都与特定的租户ID相关联。因此,当提到CHANGE_TENANT_ID
时,我们实际上是在谈论一个概念性的操作,即将某个流程实例、任务或一组数据从一个租户迁移到另一个租户。
高级应用示例
这种迁移通常不是通过简单地更改一个事件来完成的,而是需要一系列复杂的操作,流程包括但不限于:
- 数据验证:验证要迁移的数据是否属于当前租户,以及目标租户是否存在且准备好接收这些数据。
- 数据更新:更新数据库中与流程实例、任务、变量等相关的记录,将它们与新的租户ID相关联。这通常涉及多个表,因为Flowable使用多个表来存储流程执行、任务、变量等信息。
- 权限和安全性:确保迁移后的数据仍然受到适当的权限和安全策略的保护。
- 流程执行:如果流程实例在迁移后仍然需要继续执行,那么需要确保它能够在新租户的环境下正确运行。
- 日志和审计:记录迁移操作的详细信息,以便进行后续的日志分析、审计和故障排除。
业务需求示例
假设你有一个业务需求,需要将一个租户下的某些流程实例迁移到另一个租户。以下是一个高级应用示例的概述:
- 定义迁移策略:确定哪些流程实例需要迁移,以及迁移的具体规则(如基于流程定义ID、流程实例ID、租户ID范围等)。
- 开发迁移工具:编写一个自定义工具或脚本来执行迁移操作。这个工具将负责查询要迁移的数据、更新数据库中的记录、处理任何潜在的依赖关系等。
- 测试迁移:在开发环境中测试迁移工具,确保它能够正确地迁移数据并保持数据的完整性和一致性。
- 执行迁移:在测试成功后,将迁移工具部署到生产环境中,并执行实际的迁移操作。
- 验证迁移结果:迁移完成后,验证迁移结果是否符合预期。这包括检查流程实例、任务、变量等数据是否正确迁移到了新的租户,以及流程实例是否能够在新的租户下正确执行。
- 更新文档和流程:更新相关的文档和流程,以反映租户ID的变化和迁移操作的执行
示例 1: 流程迁移
假设你有一个流程实例正在一个租户下运行,但由于业务需要,你需要将这个流程实例迁移到另一个租户下。这可以通过以下步骤实现:
- 暂停当前流程实例:首先,你需要暂停正在运行的流程实例,以防止在迁移过程中发生任何状态变化。
- 更新租户ID:然后,你可以通过编程方式更新数据库中的相关记录,将流程实例的租户ID更改为新的租户ID。这通常涉及到直接操作Flowable的数据库表(如
ACT_RU_EXECUTION
),但这不是推荐的做法,因为它绕过了Flowable的API和事务管理。更好的方法是使用Flowable提供的服务API(如果可能的话)或创建一个自定义的服务来安全地更新租户ID。 - 恢复流程实例:最后,你需要恢复流程实例,以便它可以在新的租户下继续执行。
示例 2: 租户感知的流程设计
在设计流程时,你可以考虑将租户ID作为流程变量或任务分配的一部分。这样,流程中的每个任务或决策都可以根据当前的租户ID来定制其行为。
详细代码实现
由于CHANGE_TENANT_ID
不是一个内置事件,以下是一个简化的代码示例,展示了如何在Flowable中动态地更新流程实例的租户信息(假设我们通过某种方式能够安全地更新数据库)。
注意:这个示例是概念性的,并不涉及直接操作数据库,因为Flowable没有提供直接的API来更改流程实例的租户ID。
// 假设你有一个方法来更新流程实例的租户ID(这通常不是一个内置方法)
public void updateTenantId(String processInstanceId, String newTenantId) {
// 警告:以下代码是伪代码,用于说明目的
// 在实际应用中,你需要实现自定义逻辑来安全地更新租户ID
// 1. 查找流程实例
ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager().findById(processInstanceId);
// 2. 验证执行实例是否存在且属于当前租户
// ...(这里省略了验证逻辑)
// 3. 更新租户ID(注意:这通常不是直接设置的,而是可能需要通过其他方式实现)
// execution.setTenantId(newTenantId); // 这不是Flowable API的一部分
// 4. 实际上,你可能需要更新与流程实例相关的其他表(如ACT_RU_TASK, ACT_RU_IDENTITYLINK等)
// ...(这里省略了更新其他表的逻辑)
// 5. 提交事务(如果之前的操作是在事务中进行的)
// ...(这里省略了事务管理逻辑)
// 注意:上面的代码是伪代码,用于说明目的。在Flowable中,没有直接的方法来更改流程实例的租户ID。
// 你可能需要通过其他方式(如自定义服务、数据库脚本等)来实现这一功能。
}
// 调用方法(假设)
updateTenantId("someProcessInstanceId", "newTenantId");
注意事项:
- 直接操作数据库表来更改Flowable的流程实例数据是危险的,因为它可能会破坏数据完整性和一致性。
- 如果你的应用场景确实需要更改流程实例的租户ID,请考虑使用Flowable的扩展点(如自定义服务、监听器等)来安全地实现这一功能。
- 在多租户环境中,确保你的流程设计能够处理租户隔离和租户间的数据共享需求。