0%

Flowable-Overview

阅读更多

1 Overview

概念

  1. Process:文中称为流程执行流
    • instance:文中称为实例
  2. Event:文中称为事件
  3. Flow:文中称为连线
  4. Gateway:文中称为网关
  5. Task:文中称为任务
  6. Activity:流程中的一个实体都可以成为Activity,包括EventGatewayTask等等
  7. Variable:变量
  8. Expression:表达式,通常指UEL

2 Event

BPMN 2.0中,存在两种主要的event类型

  1. Catching:当process执行到此类event时,它会等待某个trigger来触发
  2. Throwing:当process执行到此类event时,一个trigger被触发

参考

2.1 Event Definitions

Event Definitions定义了event的具体语义(semantics),如果一个event不包含Event Definitions,那么这个事件不执行任何操作

2.1.1 Timer Event Definitions

Description

顾名思义,Timer events由一个事先定义好的timer来触发,可以用于start eventintermediate eventboundary event

我们可以定义多种不同的timer,主要包括如下三种(关于timer的详细语法请参考ISO 8601

  1. timeDate
  2. timeDuration
  3. timeCycle

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- timeDate -->
<timerEventDefinition>
<timeDate>2011-03-11T12:13:14</timeDate>
</timerEventDefinition>

<!-- timeDuration -->
<timerEventDefinition>
<timeDuration>P10D</timeDuration>
</timerEventDefinition>

<!-- timeCycle -->
<timerEventDefinition>
<timeCycle flowable:endDate="2015-02-25T16:42:11+00:00">R3/PT10H</timeCycle>
</timerEventDefinition>

<timerEventDefinition>
<timeCycle>R3/PT10H/${EndDate}</timeCycle>
</timerEventDefinition>

<timerEventDefinition>
<timeCycle>0 0/5 * * * ?</timeCycle>
</timerEventDefinition>

2.1.2 Error Event Definitions

Description

首先,声明一点:BPMN errorJava exception是完全不同的,不能拿来类比。BPMN error仅用于描述业务异常

XML representation

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

2.1.3 Signal Event Definitions

Description

Signal Event指向了一个signalsignal的作用域是全局的

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<definitions... >
<!-- declaration of the signal -->
<signal id="alertSignal" name="alert" />

<process id="catchSignal">
<intermediateThrowEvent id="throwSignalEvent" name="Alert">
<!-- signal event definition -->
<signalEventDefinition signalRef="alertSignal" />
</intermediateThrowEvent>
...
<intermediateCatchEvent id="catchSignalEvent" name="On Alert">
<!-- signal event definition -->
<signalEventDefinition signalRef="alertSignal" />
</intermediateCatchEvent>
...
</process>
</definitions>

<!-- 我们可以指定signal的作用域(默认是global) -->
<signal id="alertSignal" name="alert" flowable:scope="processInstance"/>

2.1.4 Message Event Definitions

Description

Message Event指向了一个message,一个message拥有一个name以及payload。与signal不同,一个message只能有一个receiver

XML representation

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>

2.2 Start Events

Description

顾名思义,start event就是一个process开始的节点,start event的类型定义着process的开始方式
start event永远是catching event,意思是说,start event一直处于wait状态,直到被触发(trigger)

XML representation

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

2.2.1 None Start Event

Description

从技术上来说,none start event意味着trigger未指定,因此这种process只能手动启动

XML representation

1
<startEvent id="start" name="my start event" />
1
ProcessInstance processInstance = runtimeService.startProcessInstanceByXXX();

2.2.2 Timer Start Event

Description

顾名思义,timer start event会在指定的时间启动process

XML representation

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

<startEvent id="theStart">
<timerEventDefinition>
<timeDate>2011-03-11T12:13:14</timeDate>
</timerEventDefinition>
</startEvent>

注意事项

  1. sub-process不允许含有timer start event
  2. timer start event在部署时就被scheduler(后台运行一个job,定时启动process)。因此不需要手动启动process(不需要而不是不能)
  3. 当一个新版本部署时,旧版本的timer(后台那个job)会被移除

2.2.3 Message Start Event

Description

message start event用于启动一个process,一个process definition允许存在多个message start event

  1. 在一个process definition内,message start event的名字必须唯一,否则flowable engine在部署时会抛出异常
  2. 不允许不同process definition包含具有相同名字的message start event,否则否则flowable engine在部署时会抛出异常
  3. 当部署新版本的process definition时,之前的message订阅关系将会被移除

XML representation

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>

注意事项

  1. message start event仅支持顶层process,即不支持sub-process
  2. 如果process definition包含多个message start event,那么runtimeService.startProcessInstanceByMessage(…​) 会选择适当的message来启动process
  3. 如果process definition包含多个message start event以及一个none start eventruntimeService.startProcessInstanceByKey(…​)以及runtimeService.startProcessInstanceById(…​) 会使用none start event来启动process
  4. 如果process definition包含多个message start event但不包含none start eventruntimeService.startProcessInstanceByKey(…​)以及runtimeService.startProcessInstanceById(…​) 会抛出异常
  5. 如果process definition包含一个message start event,那么runtimeService.startProcessInstanceByKey(…​)以及runtimeService.startProcessInstanceById(…​) 会使用message start event来启动process

2.2.4 Signal Start Event

Description

signal start event可用于使用命名信号启动process实例。可以使用intermediary signal throw event或通过API(runtimeService.signalEventReceivedXXX方法)从流程实例中触发信号。在这两种情况下,将启动具有相同名称的信号启动事件的所有流程定义

XML representation

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>

2.2.5 Error Start Event

Description

error start event可用于触发sub-processerror start event不能用于启动process实例。error start event总是在中断

XML representation

1
2
3
<startEvent id="messageStart" >
    <errorEventDefinition errorRef="someError" />
</startEvent>

2.3 End Events

end event表示processsub-process的结束。end event一定是throwing event。这意味着当process执行到达end event时,将抛出result

2.3.1 None End Event

Description

none end event表示执行动作未定义。因此,除了结束当前的执行的process外,引擎不会做任何额外的事情

XML representation

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

2.3.2 Error End Event

Description

process执行到达error end event时,当前执行路径结束并抛出error。匹配的intermediate eventboundary event可以捕获此错误。如果未找到匹配的边界错误事件,则将引发异常

XML representation

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

2.3.3 Terminate End Event

Description

到达terminate end event时,将终止当前process实例或sub-process。从概念上讲,当执行到达terminate end event时,将确定并结束第一范围(processsub-process)。请注意,在BPMN 2.0中,子流程可以是一个embedded sub-processcall activityevent sub-processtransaction sub-process。此规则通常适用:例如,当存在call activityembedded sub-process时,仅该实例结束,其他实例和流程实例不受影响

XML representation

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

2.3.4 Cancel End Event

Description

cancel end event只能与BPMNtransaction sub-process结合使用。当到达cancel end event时,抛出cancel event,必须由cancel boundary event捕获。cancel boundary event随后取消事务并触发补偿

XML representation

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

2.4 Boundary Events

boundary event捕获附加到activity的事件(boundary event一定是catching event)。这意味着当activity正在运行时,事件正在侦听某种类型的trigger。当事件被捕获时,activity被中断并且遵循事件的执行流

文档中说,boundary event不可以有多个output sequence,但实际上是可以的,自行验证一下

1
2
3
<boundaryEvent id="myBoundaryEvent" attachedToRef="theActivity">
<XXXEventDefinition/>
</boundaryEvent>

2.4.1 Timer Boundary Event

Description

timer boundary event充当秒表和闹钟。当执行到达附加timer boundary eventactivity时,启动计时器。当计时器触发时(例如,在指定的间隔之后),activity被中断并且遵循timer boundary event之外的执行流

XML representation

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

2.4.2 Error Boundary Event

Description

error boundary event捕获在定义它的activity范围内引发的error

XML representation

1
2
3
<boundaryEvent id="catchError" attachedToRef="mySubProcess">
<errorEventDefinition errorRef="myError"/>
</boundaryEvent>

2.4.3 Signal Boundary Event

Description

signal boundary event用于捕获指定的signal

XML representation

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

2.4.4 Message Boundary Event

Description

message boundary event用于捕获指定的message

XML representation

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

2.4.5 Cancel Boundary Event

Description

cancel boundary event触发时,它首先中断当前作用域中的所有activity。接下来,它开始补偿事务范围内的所有有效compensation boundary event。补偿是同步进行的,换句话说,boundary event会等待补偿完成后离开事务

XML representation

1
2
3
<boundaryEvent id="boundary" attachedToRef="transaction" >
<cancelEventDefinition />
</boundaryEvent>

2.4.6 Compensation Boundary Event

Description

compensation boundary event作为activity的补偿处理过程

XML representation

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="..." />

2.5 Intermediate Catching Events

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

2.5.1 Timer Intermediate Catching Event

Description

timer intermediate catching event充当秒表,当process到达timer intermediate catching event时,timer被触发,经过指定时间后,继续后续处理流程

XML representation

1
2
3
4
5
<intermediateCatchEvent id="timer">
<timerEventDefinition>
<timeDuration>PT5M</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>

2.5.2 Signal Intermediate Catching Event

Description

signal intermediate catching event用于捕获指定的signal

XML representation

1
2
3
<intermediateCatchEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" />
</intermediateCatchEvent>

2.5.3 Message Intermediate Catching Event

Description

message intermediate catching event用于捕获指定的message

XML representation

1
2
3
<intermediateCatchEvent id="message">
<messageEventDefinition signalRef="newCustomerMessage" />
</intermediateCatchEvent>

2.6 Intermediate Throwing Event

1
2
3
<intermediateThrowEvent id="myIntermediateThrowEvent" >
<XXXEventDefinition/>
</intermediateThrowEvent>

2.6.1 Intermediate Throwing None Event

Description

intermediate throwing none event通常用来表示process到达某种状态

XML representation

1
2
3
4
5
<intermediateThrowEvent id="noneEvent">
<extensionElements>
<flowable:executionListener class="org.flowable.engine.test.bpmn.event.IntermediateNoneEventTest$MyExecutionListener" event="start" />
</extensionElements>
</intermediateThrowEvent>

2.6.2 Signal Intermediate Throwing Event

Description

signal intermediate throwing event抛出一个signal

XML representation

1
2
3
4
5
6
7
8
<intermediateThrowEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" />
</intermediateThrowEvent>

<!-- async mode -->
<intermediateThrowEvent id="signal">
<signalEventDefinition signalRef="newCustomerSignal" flowable:async="true" />
</intermediateThrowEvent>

2.6.3 Compensation Intermediate Throwing Event

Description

compensation intermediate throwing event抛出compensation event来触发compensation

XML representation

1
2
3
4
5
6
7
<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition />
</intermediateThrowEvent>

<intermediateThrowEvent id="throwCompensation">
<compensateEventDefinition activityRef="bookHotel" />
</intermediateThrowEvent>

3 Sequence Flow

sequence flow用于表示两个process元素的连接关系(路由关系,带有方向)。process执行到某个节点时,所有通过sequence flow连接出去的路径都会被同时执行,也就是并发的两条/多条执行链路。这是BPMN 2.0的默认行为(相当于默认有一个parallel gateway

1
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />

参考

3.1 Conditional sequence flow

Description

顾名思义,conditional sequence flow允许附带一个条件。条件为真时,继续执行当前路径的后续流程,否则终止当前路径

XML representation

1
2
3
4
5
6
7
<!-- conditionExpression仅支持 UEL -->
<!-- 且表达式的值必须是bool值,否则会抛出异常 -->
<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${order.price > 100 && order.price < 250}]]>
</conditionExpression>
</sequenceFlow>

