0%

Flowable汇总

flowable涉及到的表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
ACT_GE_BYTEARRAY	通用的流程定义和流程资源
ACT_GE_PROPERTY 系统相关属性
# 流程历史记录
ACT_HI_ACTINST 历史的流程实例
ACT_HI_ATTACHMENT 历史的流程附件
ACT_HI_COMMENT 历史的说明性信息
ACT_HI_DETAIL 历史的流程运行中的细节信息
ACT_HI_IDENTITYLINK 历史的流程运行过程中用户关系
ACT_HI_PROCINST 历史的流程实例
ACT_HI_TASKINST 历史的任务实例
ACT_HI_VARINST 历史的流程运行中的变量信息
# 用户用户组表
ACT_ID_BYTEARRAY 二进制数据表
ACT_ID_GROUP 用户组信息表
ACT_ID_INFO 用户信息详情表
ACT_ID_MEMBERSHIP 人与组关系表
ACT_ID_PRIV 权限表
ACT_ID_PRIV_MAPPING 用户或组权限关系表
ACT_ID_PROPERTY 属性表
ACT_ID_TOKEN 系统登录日志表
ACT_ID_USER 用户表
# 流程定义表
ACT_RE_DEPLOYMENT 部署单元信息
ACT_RE_MODEL 模型信息
ACT_RE_PROCDEF 已部署的流程定义
# 运行实例表
ACT_RU_DEADLETTER_JOB 正在运行的任务表
ACT_RU_EVENT_SUBSCR 运行时事件
ACT_RU_EXECUTION 运行时流程执行实例
ACT_RU_HISTORY_JOB 历史作业表
ACT_RU_IDENTITYLINK 运行时用户关系信息
ACT_RU_JOB 运行时作业表
ACT_RU_SUSPENDED_JOB 暂停作业表
ACT_RU_TASK 运行时任务表
ACT_RU_TIMER_JOB 定时作业表
ACT_RU_VARIABLE 运行时变量表
# 其他表
ACT_EVT_LOG 事件日志表
ACT_PROCDEF_INFO 流程定义信息

整合启动flowable-modeler

官网下载的zip包中将wars里面的flowable-admin.war, flowable-idm.war, flowable-modeler.war and flowable-task.war放到tomcat的webapps目录,解压出来后修改每个war里面对应的properties里面的数据源,例如:

1
2
3
➜  classes pwd
/Users/zhanshifeng/Documents/ccssoftDocument/flowable/apache-tomcat-7.0.99/webapps/flowable-idm/WEB-INF/classes
➜ classes vi flowable-default.properties

然后启动tomcat访问http://localhost:8080/flowable-modeler

Events(事件)

Events are used to model something that happens during the lifetime of a process. Events are always visualized as a circle. In BPMN 2.0, there exist two main event categories: catching and throwing events.

事件的类别主要有:捕捉事件和投掷事件。

Timer Event Definitions(定时器事件定义)

Timer events are events that are triggered by a defined timer. They can be used as start event, intermediate event or boundary event.

定时器事件由某个被预定义的定时器所触发,通常被用作于开始事件、中间事件或边界事件,定时器事件中所以和事件相关的定义或变量值,都必须遵循ISO 8601标准。

  • timeDate 具体的时间点,当时间点到达,将触发事件。
  • timeDuration 每隔一个自定义的时间周期,将触发事件。
  • timeCycle 每隔一个自定义的时间周期,将触发事件,触发次数可以差异化,此外,它还具有一个EndDate属性,这个属性代表,当endDate的时间已到达,事件将不被触发,EndDate属性有两种写法,如下:
    1
    2
    3
    <timerEventDefinition>
    <timeCycle flowable:endDate="2015-02-25T16:42:11+00:00">R3/PT10H</timeCycle>
    </timerEventDefinition>
    1
    2
    3
    <timerEventDefinition>
    <timeCycle>R3/PT10H/${EndDate}</timeCycle>
    </timerEventDefinition>
    两种写法都存在同一个定时器事件的时候,Flowable默认采用第一种。

