启动事件

本文中内容和案例节选自贺波老师的《深入Activiti流程引擎:核心原理与高阶实战》一书。这本书中的内容更为全面、详尽,对系统学习和深入掌握Activiti/Flowable的用法非常有帮助,推荐给大家。

QQ交流群1:633168411 已满
QQ交流群2: 582010059

参照本书录制的讲解视频地址

博客地址

开始事件表示流程的开始,定义流程如何启动,如流程在接收事件时启动,在指定时间启动,在接收信号,消息启动等等

在Flowable中,开始事件可以划分为以下9种类型:

  • 空开始事件(none start event)
  • 定时器开始事件(timer start event)
  • 信号开始事件(signal start event)
  • 消息开始事件(message start event)
  • 错误开始事件(error start event)
  • 条件开始事件(conditional start event)
  • 参数监听开始事件(variableListener start event)
  • 升级开始事件 (escalation start event)
  • 注册表开始事件(registry start event)

在图标表示上,不同类型的开始事件以内部的白色小图标区分。在XML表示中,这些类型是通过声明不同的子元素来区分的。所以开始事件都属于捕获事件,从概念上讲,这些时间都会一直等待,需要由具体的动作或事件触发。

空启动事件

定义

空开始事件意味着没有指定启动流程实例的触发条件。它是最常见的一种开始事件,一般需要人工启动,或通过API触发

图形标记

none-start-event.png

XML内容

<startEvent id="aba1958401251475ca53b3f5d152fde3b" name="空开始"/>

使用示例

空开始事件无需指定触发条件,可以由API触发 runtimeService.startProcessInstanceBy开头的各种方法发起流程实例。

空启动事件的自定义扩展

  • formKey: 引用表单定义,用户需要在启动新流程实例时填写该表单。
    <startEvent id="request" flowable:formKey="request" />
    

演示demo

空开始事件

定时器开始事件

定义

定时器启动事件(timer start event)用于在指定的时间启动一个流程,或者在一定周期内循环启动多次流程,如在2023年8月1日10时整发起年度目标审核流程, 或每月1日0时开始启动财务结算处理流程。当满足设定的时间条件时,定时器开始事件被触发,从而启动流程。

注意 使用定时器开始事件需要开启flowable的作业执行器

configuration.setAsyncExecutorActivate(true);

图形标记

定时开始事件显示为了一个圆圈,内部是一个小时钟

time-start-event.png

XML内容

定时开始事件的 XML 内容是普通开始事件的声明,包含一个定时器事件子元素。

<startEvent id="timerStart" >
    <timerEventDefinition>
        <timeDate>2023-07-14T12:12:14</timeDate>
    </timerEventDefinition>
</startEvent>

定义定时器的标签是<timerEventDefinition>...</timerEventDefinition>,它必须具有以下一个元 素:timeDate,timeDuration,timeCycle。

1. timeDate:设置在指定时间触发。

    <startEvent id="timerStart">
        <timerEventDefinition>
           <timeDate>2023-07-14T12:12:14</timeDate>
        </timerEventDefinition>
    </startEvent>

timeDate 是使用 ISO 8601 格式指定一个确定的时间来触发事件,以上配置表示流程会在 2023-07-14T12:12:14 启动起来。

注意:ISO8601 时间格式,如果要加时间需要前面加 T。

使用示例

2、timeDuration:置指定一个时间段之后执行。

     <startEvent id="timerStart">
        <timerEventDefinition>
            <timeDuration>PT1S</timeDuration>
        </timerEventDefinition>
    </startEvent>

timeDuration 是指定定时器之前要等待多长时间。S 表示秒,M 表示分,D 表示天;P 表示时 间段,T 表示精确到时间的时间段。

注意:时间格式依然为 ISO 8601 格式,一年两个月三天四小时五分六秒内,可以写成 P1Y2M3DT4H5M6S,P 是开始标记,T 是时间和日期分割标记,没有日期只有时间 T 是不能省去 的,比如 1 小时执行一次应该写成 PT1H。

使用示例

3、通过 timeCycle 设置指定定时器的运行周期

     <startEvent id="timerStart">
        <timerEventDefinition>
            <timeCycle>R2/${EndDate}/PT1M</timeCycle>
        </timerEventDefinition>
    </startEvent>

timeCycle 指定重复执行的间隔,可以用来定期启动流程实例。timeCycle 的设置目前有两种方 式:ISO 8601 和 Cron 表达式。R 表示需要执行的次数,R2/PT1M 表示执行两次,每次间隔 1 分钟。 其中 endDate 是可选的配置,定时器将会在指定的时间停止工作。