3.2 Default sequence flow

Description

default sequence flow当且仅当当前节点的其他sequence flow没有被触发时才会生效,起到一个默认路由的作用

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
<!-- The following XML snippet shows an example of an exclusive gateway that has as default sequence flow, flow 2. Only when conditionA and conditionB both evaluate to false, will it be chosen as the outgoing sequence flow for the gateway. -->
<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow2" />

<sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">
<conditionExpression xsi:type="tFormalExpression">${conditionA}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3">
<conditionExpression xsi:type="tFormalExpression">${conditionB}</conditionExpression>
</sequenceFlow>

4 Gateway

gateway用于控制process的执行流。抽象地来说,gateway能够使用或者消耗token

参考

4.1 Exclusive Gateway

Description

exclusive gateway又被称为XOR gateway,通常用于描述decision。当流程执行到exclusive gateway时,所有的sequence flow会按照定义的顺序进行条件判断(针对conditional sequence flowsequence flow也可以看成一个条件永远为真的conditional sequence flow)。第一个为真的conditional sequence flow将会被选中并继续执行后续流程,其余sequence flow被忽略。全都为假时,将会抛出异常

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1">
<conditionExpression xsi:type="tFormalExpression">${input == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2">
<conditionExpression xsi:type="tFormalExpression">${input == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3">
<conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression>
</sequenceFlow>

4.2 Parallel Gateway

Description

parallel gateway通常用于描述并发执行流,最直接最方便的引入并发特性的元素就是parallel gatewayparallel gateway可以起到fork的作用(从一条路径到多条路径),以及join的作用(从多条执行路径到一条执行路径),这取决于parallel gateway放置的位置
要注意的是,与parallel gateway相连的sequence flow若是conditional sequence flow,则条件的校验将会被直接忽略

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<parallelGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

4.3 Inclusive Gateway

Description

inclusive gateway可以看成是exclusive gateway以及parallel gateway的结合体。与exclusive gateway类似,inclusive gateway会执行conditional sequence flow上的条件;与parallel gateway类似,inclusive gateway同样允许fork以及join

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<inclusiveGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" >
<conditionExpression xsi:type="tFormalExpression">${paymentReceived == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="fork" targetRef="shipOrder" >
<conditionExpression xsi:type="tFormalExpression">${shipOrder == true}</conditionExpression>
</sequenceFlow>

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<inclusiveGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

5 Task

5.1 User Task

Description

user task用于描述人类需要完成的工作。当流程执行到此类任务时,将在分配给该任务的任何用户或组的任务列表中创建新任务

XML representation

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
<!-- normal -->
<userTask id="theTask" name="Important task" />

<!-- documentation -->
<userTask id="theTask" name="Schedule meeting" >
<documentation>
Schedule an engineering meeting for next week with the new hire.
</documentation>
</userTask>

<!-- due date -->
<userTask id="theTask" name="Important task" flowable:dueDate="${dateVariable}"/>

<!-- user assignment -->
<userTask id='theTask' name='important task' >
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>kermit</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>

<!-- candidate user assignment -->
<!-- If no specifics are given as to whether the given text string is a user or group, the engine defaults to group -->
<userTask id='theTask' name='important task' >
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(management)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>

<!-- more flexible way -->
<userTask id="theTask" name="my task" flowable:assignee="kermit" />
<userTask id="theTask" name="my task" flowable:candidateUsers="kermit, gonzo" />
<userTask id="theTask" name="my task" flowable:candidateGroups="management, accountancy" />
<userTask id="theTask" name="my task" flowable:candidateUsers="kermit, gonzo" flowable:candidateGroups="management, accountancy" />

参考

5.2 Script Task

Description

script task是一个自动的activity,当一个process执行到script task时,相关联的script就会被执行

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
</script>
</scriptTask>

<!-- variable store -->
<!-- default value of autoStoreVariables is false -->
<scriptTask id="script" scriptFormat="JavaScript" flowable:autoStoreVariables="false">
<script>
def scriptVar = "test123"
execution.setVariable("myVar", scriptVar)
</script>
</scriptTask>

<!-- script result store -->
<!-- In the following example, the result of the script execution (the value of the resolved expression '#{echo}') is set to the process variable named 'myVar' after the script completes. -->
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" flowable:resultVariable="myVar">
<script>#{echo}</script>
</scriptTask>

以下名称是保留字符,不可用于变量名

  1. out
  2. out:print
  3. lang:import
  4. context
  5. elcontext

参考

5.3 Java Service Task

Description

java service task用于触发一个Java方法

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- normal -->
<serviceTask id="javaService"
name="My Java Service Task"
flowable:class="org.flowable.MyJavaDelegate" />

<!-- delegate to bean -->
<!-- the delegateExpressionBean is a bean that implements the JavaDelegate interface, defined in, for example, the Spring container -->
<serviceTask id="serviceTask" flowable:delegateExpression="${delegateExpressionBean}" />

<!-- UEL(Unified Expression Language) method expression -->
<serviceTask id="javaService"
name="My Java Service Task"
flowable:expression="#{printer.printMessage()}" />

<!-- Field Injected -->
<serviceTask id="javaService"
name="Java service invocation"
flowable:class="org.flowable.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
<extensionElements>
<flowable:field name="text" stringValue="Hello World" />
</extensionElements>
</serviceTask>

Implementation

  1. 必须实现org.flowable.engine.delegate.JavaDelegateexecute方法
  2. 所有process的实例共享同一个JavaDelegate的实例,因此这个类的实现必须是线程安全的(最好无状态)
  3. 当第一次被使用时,才会创建JavaDelegate的实例

Field Injection

  1. 通常,会通过setter方法来为delegated class注入属性值(超级无敌神坑:若写的是private的字段,而没有提供public的set方法,有时候注入会失败)
  2. 字段类型必须是org.flowable.engine.delegate.Expression

Using a Flowable service from within a JavaDelegate

  1. RuntimeService runtimeService = Context.getProcessEngineConfiguration().getRuntimeService();

参考

5.4 Web Service Task

Description

web service task用于同步地触发一个外部的Web service

参考

5.5 Business Rule Task

Description

business rule task用于同步地执行一个或多个rule。Flowable使用Drools Rule Engine来执行具体的rule

参考

5.6 Email Task

Description

Flowable允许您使用向一个或多个收件人发送电子邮件的自动邮件服务任务来增强业务流程

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<serviceTask id="sendMail" flowable:type="mail">
<extensionElements>
<flowable:field name="from" stringValue="order-shipping@thecompany.com" />
<flowable:field name="to" expression="${recipient}" />
<flowable:field name="subject" expression="Your order ${orderId} has been shipped" />
<flowable:field name="html">
<flowable:expression>
<![CDATA[
<html>
<body>
Hello ${male ? 'Mr.' : 'Mrs.' } ${recipientName},<br/><br/>

As of ${now}, your order has been <b>processed and shipped</b>.<br/><br/>

Kind regards,<br/>

TheCompany.
</body>
</html>
]]>
</flowable:expression>
</flowable:field>
</extensionElements>
</serviceTask>

参考

5.7 Http Task

Description

http task允许发出HTTP请求,增强了Flowable的集成功能。请注意,http task不是BPMN 2.0规范的官方任务(因此没有专用图标)。因此,在Flowable中,http task被实现为专用服务任务

XML representation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<serviceTask id="httpGet" flowable:type="http">
<extensionElements>
<flowable:field name="requestMethod" stringValue="GET" />
<flowable:field name="requestUrl" stringValue="http://flowable.org" />
<flowable:field name="requestHeaders">
<flowable:expression>
<![CDATA[
Accept: text/html
Cache-Control: no-cache
]]>
</flowable:expression>
</flowable:field>
<flowable:field name="requestTimeout">
<flowable:expression>
<![CDATA[
${requestTimeout}
]]>
</flowable:expression>
</flowable:field>
<flowable:field name="resultVariablePrefix">
<flowable:string>task7</flowable:string>
</flowable:field>
</extensionElements>
</serviceTask>

参考

5.8 Mule Task

Description

mule task允许您向Mule发送消息,增强Flowable的集成功能。请注意,Mule任务不是BPMN 2.0规范的官方任务(因此没有专用图标)。因此,在Flowable中,mule task任务被实现为专用服务任务

参考

5.9 Camel Task

Description

camel task允许您向Camel发送消息和从Camel接收消息,从而增强Flowable的集成功能。请注意,camel task不是BPMN 2.0规范的官方任务(因此没有专用图标)。因此,在Flowable中,Camel任务被实现为专用服务任务。另请注意,必须在项目中包含Flowable Camel模块才能使用Camel任务功能

参考

5.10 Manual Task

Description

manual task定义BPM引擎外部的任务。它用于模拟由某人完成的工作,引擎不需要知道,也没有系统或用户界面。对于引擎,手动任务作为传递活动处理,从流程执行到达时自动继续流程

XML representation

1
<manualTask id="myManualTask" name="Call client for more information" />

参考

5.11 Java Receive Task

Description

java receuve task务是一个等待某个消息到达的简单任务。目前,我们只为此任务实现了Java语义。当process执行到达接收任务时,process状态将提交给持久性存储。这意味着process将保持此等待状态,直到引擎接收到特定消息,进而触发java receuve task,继续执行process

XML representation

1
<receiveTask id="waitState" name="wait" />

参考

5.12 Shell Task

Description

shell task允许您运行shell脚本和命令。请注意,shell task不是BPMN 2.0规范的官方任务(因此没有专用图标)

XML representation

1
2
3
4
5
6
7
8
9
10
11
<!-- cmd /c echo EchoTest -->
<serviceTask id="shellEcho" flowable:type="shell" >
<extensionElements>
<flowable:field name="command" stringValue="cmd" />
<flowable:field name="arg1" stringValue="/c" />
<flowable:field name="arg2" stringValue="echo" />
<flowable:field name="arg3" stringValue="EchoTest" />
<flowable:field name="wait" stringValue="true" />
<flowable:field name="outputVariable" stringValue="resultVar" />
</extensionElements>
</serviceTask>

参考

5.13 Execution listener

Description

execution listener允许您在流程执行期间发生某些事件时执行外部Java代码或计算表达式。可以捕获的事件是:

  1. 启动或停止process
  2. 进行转移,即sequence flow
  3. 启动或停止activity
  4. 启动或停止gateway
  5. 启动或停止intermediate event
  6. 结束start event或启动end event

示例

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
40
41
<process id="executionListenersProcess">

<!-- 第一个Listener -->
<!-- 在process的启动时触发Listener -->
<extensionElements>
<flowable:executionListener
class="org.flowable.examples.bpmn.executionlistener.ExampleExecutionListenerOne"
event="start" />
</extensionElements>

<startEvent id="theStart" />
<sequenceFlow sourceRef="theStart" targetRef="firstTask" />

<userTask id="firstTask" />

<!-- 第二个Listener -->
<!-- 在进行转移时触发Listener -->
<sequenceFlow sourceRef="firstTask" targetRef="secondTask">
<extensionElements>
<flowable:executionListener
class="org.flowable.examples.bpmn.executionListener.ExampleExecutionListenerTwo" />
</extensionElements>
</sequenceFlow>

<!-- 第一个Listener -->
<!-- 在userTask结束时触发Listener -->
<userTask id="secondTask" >
<extensionElements>
<flowable:executionListener
expression="${myPojo.myMethod(execution.event)}"
event="end" />
</extensionElements>
</userTask>
<sequenceFlow sourceRef="secondTask" targetRef="thirdTask" />

<userTask id="thirdTask" />
<sequenceFlow sourceRef="thirdTask" targetRef="theEnd" />

<endEvent id="theEnd" />

</process>

需要实现的接口:org.flowable.engine.delegate.ExecutionListener

参考

5.14 Task listener

Description

task listener用于在发生某个与任务相关的事件时执行自定义Java逻辑或表达式。task listener只能作为user task的子元素添加到流程定义中。请注意,这也必须作为BPMN 2.0 extensionElements子元素或flowable namespace,因为task listenerFlowable特定的构造

XML representation

1
2
3
4
5
<userTask id="myTask" name="My Task" >
<extensionElements>
<flowable:taskListener event="create" class="org.flowable.MyTaskCreateListener" />
</extensionElements>
</userTask>

event的类型(触发的时刻)

  • create:当Task被创建后,且所有属性设置完毕后
  • assignment:当Task被分配给某人时。当执行流程到达UserTask时,assignment event会优先于create event触发
  • complete:当Task被完成后,且被删除前
  • delete:当Task即将被删除时

需要实现的接口:org.flowable.engine.delegate.TaskListener

参考

5.15 Multi-instance (for each)

Description

multi-instance用于重复执行业务流程中的某个步骤。在编程概念中,multi-instance同于for each语句:它允许您按顺序或并行地为给定集合中的每个元素执行某个步骤,甚至是完整的子流程

参考

5.16 Compensation Handlers

Description

如果某个activity用于补偿另一个activity,则可以将其声明为compensation handlercompensation handler在正常流程中不存在,仅在抛出compensation event时执行

参考

6 Variables

Flowable中,与process相关的这些数据被称为variables,这些数据存储在数据库中,这些变量可以在表达式中,或者Java Service Task中被使用

详细内容请参考Variables

7 Expression

Expression通常指UEL ExpressionUEL的全称是Unified Expression Language

详细内容请参考Expression

7.1 Value Expression

1
2
${myVar}
${myBean.myProperty}

7.2 Method Expression

1
2
3
${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}

7.3 default Object

  1. execution:DelegateExecution的对象
  2. task:DelegateTask的对象
  3. authenticatedUserId:当前已通过身份验证的用户的id

8 Table

8.1 Database table names explained

所有Flowable的表名前缀都是ACT_

Flowable的表名的第二段表示了用途,与API对应

  1. ACT_RE_*RE表示repository,通常用于存储静态数据,比如process definitionsprocess resources等等
  2. ACT_RU_*RU表示runtime,通常用于存储运行时数据,比如tasksvariablesjobs等等
  3. ACT_HI_*HI表示history,通常保存历史数据,例如已经执行过的process instancevariablestasks等等
  4. ACT_GE_*GE表示general,通常表示全局通用数据及设置

参考

8.2 Creating the database tables

flowable的建表语句都在org.flowable:xxx中的org/flowable/db/create路径下

1
flowable.{db}.{create|drop}.{type}.sql
  • {db}:代表数据库类型
  • {create|drop}:创建还是销毁
  • {type}:类型,就两种historyengine

sql文件路径(按如下顺序依次执行,表之间是有依赖关系的,切记按顺序执行)

  1. org.flowable:flowable-engine-common:xxx中的org/flowable/common/db/create/flowable.mysql.create.common.sql
  2. org.flowable:flowable-idm-engine:xxx中的org/flowable/idm/db/create/flowable.mysql.create.identity.sql
  3. org.flowable:flowable-identitylink-service:xxx中的org/flowable/identitylink/service/db/create/flowable.mysql.create.identitylink.sql
  4. org.flowable:flowable-identitylink-service:xxx中的org/flowable/identitylink/service/db/create/flowable.mysql.create.identitylink.history.sql
  5. org.flowable:flowable-variable-service:xxx中的org/flowable/variable/service/db/create/flowable.mysql.create.variable.sql
  6. org.flowable:flowable-variable-service:xxx中的org/flowable/variable/service/db/create/flowable.mysql.create.variable.history.sql
  7. org.flowable:flowable-job-service:xxx中的org/flowable/job/service/db/create/flowable.mysql.create.job.sql
  8. org.flowable:flowable-task-service:xxx中的org/flowable/task/service/db/create/flowable.mysql.create.task.sql
  9. org.flowable:flowable-task-service:xxx中的org/flowable/task/service/db/create/flowable.mysql.create.task.history.sql
  10. org.flowable:flowable-engine:xxx中的org/flowable/db/create/flowable.mysql.create.engine.sql
  11. org.flowable:flowable-engine:xxx中的org/flowable/db/create/flowable.mysql.create.history.sql
  • 共计34张表

参考

9 参考