Signal Event Definitions(信号事件定义)

运行时通过代码抛出信号事件:

1
2
RuntimeService.signalEventReceived(String signalName);
RuntimeService.signalEventReceived(String signalName, String executionId);

Querying for Signal Event subscriptions(信号事件订阅查询)

查询所有订阅的特定信号事件:

1
2
3
List<Execution> executions = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("alert")
.list();

Signal event scope(信号事件的作用域)

By default, signals are broadcast process engine wide. This means that you can throw a signal event in a process instance, and other process instances with different process definitions can react on the occurrence of this event.
默认,信号事件的作用域是整个广播流程引擎的范围,如果要将作用域限制在某个特定的流程实例以内i,就需要将信号事件绑定在特定的流程定义上。

1
<signal id="alertSignal" name="alert" flowable:scope="processInstance"/>

scope属性值默认是”global”,全局。

Message Event Definitions(消息事件定义)

消息事件的定义demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="Examples"
xmlns:tns="Examples">

<message id="newInvoice" name="newInvoiceMessage" />
<message id="payment" name="paymentMessage" />

<process id="invoiceProcess">

<startEvent id="messageStart" >
<messageEventDefinition messageRef="newInvoice" />
</startEvent>
...
<intermediateCatchEvent id="paymentEvt" >
<messageEventDefinition messageRef="payment" />
</intermediateCatchEvent>
...
</process>

</definitions>

As an embeddable process engine, Flowable is not concerned with actually receiving a message. This would be environment dependent and entail platform-specific activities, such as connecting to a JMS (Java Messaging Service) Queue/Topic or processing a Webservice or REST request. The reception of messages is therefore something you have to implement as part of the application or infrastructure into which the process engine is embedded.(大概意思是flowable没有局限消息接收的具体实现,这部分由开发者自定义,可以是JMS、消息队列、WebService或者是REST风格的请求)

通过消息来触发启动流程实例可以有如下二个API可供选择:

1
2
3
4
ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey,
Map<String, Object> processVariables);

If the message needs to be received by an existing process instance, you first have to correlate the message to a specific process instance (see next section) and then trigger the continuation of the waiting execution. The runtime service offers the following methods for triggering an execution based on a message event subscription:(两个方法关联消息去触发继续某个正在等待状态的流程)

1
2
void messageEventReceived(String messageName, String executionId);
void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);

使用ProcessDefinitionQuery来绑定消息订阅查询拿到流程定义ProcessDefinition:

1
2
3
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.messageEventSubscription("newCallCenterBooking")
.singleResult();

或者使用ExecutionQuery来绑定消息订阅查询特定的执行对象Execution。

Start Events(开始事件)

概念上来说,开始事件总是在等待着捕捉一个触发的发生.
开始事件的定义demo:
initiator: 指向一个认证的用户id,应该是被纳入IDM范围内的一个用户对象的id。

1
<startEvent id="request" flowable:initiator="initiator" />

Timer Start Event(定时器开始事件)

XML定义的demo:

1
2
3
4
5
<startEvent id="theStart">
<timerEventDefinition>
<timeCycle>R4/2011-03-11T12:13/PT5M</timeCycle>
</timerEventDefinition>
</startEvent>

Message Start Event(消息开始事件)

流程定义引用到消息开始事件的时候:
The name of the message start event must be unique across a given process definition. A process definition must not have multiple message start events with the same name. Flowable throws an exception upon deployment of a process definition containing two or more message start events referencing the same message, or if two or more message start events reference messages with the same message name.(消息开始事件在流程定义中必须是唯一的,一个流程定义如果引用多个名字相同的消息开始事件的话,会抛出异常,或者多个消息开始事件被定义成相同的name也会抛出异常;如果流程部署了一个新的版本,那么老旧的版本中的消息订阅将会被移除)

如上文所讲到的,消息事件通过这些API调用来触发:

1
2
3
4
ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey,
Map<String, Object< processVariables);
  • 多个消息开始事件的流程通过runtimeService.startProcessInstanceByMessage(…​)启动
  • 拥有一个空的开始事件可以通过实例id启动流程实例
  • 没有空的开始事件的话通过实例id启动流程会抛异常

xml定义demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<definitions id="definitions"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="Examples"
xmlns:tns="Examples">

<message id="newInvoice" name="newInvoiceMessage" />

<process id="invoiceProcess">

<startEvent id="messageStart" >
<messageEventDefinition messageRef="tns:newInvoice" />
</startEvent>
...
</process>

</definitions>

Signal Start Event(信号开始事件)

xml定义的配置demo:

1
2
3
4
5
6
7
8
9
10
11
<signal id="theSignal" name="The Signal" />

<process id="processWithSignalStart1">
<startEvent id="theStart">
<signalEventDefinition id="theSignalEventDefinition" signalRef="theSignal" />
</startEvent>
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />
<userTask id="theTask" name="Task in process A" />
<sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>

可以通过runtimeService.signalEventReceivedXXX触发。

Error Start Even(错误开始事件)

An error start event can be used to trigger an Event Sub-Process. An error start event cannot be used for starting a process instance.(错误开始事件只能用来发出子流程,不能触发整个的流程实例??)

End Events(结束事件)

None End Event(空结束事件)

xml定义demo:

1
<endEvent id="end" name="my end event" />

Error End Event(错误结束事件)

xml定义demo:

1
2
3
<endEvent id="myErrorEndEvent">
<errorEventDefinition errorRef="myError" />
</endEvent>

具体的错误能够被定义在流程之外,如:

1
2
3
4
<error id="myError" errorCode="123" />
...
<process id="myProcess">
...

errorCode会被用来匹配一个等待被捕捉的边界错误事件,如果匹配不到,那么errorCode会被等同于id来使用,比如下面的二个代码片段作用一样:

1
2
3
4
5
6
7
8
<error id="myError" errorCode="error123" />
...
<process id="myProcess">
...
<endEvent id="myErrorEndEvent">
<errorEventDefinition errorRef="myError" />
</endEvent>
...
1
2
3
<endEvent id="myErrorEndEvent">
<errorEventDefinition errorRef="error123" />
</endEvent>

Terminate End Event(终止结束事件)

xml定义demo:

1
2
3
<endEvent id="myEndEvent >
<terminateEventDefinition flowable:terminateAll="true"></terminateEventDefinition>
</endEvent>

如果terminateAll为true,会总之所有整个流程以及相关子流程。

Cancel End Event(取消结束事件)

xm定义demo:

1
2
3
<endEvent id="myCancelEndEvent">
<cancelEventDefinition />
</endEvent>

Boundary Events(边界事件)

边界事件的定义规则如下:

  • 在流程范围内是唯一的
  • 通过attachedToRef属性附加到一个引用的Activity,但是边界事件和它附着的活动是同一等级的,不是上下级关系??
    xml定义demo:
    1
    2
    3
    <boundaryEvent id="myBoundaryEvent" attachedToRef="theActivity">
    <XXXEventDefinition/>
    </boundaryEvent>

Timer Boundary Event(定时器边界事件)

xml定义demo:

1
2
3
4
5
<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport">
<timerEventDefinition>
<timeDuration>PT4H</timeDuration>
</timerEventDefinition>
</boundaryEvent>

有个关键的不同点是:Non-interrupting 和 Interrupting,前者是不会打断流程原来的活动,后者反之,边界事件默认是会打断的,可以通过cancelActivity属性自定义

1
<boundaryEvent id="escalationTimer" cancelActivity="false" attachedToRef="firstLineSupport"/>

Note: boundary timer events are only fired when the async executor is enabled (asyncExecutorActivate needs to be set to true in the flowable.cfg.xml, since the async executor is disabled by default).
注意要开启异步执行器,flowable默认是关闭该配置的。
官方给出的demo(通过定时器边界事件来对Task额外的邮件通知做处理,同时不影响原来Task的继续执行):