注意:使用定时器开始事件需要启动 JobExecutor

使用示例

注意

1、子流程中不能使用定时器启动事件。定时器是从流程部署开始计时,不需要去启动流程。

2、当定时启动任务已经超过运行时间,再次去部署流程时,就会把它当成一个普通的空启动事件来处理。部署新的流程后,旧版本的流程中的定时事件就会被移除。

演示demo

定时器开始事件

信号开始事件

定义

信号开始事件在接收到特定的信号后被触发,启动一个流程实例。如果多个流程含有相同信号名称的信号开始事件,那么它们都会被启动。

图形标记

消息开始事件是一个圆圈,中间是一个消息事件图标。图标是白色未填充的,来表示捕获(接收)行为。

signal-start-event.png

XML内容

信号开始事件的 XML 内容是在普通开始事件申请中包含一个 signalEventDefinition 子元素

 <!-- 信号定义 -->
 <signal id="theSignal" name="The Signal" />
 <process id="signalStartProcess">
     <startEvent id="signalStart" >
     <!-- 定义为开始信号事件 -->
     <signalEventDefinition signalRef="theSignal" />
     </startEvent>
 </process>

以上 xml 代码片段中加粗的部分分别定义了 signal、startEvent,信号 signal 的 id 属性值为theSignal,信号开始事件 startEvent 中的 signalEventDefinition 子元素通过设置 signalRef 为 theSignal 引用了该信号。

界面操作

定义信号

选择信号

使用示例

信号启动事件的触发方式通常有以下几种:

1、流程中的抛出信号事件(Signal Intermediate Throwing Event)、信号结束事件(Signal End Event)发出信号,所有拥有相同名字信号启动事件的流程定义都会被启动。

2、通过 API(runtimeService.signalEventReceivedXXX 方法)抛出一个信号,所有拥有相同名字 信号启动事件的流程定义都会被启动。需要为 API 传递的 signalName,是由 signal 元素的 name 属 性决定的名字。signal 元素被 signalEventDefinition 的 signalRef 属性所引用。

3、作为普通开始事件,启动流程。

注意:信号定义的作用域分流程实例有效和全局有效

<signal id="startSigon" name="开始信号" flowable:scope="processInstance" />

<signal id="startSigon" name="开始信号" flowable:scope="global" />

演示demo

信号开始事件

消息开始事件

定义

在 BPMN2.0 规范中,消息表示的是流程参与者的沟通信息对象,在一般流程中,流程的各个角色的沟通信息均有可能导致流程的开始。流程开始事件,可以理解为另外一种启动流程的方式或者途径,使用该开始事件,当达到“接收消息”的条件后启动流程。

图形标记

消息开始事件是一个圆圈,中间是一个消息事件图标,图标是白色未填充小信封,来表示捕获(接收)行为。

message-start-event.png

XML内容

<!-- 消息定义 -->
 <message id="theMessage" name="newMessageName" />
 <process id="messageStartEventProcess">
     <startEvent id="messageStart" >
     <!-- messageEventDefinition -->
        <messageEventDefinition messageRef="theMessage" />
     </startEvent>
 <!-- -->
 </process>

在以上xml代码片段中,首先定义了一个名称为theMessage的消息 ,消息值为newMessageName,然后在开始事件中使用 messageEventDefinition 元素引用该 message,从而构成了一个消息开始事件。

界面操作

定义消息

选择消息

使用示例

在发布包含一个或多个消息开始事件的流程定义时,需要考虑下面的条件:

1、流程的消息名称必须是唯一的,一个流程定义不得包含多个同名的启动消息。如果两个或以上消息开始事件应用了相同的事件,或两个或以上消息事件引用的消息名称相同,Flowable 会在发布流程定义时抛出异常。

2、消息开始事件的名称在所有已发布的流程定义中不能重复。如果一个或多个消息开始事件引用了相同名称的消息,而这个消息开始事件已经部署到不同的流程定义中,Flowable 就会在发布时抛出一个异常。

3、发布新版流程定义时,会取消上一版本的消息订阅。

4、只有顶级流程(toplevel process)才支持消息开始事件,内嵌子流程不支持消息事件。如果流程被调用环节(callActivity)启动,消息开始事件只支持以下两种情况:在消息开始事件以外,还有一个单独的空开始事件;流程只有一个消息开始事件,没有空开始事件。

通过消息开始事件启动流程实例有三种方法: ProcessInstance startProcessInstanceByMessage(String messageName);

ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object>processVariables);

ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object< processVariables);