Known issue with boundary events(边界事件已知问题)

无论是那种类型的边界事件,都不允许直接并发触发多个外部的序列流程,必须通过并行网关来处理:

Error Boundary Event(错误边界事件)

xml定义demo:

1
2
3
4
5
6
7
8
<boundaryEvent id="catchError" attachedToRef="mySubProcess">
<errorEventDefinition errorRef="myError"/>
</boundaryEvent>

<error id="myError" errorCode="123" />
...
<process id="myProcess">
...
  • 如果errorRef被省略,那么边界错误事件将捕获任何错误事件,如果errorRef指向的error存在,那么将只捕捉对应的error,如果error不存在,那么会将errorRef的值视为对应的error,就像错误结束事件一样。
    官方给出的demo():

    还有官方根据上图demo做的测试类:BoundaryErrorEventTest.java

Signal Boundary Event(信号边界事件)

信号边界事件是不可消耗的,意思是,如果一个信号事件被抛出,那么捕捉这个信号事件的所有流程实例的活动都会被触发,因为信号事件的作用域是全局的,它能够在任何地方被抛出,在任何地方被捕捉。
xml定义demo:

1
2
3
<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
<signalEventDefinition signalRef="alertSignal"/>
</boundaryEvent>

Message Boundary Event(消息边界事件)

xml定义demo:

1
2
3
<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
<messageEventDefinition messageRef="newCustomerMessage"/>
</boundaryEvent>

Cancel Boundary Event(取消边界事件)

compensation boundary event(补偿边界事件)

补偿边界事件被定义做一个典型的边界事件,xml定义demo:

1
2
3
4
5
6
7
8
<boundaryEvent id="compensateBookHotelEvt" attachedToRef="bookHotel" >
<compensateEventDefinition />
</boundaryEvent>

<association associationDirection="One" id="a1"
sourceRef="compensateBookHotelEvt" targetRef="undoBookHotel" />

<serviceTask id="undoBookHotel" isForCompensation="true" flowable:class="..." /
  • When compensation is triggered, the compensation handler associated with the compensation boundary event is invoked the same number of times the activity it is attached to completed successfully.(当补偿被触发,补偿边界事件绑定的补偿处理器被调用的次数和事件依附在流程活动的次数是一样的)
  • If a compensation boundary event is attached to an activity with multiple instance characteristics, a compensation event subscription is created for each instance.(如果补偿边界事件被绑定在多个不同的流程实例,那么每个流程实例都将创建一个事件订阅)
  • If a compensation boundary event is attached to an activity that is contained inside a loop, a compensation event subscription is created each time the activity is executed.(如果事件的绑定逻辑在内部的循环里,那么事件订阅的创建也将跟随着每个循环都创建一次)
  • If the process instance ends, the subscriptions to compensation events are canceled.(流程实例结束,补偿事件的订阅也将取消)

Intermediate Catching Events(中间捕捉事件)

所有中间捕捉事件的定义方式,同个流程范围内必须唯一:

1
2
3
<intermediateCatchEvent id="myIntermediateCatchEvent" >
<XXXEventDefinition/>
</intermediateCatchEvent>

Timer Intermediate Catching Event(定时器中间捕捉事件)

Signal Intermediate Catching Event(信号中间捕捉事件)

Message Intermediate Catching Event(消息中间捕捉事件)

Problem Solution

upgrading flowable engine schema from 6.4.1.1 to 6.5.0.1

1
performing upgrade on engine with resource org/flowable/db/upgrade/flowable.mysql.upgradestep.6411.to.6412.engine.sql

这个报错是因为默认配置的dbSchemaUpgrade是true,这个会在流程初始化的时候去对Flowable版本和数据库存的Flowable版本做比对并做一些初始化的处理,如果要快速启动忽略版本比对问题的话改成false,如果还有问题干脆改成”none”。