其中,messageName 是 messageEventDefinition 的 messageRef 属性引用的 message 元素的 name属性。

注意:使用这些 API 有以下几个注意事项:

1、如果流程定义中有多个消息开始事件,那么 runtimeService.startProcessInstanceByMessage(...)会选择对应的开始事件。

2、如果流程定义中既有消息开始事件又有一个空开始事件,那么runtimeService.startProcessInstanceByKey(...)和 runtimeService.startProcessInstanceById(...)会使用空开始事件启动流程实例。

3、如果流程定义中有多个消息开始事件,而没有空开始事件,那么runtimeService.startProcessInstanceByKey(...)和 runtimeService.startProcessInstanceById(...)会抛出异常。

4、如果流程定义只有一个消息开始事件, runtimeService.startProcessInstanceByKey(...) 和runtimeService.startProcessInstanceById(...)会使用这个消息开始事件启动流程实例。

5、如果被启动的流程是一个调用子流程(callActivity)并且有多个开始事件,那么该流程定义中除了含有消息开始事件外,还需要有一个无指定开始是;或者该调用子流程中只有一个消息开始事件。

演示demo

消息开始事件

错误开始事件

定义

错误开始事件可以触发一个异常子流程,它总是在另外一个流程在异常结束的时候触发。BPMN2.0 规定了错误开始事件只能使用在事件子流程(Event Sub-Process)中,该该事件不能 使用在其它流程中,包括最高级流程(Top-Level Process)、嵌套子流程(Sub-Process)和调用子流程(Call Activity)。

注意,BPMN 错误与 Java 异常不是一回事,BPMN 错误事件是建模业务异常(business exceptions)的方式,二者没有直接关联。

图形图标

错误开始事件是一个圆圈,包含一个错误事件标记。标记是白色未填充的,来表示捕获(接收)行为。

error-start-event.png

XML内容

<error id="errorStart" errorCode="501" />
<process id="errorStartEventProcess">
    <startEvent id="errorStartEvent" >
        <errorEventDefinition errorRef="theError" />
    </startEvent>
</process>

在以上 xml 代码片段中,首先定义了一个 id 属性值为 theError 的错误,然后在开始事件中使用 errorEventDefinition 元素引用该 error,从而构成了一个错误开始事件。

注意:错误开始事件不能独立存在,必须是其他事件的子流程。

界面操作

错误定义

错误选择

使用示例

两种方式触发错误开始事件

1、错误结束事件抛出错误(注:错误结束事件也选择的是同一个错误定义)

2、自动执行主流程的服务任务抛出错误,接下来子流程的错误开始事件捕获到错误后执行。

@Slf4j
public class AutomaticReviewService implements JavaDelegate {
    @Override
    public void execute(DelegateExecution execution) {
        String healthCodeStatus = (String) execution.getVariable("healthCodeStatus");
        if (!"green".equals(healthCodeStatus)) {
            String errorCode = "500";
            log.error("健康码异常,抛出BPMN错误,errorCode为:{}", errorCode);
            throw new BpmnError(errorCode);
        }
    }
}

演示demo

错误开始事件

条件开始事件

定义

定义了一个事件,该事件在给定条件被求值为true时被触发,作为事件子流程的起始事件。

图形图标

条件开始事件是一个圆圈,包含一个条件事件标记。

conditional-start-event.png

XML内容

<bpmn:startEvent id="Event_1gjhevt">
    <bpmn:conditionalEventDefinition id="ConditionalEventDefinition_1j8ag66">
        <bpmn:condition xsi:type="bpmn:tFormalExpression">${name=='lwj'}</bpmn:condition>
    </bpmn:conditionalEventDefinition>
</bpmn:startEvent>

界面操作

conditional-start-event-01.png

参数监听开始事件

定义

定义了一个事件,该事件在指定参数发生变化而触发的,作为事件子流程的起始事件。

图形图标

条件开始事件是一个圆圈,包含一个五边形标记。

variableListener-start-event.png

variableChangeType类型有四种类型:all、create、update、createupdate 1、all:参数只要发生变化被触发 2、create:参数创建被触发 3、update:参数更新被触发 4、createupdate:参数创建或更新被触发

XML内容

<bpmn:startEvent id="Event_1gyqk9p" flowable:initiator="initiator">
    <bpmn:extensionElements>
        <flowable:variableListenerEventDefinition variableName="name" variableChangeType="create" />
    </bpmn:extensionElements>
</bpmn:startEvent>

界面操作

variableListener-start-event-01.png

升级开始事件

敬请期待

注册开始事件

敬请期待