日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Flowable学习笔记(二、BPMN 2.0-基础 )

發(fā)布時間:2023/12/3 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Flowable学习笔记(二、BPMN 2.0-基础 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載自??Flowable學(xué)習筆記(二、BPMN 2.0-基礎(chǔ) )

1、BPMN簡介

業(yè)務(wù)流程模型和標記法(BPMN, Business Process Model and Notation)是一套圖形化表示法,用于以業(yè)務(wù)流程模型詳細說明各種業(yè)務(wù)流程。

它最初由業(yè)務(wù)流程管理倡議組織(BPMI, Business Process Management Initiative)開發(fā),名稱為"Business Process Modeling Notation",即“業(yè)務(wù)流程建模標記法”。BPMI于2005年與對象管理組織(OMG, Object Management Group)合并。2011年1月OMG發(fā)布2.0版本,同時改為現(xiàn)在的名稱。

?

2、BPMN基本要素

BPMN包含四種要素:

流對象(Flow Object):

  • 事件(Events)
  • 活動(Activities)
  • 網(wǎng)關(guān)(Gateways)

連接對象(Connecting Objects):

  • 順序流(Sequence Flow)
  • 消息流(Message Flow)
  • 關(guān)聯(lián)(Association)

泳道(Swimlanes):

  • 池(Pool)
  • 道(Lane)

附加工件(Artifacts/Artefacts):

  • 數(shù)據(jù)對象(Data Object)
  • 組(Group)
  • 注釋(Annotation)

在這里需要重要關(guān)注4個基本對象,

  • 事件(Event):用來表明流程的生命周期中發(fā)生了什么。
  • 活動(Activity):活動(Activities)是業(yè)務(wù)流程定義的核心元素,中文稱為“活動”、“節(jié)點”、“步驟”。一個活動可以是流程的基本處理單元(如人工任務(wù)、服務(wù)任務(wù)),也可以是一個組合單元(如外部子流程、嵌套子流程)。
  • 網(wǎng)關(guān)(Gateway):用來控制流程的流向。
  • 流向/順序流(Flow):是連接兩個流程節(jié)點的連線。

?

3、流程根元素

一個BPMN 2.0 XML流程的根是definitions元素。 在命名狀態(tài),子元素會包含真正的業(yè)務(wù)流程定義。 每個process子元素 可以擁有一個id(必填)和 name(可選)。下面是一個空的BPMN 2.0業(yè)務(wù)流程 。

<definitions id="myProcesses"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 BPMN20.xsd"xmlns="http://schema.omg.org/spec/BPMN/2.0"typeLanguage="http://www.w3.org/2001/XMLSchema"expressionLanguage="http://www.w3.org/1999/XPath"targetNamespace="http://jbpm.org/example/bpmn2"><process id="My business processs" name="myBusinessProcess">

?

4、BPMN結(jié)構(gòu)

在BPMN中,流對象是用于定義業(yè)務(wù)流程行為的主要圖形元素。需要重點理解三個流對象。


?

4.1、事件

事件包含啟動事件、結(jié)束事件、中間事件,還有一類邊界事件,屬于中間中間事件的一種。

?

4.1.1、啟動事件(startEvent)

啟動事件(start event)(有的譯為開始時間)是流程的起點。啟動事件的類型(例如流程在消息到達時啟動,在指定的時間間隔后啟動,等等),定義了流程如何啟動,并顯示為啟動事件中的小圖標。在XML中,類型由子元素聲明來定義。

啟動事件隨時捕獲:啟動事件(保持)等候,直到特定的觸發(fā)器被觸發(fā)。

4.1.1.1、空啟動事件

  • 描述:空”啟動事件(none Start Event),指的是未指定啟動流程實例觸發(fā)器的啟動事件。引擎將無法預(yù)知何時啟動流程實例。空啟動事件用于流程實例通過調(diào)用下列startProcessInstanceByXXX API方法啟動的情況。
ProcessInstance processInstance = runtimeService.startProcessInstanceByXXX();
  • 圖示:空啟動事件用空心圓圈表示,中間沒有圖標(也就是說,沒有觸發(fā)器):

  • xml表示:
<startEvent id="start" name="my start event" />

?

4.1.1.2、定時器啟動事件

  • 描述:定時器啟動事件(timer start event)在指定時間創(chuàng)建流程實例。在流程只需要啟動一次,或者流程需要在特定的時間間隔重復(fù)啟動時,可以使用定時器啟動事件。

請注意:子流程不能有定時器啟動事件。
請注意:定時器啟動事件,在流程部署的同時就開始計時。不需要調(diào)用startProcessInstanceByXXX就會在時間啟動。調(diào)用startProcessInstanceByXXX時會在定時啟動之外額外啟動一個流程。
請注意:當部署帶有定時器啟動事件的流程的更新版本時,上一版本的定時器作業(yè)會被移除。這是因為通常并不希望舊版本的流程仍然自動啟動新的流程實例。

  • 圖示:定時器啟動事件,用其中有一個鐘表圖標的圓圈來表示。

  • XML表示:定時器啟動事件的XML表示格式,是普通的啟動事件聲明加上定時器定義子元素。

示例:流程會啟動4次,間隔5分鐘,從2011年3月11日,12:13開始

<startEvent id="theStart"><timerEventDefinition><timeCycle>R4/2011-03-11T12:13/PT5M</timeCycle></timerEventDefinition> </startEvent>

示例:流程會在設(shè)定的時間啟動一次

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

?

4.1.1.3、消息啟動事件

  • 描述:
    消息啟動事件(message start event)使用具名消息啟動流程實例。消息名用于選擇正確的啟動事件。

當部署具有一個或多個消息啟動事件的流程定義時,會做如下判斷:

>> 給定流程定義中,消息啟動事件的名字必須是唯一的。一個流程定義不得包含多個同名的消息啟動事件。如果流程定義中有兩個或多個消息啟動事件引用同一個消息,或者兩個或多個消息啟動事件引用了具有相同消息名字的消息,則Flowable會在部署這個流程定義時拋出異常。

>> 在所有已部署的流程定義中,消息啟動事件的名字必須是唯一的。如果在流程定義中,一個或多個消息啟動事件引用了已經(jīng)部署的另一流程定義中消息啟動事件的消息名,則Flowable會在部署這個流程定義時拋出異常。

>> 流程版本:在部署流程定義的新版本時,會取消上一版本的消息訂閱,即使新版本中并沒有這個消息事件)。

  • 圖示:消息啟動事件用其中有一個消息事件標志的圓圈表示。這個標志并未填充,用以表示捕獲(接收)行為。

  • XML表示:
    消息啟動事件的XML表示格式,為普通啟動事件聲明加上messageEventDefinition子元素:

<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>

?

4.1.1.4、信號啟動事件

  • 描述:
    信號啟動事件(signal start event),使用具名信號啟動流程實例。這個信號可以由流程實例中的信號拋出中間事件(intermediary signal throw event),或者API(runtimeService.signalEventReceivedXXX方法)觸發(fā)。兩種方式都會啟動所有擁有相同名字信號啟動事件的流程定義。

請注意可以選擇異步還是同步啟動流程實例。

需要為API傳遞的signalName,是由signal元素的name屬性決定的名字。signal元素由signalEventDefinition的signalRef屬性引用。

  • 圖示:
    信號啟動事件用其中有一個信號事件標志的圓圈表示。這個標志并未填充,用以表示捕獲(接收)行為。

?

  • XML表示:
    信號啟動事件的XML表示格式,為普通啟動事件聲明,加上signalEventDefinition子元素:
<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>

?

4.1.1.5、錯誤啟動事件

  • 描述:
    錯誤啟動事件(error start event),可用于觸發(fā)事件子流程(Event Sub-Process)。錯誤啟動事件不能用于啟動流程實例。
    錯誤啟動事件總是中斷。

  • 圖示:
    錯誤啟動事件用其中有一個錯誤事件標志的圓圈表示。這個標志并未填充,用以表示捕獲(接收)行為。

  • XML表示:
    錯誤啟動事件的XML表示格式,為普通啟動事件聲明加上errorEventDefinition子元素:
<startEvent id="messageStart" ><errorEventDefinition errorRef="someError" /> </startEvent>

?

4.1.2、結(jié)束事件

結(jié)束事件(end event)標志著流程或子流程中一個分支的結(jié)束。結(jié)束事件總是拋出(型)事件。這意味著當流程執(zhí)行到達結(jié)束事件時,會拋出一個結(jié)果。結(jié)果的類型由事件內(nèi)部的黑色圖標表示。在XML表示中,類型由子元素聲明給出。

?

4.1.2.1、空結(jié)束事件

  • 描述:
    “空”結(jié)束事件(none end event),意味著當?shù)竭_這個事件時,沒有特別指定拋出的結(jié)果。因此,引擎除了結(jié)束當前執(zhí)行分支之外,不會多做任何事情。

  • 圖示:
    空結(jié)束事件,用其中沒有圖標(沒有結(jié)果類型)的粗圓圈表示。

  • xml表示:
    空事件的XML表示格式為普通結(jié)束事件聲明,沒有任何子元素(其它種類的結(jié)束事件都有子元素,用于聲明其類型)。
<endEvent id="end" name="my end event" />

?

4.1.2.2、錯誤結(jié)束事件

  • 描述:
    當流程執(zhí)行到達錯誤結(jié)束事件(error end event)時,結(jié)束執(zhí)行的當前分支,并拋出錯誤。這個錯誤可以由匹配的錯誤邊界中間事件捕獲。如果找不到匹配的錯誤邊界事件,將會拋出異常。

  • 圖示:
    錯誤結(jié)束事件事件用內(nèi)部有一個錯誤圖標的標準結(jié)束事件(粗圓圈)表示。錯誤圖標是全黑的,代表拋出的含義。

  • XML表示:
    錯誤結(jié)束事件表示為結(jié)束事件,加上errorEventDefinition子元素:
<endEvent id="myErrorEndEvent"><errorEventDefinition errorRef="myError" /> </endEvent>

errorRef屬性可以引用在流程外定義的error元素:

<error id="myError" errorCode="123" /> ... <process id="myProcess"> ...

?

4.1.2.3、終止結(jié)束事件

  • 描述:
    當?shù)竭_終止結(jié)束事件(terminate end event)時,當前的流程實例或子流程會被終止。也就是說,當執(zhí)行到達終止結(jié)束事件時,會判斷第一個范圍 scope(流程或子流程)并終止它。在BPMN 2.0中,子流程可以是嵌入式子流程,調(diào)用活動,事件子流程,或事務(wù)子流程。有一條通用規(guī)則:當存在多實例的調(diào)用過程或嵌入式子流程時,只會終止一個實例,其他的實例與流程實例不會受影響。
    可以添加一個可選屬性terminateAll。當其為true時,無論該終止結(jié)束事件在流程定義中的位置,也無論它是否在子流程(甚至是嵌套子流程)中,都會終止(根)流程實例。

  • 圖示:
    終止結(jié)束事件用內(nèi)部有一個全黑圓的標準結(jié)束事件(粗圓圈)表示。

  • xml表示:
    終止結(jié)束事件,表示為結(jié)束事件,加上terminateEventDefinition子元素。
    terminateAll屬性是可選的(默認為false)。

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

?

4.1.2.4、取消結(jié)束事件

  • 描述:
    取消結(jié)束事件(cancel end event)只能與BPMN事務(wù)子流程(BPMN transaction subprocess)一起使用。當?shù)竭_取消結(jié)束事件時,會拋出取消事件,且必須由取消邊界事件(cancel boundary event)捕獲。取消邊界事件將取消事務(wù),并觸發(fā)補償(compensation)。

  • 圖示:
    取消結(jié)束事件用內(nèi)部有一個取消圖標的標準結(jié)束事件(粗圓圈)表示。取消圖標是全黑的,代表拋出的含義。

  • xml表示:
    取消結(jié)束事件,表示為結(jié)束事件,加上cancelEventDefinition子元素。

<endEvent id="myCancelEndEvent"><cancelEventDefinition /> </endEvent>

?

4.1.3、邊界事件

邊界事件(boundary event)是捕獲型事件,依附在活動(activity)上。邊界事件永遠不會拋出。這意味著當活動運行時,事件將監(jiān)聽特定類型的觸發(fā)器。當捕獲到事件時,會終止活動,并沿該事件的出口順序流繼續(xù)。

所有的邊界事件都用相同的方式定義:

<boundaryEvent id="myBoundaryEvent" attachedToRef="theActivity"><XXXEventDefinition/> </boundaryEvent>

邊界事件由下列元素定義:

  • (流程范圍內(nèi))唯一的標識符
* 由attachedToRef屬性定義的,對該事件所依附的活動的引用。邊界事件及其所依附的活動,應(yīng)定義在相同級別(也就是說,邊界事件并不包含在活動內(nèi))。* 定義了邊界事件的類型的,形如XXXEventDefinition的XML子元素(例如TimerEventDefinition,ErrorEventDefinition,等等)。查閱特定的邊界事件類型,以了解更多細節(jié)。

?

4.1.3.1、定時器邊界事件

  • 描述:
    定時器邊界事件(timer boundary event)的行為像是跑表與鬧鐘。當執(zhí)行到達邊界事件所依附的活動時,將啟動定時器。當定時器觸發(fā)時(例如在特定時間間隔后),可以中斷活動,并沿著邊界事件的出口順序流繼續(xù)執(zhí)行。

  • 圖示:
    定時器邊界事件用內(nèi)部有一個定時器圖標的標準邊界事件(圓圈)表示。

  • XML表示:
    定時器邊界事件與一般邊界事件一樣定義。其中類型子元素為timerEventDefinition元素。
<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport"><timerEventDefinition><timeDuration>PT4H</timeDuration></timerEventDefinition> </boundaryEvent>

?

4.1.3.2、錯誤邊界事件

  • 描述
    在活動邊界上的錯誤捕獲中間(事件),或簡稱錯誤邊界事件(error boundary event),捕獲其所依附的活動范圍內(nèi)拋出的錯誤。
    在嵌入式子流程或者調(diào)用活動上定義錯誤邊界事件最有意義,因為子流程的范圍會包括其中的所有活動。錯誤可以由錯誤結(jié)束事件拋出。這樣的錯誤會逐層向其上級父范圍傳播,直到在范圍內(nèi)找到一個匹配錯誤事件定義的錯誤邊界事件。
    當捕獲錯誤事件時,會銷毀邊界事件定義所在的活動,同時銷毀其中所有的當前執(zhí)行(例如,并行活動,嵌套子流程,等等)。流程執(zhí)行將沿著邊界事件的出口順序流繼續(xù)。

  • 圖示:
    錯誤邊界事件用內(nèi)部有一個錯誤圖標的標準中間事件(兩層圓圈)表示。錯誤圖標是白色的,代表捕獲的含義。

  • xml表示:
    錯誤邊界事件與標準邊界事件一樣定義:

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

?

4.1.3.3、信號邊界事件

  • 描述:
    依附在活動邊界上的信號捕獲中間(事件),或簡稱信號邊界事件(signal boundary event),捕獲與其信號定義具有相同名稱的信號。

與其他事件例如錯誤邊界事件不同的是,信號邊界事件不只是捕獲其所依附范圍拋出的信號。信號邊界事件為全局范圍(廣播)的,意味著信號可以從任何地方拋出,甚至可以是不同的流程實例。

  • 圖示:
    信號邊界事件,用內(nèi)部有一個信號圖標的標準中間事件(兩層圓圈)表示。信號圖標是白色的,代表捕獲的含義。

  • xml表示:
    信號邊界事件與標準邊界事件一樣定義:
<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true"><signalEventDefinition signalRef="alertSignal"/> </boundaryEvent>

?

4.1.3.4、消息邊界事件

  • 描述:
    在活動邊界上的消息捕獲中間(事件),或簡稱消息邊界事件(message boundary event),捕獲與其消息定義具有相同消息名的消息。

  • 圖示:
    消息邊界事件,用內(nèi)部有一個消息圖標的標準中間事件(兩層圓圈)表示。信號圖標是白色的,代表捕獲的含義。

    息邊界事件既可以是中斷型的(右圖),也可以是非中斷型的(左圖)。

  • XML表示:
    消息邊界事件與標準邊界事件一樣定義:

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

?

4.1.3.5、取消邊界事件

  • 描述
    依附在事務(wù)子流程邊界上的取消捕獲中間事件,或簡稱取消邊界事件(cancel boundary event),在事務(wù)取消時觸發(fā)。當取消邊界事件觸發(fā)時,首先會中斷當前范圍的所有活動執(zhí)行。接下來,啟動事務(wù)范圍內(nèi)所有有效的的補償邊界事件(compensation boundary event)。補償會同步執(zhí)行,也就是說在離開事務(wù)前,邊界事件會等待補償完成。當補償完成時,沿取消邊界事件的任何出口順序流離開事務(wù)子流程。

>>> 一個事務(wù)子流程只允許使用一個取消邊界事件。
>>> 如果事務(wù)子流程中有嵌套的子流程,只會對成功完成的子流程觸發(fā)補償。
>>> 如果取消邊界事件放置在具有多實例特性的事務(wù)子流程上,如果一個實例觸發(fā)了取消,則邊界事件將取消所有實例。

  • 圖示:
    取消邊界事件,用內(nèi)部有一個取消圖標的標準中間事件(兩層圓圈)表示。取消圖標是白色的(未填充),代表捕獲的含義。

  • xml表示:
    取消邊界事件與標準邊界事件一樣定義:
<boundaryEvent id="boundary" attachedToRef="transaction" ><cancelEventDefinition /> </boundaryEvent>

?

4.1.3.6、補償邊界事件

  • 描述:
    依附在活動邊界上的補償捕獲中間(事件),或簡稱補償邊界事件(compensation boundary event),可以為活動附加補償處理器。
    補償邊界事件必須使用直接關(guān)聯(lián)的方式引用單個的補償處理器。
    補償邊界事件與其它邊界事件的活動策略不同。其它邊界事件,例如信號邊界事件,在其依附的活動啟動時激活;當該活動結(jié)束時會被解除,并取消相應(yīng)的事件訂閱。而補償邊界事件不是這樣。補償邊界事件在其依附的活動成功完成時激活,同時創(chuàng)建補償事件的相應(yīng)訂閱。當補償事件被觸發(fā),或者相應(yīng)的流程實例結(jié)束時,才會移除訂閱。請考慮下列因素:

    >>> 當補償被觸發(fā)時,會調(diào)用補償邊界事件關(guān)聯(lián)的補償處理器。調(diào)用次數(shù)與其依附的活動成功完成的次數(shù)相同。

    >>>如果補償邊界事件依附在具有多實例特性的活動上,則會為每一個實例創(chuàng)建補償事件訂閱。

    >>> 如果補償邊界事件依附在位于循環(huán)內(nèi)部的活動上,則每次該活動執(zhí)行時,都會創(chuàng)建一個補償事件訂閱。

    >>> 如果流程實例結(jié)束,則取消補償事件的訂閱。

  • 圖示:
    補償邊界事件,用內(nèi)部有一個補償圖標的標準中間事件(兩層圓圈)表示。補償圖標是白色的(未填充),代表捕獲的含義。另外,補償邊界事件使用單向連接關(guān)聯(lián)補償處理器,如下圖所示:

  • xml表示:
    補償邊界事件與標準邊界事件一樣定義:

<boundaryEvent id="compensateBookHotelEvt" attachedToRef="bookHotel" ><compensateEventDefinition /> </boundaryEvent><association associationDirection="One" id="a1"sourceRef="compensateBookHotelEvt" targetRef="undoBookHotel" /><serviceTask id="undoBookHotel" isForCompensation="true" flowable:class="..." />

?

4.1.4、中間事件

在開始事件和結(jié)束事件之間發(fā)生的事件都稱為中間事件。中間事件會影響流程的流轉(zhuǎn)路線,但不會啟動或直接終止流程的執(zhí)行。

中間事件按照其特性可以分為兩類:中間Catching(捕獲)事件和中間Throwing(拋出)事件,當流程到達中間Catching事件時,它會一直在等待被觸發(fā),直接接收到的信息,才會被觸發(fā),而當流程到達中間Throwing事件時,該事件會自動被觸發(fā)并拋出相應(yīng)的結(jié)果或者信息。

?

4.1.4.1、捕獲中間事件

所有的捕獲中間事件(intermediate catching events)都使用相同方式定義:

<intermediateCatchEvent id="myIntermediateCatchEvent" ><XXXEventDefinition/> </intermediateCatchEvent>

捕獲中間事件由下列元素定義:

  • (流程范圍內(nèi))唯一的標識符

  • 定義了捕獲中間事件類型的,形如XXXEventDefinition的XML子元素(例如TimerEventDefinition等)。查閱特定中間捕獲事件類型,以了解更多細節(jié)。

?

4.1.4.1.1、定時器捕獲中間事件

  • 描述:
    定時器捕獲中間事件(timer intermediate catching event)的行為像是跑表。當執(zhí)行到達捕獲事件時,啟動定時器;當定時器觸發(fā)時(例如在一段時間間隔后),沿定時器中間事件的出口順序流繼續(xù)執(zhí)行。

  • 圖示:
    定時器中間事件用內(nèi)部有定時器圖標的中間捕獲事件表示。

  • XML表示:
    定時器中間事件與捕獲中間事件一樣定義。子元素為timerEventDefinition。

<intermediateCatchEvent id="timer"><timerEventDefinition><timeDuration>PT5M</timeDuration></timerEventDefinition> </intermediateCatchEvent>

?

4.1.4.1.2、信號捕獲中間事件

  • 描述:
    信號捕獲中間事件(signal intermediate catching event),捕獲與其引用的信號定義具有相同信號名稱的信號。

>>> 與其他事件如錯誤事件不同,信號在被捕獲后不會被消耗。如果有兩個激活的信號中間事件,捕獲相同的信號事件,則兩個中間事件都會被觸發(fā),哪怕它們不在同一個流程實例里。

  • 圖示:
    信號捕獲中間事件用內(nèi)部有信號圖標的標準中間事件(兩層圓圈)表示。信號圖標是白色的(未填充),代表捕獲的含義。

  • xml表示:
    信號中間事件與捕獲中間事件一樣定義。子元素為signalEventDefinition。
<intermediateCatchEvent id="signal"><signalEventDefinition signalRef="newCustomerSignal" /> </intermediateCatchEvent>

?

4.1.4.1.3、信號捕獲中間事件

  • 描述:
    消息捕獲中間事件(message intermediate catching event),捕獲特定名字的消息。

  • 圖示:
    消息捕獲中間事件用內(nèi)部有消息圖標的標準中間事件(兩層圓圈)表示。消息圖標是白色的(未填充),代表捕獲的含義。

  • xml表示:
    消息中間事件與捕獲中間事件一樣定義。子元素為messageEventDefinition。
<intermediateCatchEvent id="message"><messageEventDefinition signalRef="newCustomerMessage" /> </intermediateCatchEvent>

?

4.1.4.2、拋出中間事件

所有的拋出中間事件(intermediate throwing evnet)都使用相同方式定義:

<intermediateThrowEvent id="myIntermediateThrowEvent" ><XXXEventDefinition/> </intermediateThrowEvent>

拋出中間事件由下列元素定義:

  • (流程范圍內(nèi))唯一的標識符
* 定義了拋出中間事件類型的,形如XXXEventDefinition的XML子元素(例如signalEventDefinition等)。查閱特定中間拋出事件類型,以了解更多細節(jié)。

?

4.1.4.2.1、空拋出中間事件

下面的流程圖展示了空拋出中間事件(intermediate throwing none event)的簡單例子。其用于指示流程已經(jīng)到達了某種狀態(tài)。

添加一個執(zhí)行監(jiān)聽器后,空中間事件就可以成為很好的監(jiān)視某些KPI(Key Performance Indicators 關(guān)鍵績效指標)的鉤子。

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

?

4.1.4.2.2、信號拋出中間事件

  • 描述:
    信號拋出中間事件(signal intermediate throwing event),拋出所定義信號的信號事件。

在Flowable中,信號會廣播至所有的激活的處理器(也就是說,所有的信號捕獲事件)。可以同步或異步地發(fā)布信號。

  • 在默認配置中,信號同步地傳遞。這意味著拋出信號的流程實例會等待,直到信號傳遞至所有的捕獲信號的流程實例。所有的捕獲流程實例也會在與拋出流程實例相同的事務(wù)中,也就是說如果收到通知的流程實例中,有一個實例產(chǎn)生了技術(shù)錯誤(拋出異常),則所有相關(guān)的實例都會失敗。
  • 信號也可以異步地傳遞。這是由到達拋出信號事件時的發(fā)送處理器來決定的。對于每個激活的處理器,JobExecutor會為其存儲并傳遞一個異步通知消息(asynchronous notification message),即作業(yè)(Job)。
  • 圖示:
    消息拋出中間事件用內(nèi)部有信號圖標的標準中間事件(兩層圓圈)表示。信號圖標是黑色的(已填充),代表拋出的含義。

  • xml表示:
    信號中間事件與拋出中間事件一樣定義。子元素為signalEventDefinition。

<intermediateThrowEvent id="signal"><signalEventDefinition signalRef="newCustomerSignal" /> </intermediateThrowEvent>

異步信號事件這樣定義:

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

?

4.1.4.2.3、補償拋出中間事件

  • 描述:
    補償拋出中間事件(compensation intermediate throwing event)用于觸發(fā)補償。

觸發(fā)補償:既可以為設(shè)計的活動觸發(fā)補償,也可以為補償事件所在的范圍觸發(fā)補償。補償由活動所關(guān)聯(lián)的補償處理器執(zhí)行。

  • 活動拋出補償時,活動關(guān)聯(lián)的補償處理器將執(zhí)行的次數(shù),為活動成功完成的次數(shù)。
  • 拋出補償時,當前范圍中所有的活動,包括并行分支上的活動都會被補償。
* * 補償分層觸發(fā):如果將要被補償?shù)幕顒邮且粋€子流程,則該子流程中所有的活動都會觸發(fā)補償。如果該子流程有嵌套的活動,則會遞歸地拋出補償。然而,補償不會傳播至流程的上層:如果子流程中觸發(fā)了補償,該補償不會傳播至子流程范圍外的活動。BPMN規(guī)范指出,對“與子流程在相同級別”的活動觸發(fā)補償。* * 在Flowable中,補償按照執(zhí)行的相反順序運行。這意味著最后完成的活動會第一個補償。
  • 可以使用補償拋出中間事件補償已經(jīng)成功完成的事務(wù)子流程。

>>> 如果拋出補償?shù)姆秶杏幸粋€子流程,而該子流程包含有關(guān)聯(lián)了補償處理器的活動,則當拋出補償時,只有該子流程成功完成時,補償才會傳播至該子流程。如果子流程內(nèi)嵌套的部分活動已經(jīng)完成,并附加了補償處理器,但包含這些活動的子流程還沒有完成,則這些補償處理器仍不會執(zhí)行。參考下面的例子:

在這個流程中,有兩個并行的執(zhí)行:一個執(zhí)行嵌入子流程,另一個執(zhí)行“charge credit card(信用卡付款)”活動。假定兩個執(zhí)行都已開始,且第一個執(zhí)行正等待用戶完成“review bookings(檢查預(yù)定)”任務(wù)。第二個執(zhí)行進行了“charge credit card(信用卡付款)”活動的操作,拋出了錯誤,導(dǎo)致“cancel reservations(取消預(yù)訂)”事件觸發(fā)補償。這時并行子流程還未完成,意味著補償不會傳播至該子流程,因此不會執(zhí)行“cancel hotel reservation(取消酒店預(yù)訂)”補償處理器。而如果“cancel reservations(取消預(yù)訂)”運行前,這個用戶任務(wù)(因此該嵌入式子流程也)已經(jīng)完成,則補償會傳播至該嵌入式子流程。

流程變量:當補償嵌入式子流程時,用于執(zhí)行補償處理器的執(zhí)行,可以訪問子流程的局部流程變量在子流程完成時的值。為此,會對范圍執(zhí)行(為執(zhí)行子流程所創(chuàng)建的執(zhí)行)所關(guān)聯(lián)的流程變量進行快照。意味著:

  • 補償執(zhí)行器無法訪問子流程范圍內(nèi)并行執(zhí)行所添加的變量。
* * 上層執(zhí)行所關(guān)聯(lián)的流程變量(例如流程實例關(guān)聯(lián)的流程變量)不在該快照中。因為補償處理器可以直接訪問這些流程變量在拋出補償時的值。* * 只會為嵌入式子流程進行變量快照。其他活動不會進行變量快照。

目前的限制:

  • 目前不支持waitForCompletion="false"。當補償拋出中間事件觸發(fā)補償時,只有在補償成功完成時,才會離開該事件。
* * 補償由并行執(zhí)行運行。并行執(zhí)行會按照補償活動完成的逆序啟動。
  • 補償不會傳播至調(diào)用活動(call activity)生成的子流程。
  • 圖示:
    補償拋出中間事件用內(nèi)部有補償圖標的標準中間事件(兩層圓圈)表示。補償圖標是黑色的(已填充),代表拋出的含義。

  • xml表示:
    補償中間事件與拋出中間事件一樣定義。子元素為compensateEventDefinition。
<intermediateThrowEvent id="throwCompensation"><compensateEventDefinition /> </intermediateThrowEvent>

另外,activityRef可選項用于為指定的范圍或活動觸發(fā)補償:

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

?

4.2、順序流

  • 描述:
    順序流(sequence flow)是流程中兩個元素間的連接器。在流程執(zhí)行過程中,一個元素被訪問后,會沿著其所有出口順序流繼續(xù)執(zhí)行。這意味著BPMN 2.0的默認是并行執(zhí)行的:兩個出口順序流就會創(chuàng)建兩個獨立的、并行的執(zhí)行路徑。

  • 圖示:
    順序流,用從源元素指向目標元素的箭頭表示。箭頭總是指向目標元素。

  • xml表示:
    順序流需要有流程唯一的id,并引用存在的源與目標元素。

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

?

4.2.1、條件順序流

  • 描述:
    在順序流上可以定義條件(conditional sequence flow)。當離開BPMN 2.0活動時,默認行為是計算其每個出口順序流上的條件。當條件計算為true時,選擇該出口順序流。如果該方法選擇了多條順序流,則會生成多個執(zhí)行,流程會以并行方式繼續(xù)。

>>> 上面的介紹針對BPMN 2.0活動(與事件),但不適用于網(wǎng)關(guān)(gateway)。不同類型的網(wǎng)關(guān),會用不同的方式處理帶有條件的順序流。

  • 圖示:
    條件順序流用起點帶有小菱形的順序流表示。在順序流旁顯示條件表達式。

  • xml表示:
    條件順序流的XML表示格式為含有conditionExpression(條件表達式)子元素的普通順序流。請注意目前只支持tFormalExpressions。可以省略xsi:type=""定義,默認為唯一支持的表達式類型。
<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask"><conditionExpression xsi:type="tFormalExpression"><![CDATA[${order.price > 100 && order.price < 250}]]></conditionExpression> </sequenceFlow>

>>> 目前conditionalExpressions只能使用UEL。使用的表達式需要能解析為boolean值,否則當計算條件時會拋出異常。

  • 下面的例子,通過典型的JavaBean的方式,使用getter引用流程變量的數(shù)據(jù)。
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${order.price > 100 && order.price < 250}]]> </conditionExpression>
  • 這個例子調(diào)用了一個解析為boolean值的方法。
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${order.isStandardOrder()}]]> </conditionExpression>

Flowable發(fā)行版中包含了下列示例流程,用于展示值表達式與方法表達式的使用。

?

4.2.2、默認順序流

  • 描述:
    所有的BPMN 2.0任務(wù)與網(wǎng)關(guān)都可以使用默認順序流(default sequence flow)。只有當沒有其他順序流可以選擇時,才會選擇默認順序流作為活動的出口順序流。流程會忽略默認順序流上的條件。

  • 圖示:
    默認順序流用起點帶有“斜線”標記的一般順序流表示。

  • XML表示:
    活動的默認順序流由該活動的default屬性定義。下面的XML片段展示了一個排他網(wǎng)關(guān)(exclusive gateway),帶有默認順序流flow 2。只有當conditionA與conditionB都計算為false時,才會選擇默認順序流作為網(wǎng)關(guān)的出口順序流。
<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>

對應(yīng)下面的圖示:

?

4.3、網(wǎng)關(guān)

網(wǎng)關(guān)(gateway)用于控制執(zhí)行的流向(或者按BPMN 2.0的用詞:執(zhí)行的“標志(token)”)。網(wǎng)關(guān)可以消費(consuming)與生成(generating)標志。

網(wǎng)關(guān)用其中帶有圖標的菱形表示。該圖標顯示了網(wǎng)關(guān)的類型。

這里出口順序流的含義與BPMN 2.0中的一般情況不一樣。一般情況下,會選擇所有條件計算為true的順序流,并行執(zhí)行。而使用排他網(wǎng)關(guān)時,只會選擇一條順序流。當多條順序流的條件都計算為true時,會且僅會選擇在XML中最先定義的順序流繼續(xù)流程。如果沒有可選的順序流,會拋出異常。

?

4.3.1、排他網(wǎng)關(guān)

  • 描述:
    排他網(wǎng)關(guān)(exclusive gateway)(也叫異或網(wǎng)關(guān) XOR gateway,或者更專業(yè)的,基于數(shù)據(jù)的排他網(wǎng)關(guān) exclusive data-based gateway),用于對流程中的決策建模。當執(zhí)行到達這個網(wǎng)關(guān)時,會按照所有出口順序流定義的順序?qū)λ鼈冞M行計算。選擇第一個條件計算為true的順序流(當沒有設(shè)置條件時,認為順序流為true)繼續(xù)流程。

  • 圖示:
    排他網(wǎng)關(guān)用內(nèi)部帶有’X’圖標的標準網(wǎng)關(guān)(菱形)表示,'X’圖標代表異或的含義。請注意內(nèi)部沒有圖標的網(wǎng)關(guān)默認為排他網(wǎng)關(guān)。BPMN 2.0規(guī)范不允許在同一個流程中混合使用有及沒有X的菱形標志。

  • xml表示:
    排他網(wǎng)關(guān)的XML表示格式很簡潔:一行定義網(wǎng)關(guān)的XML。條件表達式定義在其出口順序流上。

以下面的模型為例:

其xml表示如下:

<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.3.2、并行網(wǎng)關(guān)

  • 描述:
    網(wǎng)關(guān)也可以建模流程中的并行執(zhí)行。在流程模型中引入并行的最簡單的網(wǎng)關(guān),就是并行網(wǎng)關(guān)(parallel gateway)。它可以將執(zhí)行分支(fork)為多條路徑,也可以合并(join)多條入口路徑的執(zhí)行。

并行網(wǎng)關(guān)的功能取決于其入口與出口順序流:

  • 分支:所有的出口順序流都并行執(zhí)行,為每一條順序流創(chuàng)建一個并行執(zhí)行。
  • 合并:所有到達并行網(wǎng)關(guān)的并行執(zhí)行都會在網(wǎng)關(guān)處等待,直到每一條入口順序流都到達了有個執(zhí)行。然后流程經(jīng)過該合并網(wǎng)關(guān)繼續(xù)。

>>> 如果并行網(wǎng)關(guān)同時具有多條入口與出口順序流,可以同時具有分支與合并的行為。在這種情況下,網(wǎng)關(guān)首先合并所有入口順序流,然后分裂為多條并行執(zhí)行路徑。

與其他網(wǎng)關(guān)類型有一個重要區(qū)別:并行網(wǎng)關(guān)不計算條件。如果連接到并行網(wǎng)關(guān)的順序流上定義了條件,會直接忽略該條件。

  • 圖示:
    并行網(wǎng)關(guān),用內(nèi)部帶有’加號’圖標的網(wǎng)關(guān)(菱形)表示,代表與(AND)的含義。

  • xml表示:
    定義并行網(wǎng)關(guān)只需要一行XML:
<parallelGateway id="myParallelGateway" />

實際行為(分支,合并或兩者皆有),由連接到該并行網(wǎng)關(guān)的順序流定義。

例如,上面的模型表示為下面的XML:

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

在上面的例子中,當流程啟動后會創(chuàng)建兩個任務(wù):

ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin"); TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();List<Task> tasks = query.list(); assertEquals(2, tasks.size());Task task1 = tasks.get(0); assertEquals("Receive Payment", task1.getName()); Task task2 = tasks.get(1); assertEquals("Ship Order", task2.getName());

當這兩個任務(wù)完成后,第二個并行網(wǎng)關(guān)會合并這兩個執(zhí)行。由于它只有一條出口順序流,因此就不會再創(chuàng)建并行執(zhí)行路徑,而只是激活A(yù)rchive Order(存檔訂單)任務(wù)。

并行網(wǎng)關(guān)不需要“平衡”(也就是說,前后對應(yīng)的兩個并行網(wǎng)關(guān),其入口/出口順序流的數(shù)量不需要一致)。每個并行網(wǎng)關(guān)都會簡單地等待所有入口順序流,并為每一條出口順序流創(chuàng)建并行執(zhí)行,而不受流程模型中的其他結(jié)構(gòu)影響。因此,下面的流程在BPMN 2.0中是合法的:

4.3.3、包容網(wǎng)關(guān)

  • 描述:
    可以把包容網(wǎng)關(guān)(inclusive gateway)看做排他網(wǎng)關(guān)與并行網(wǎng)關(guān)的組合。與排他網(wǎng)關(guān)一樣,可以在包容網(wǎng)關(guān)的出口順序流上定義條件,包容網(wǎng)關(guān)會計算條件。然而主要的區(qū)別是,包容網(wǎng)關(guān)與并行網(wǎng)關(guān)一樣,可以同時選擇多于一條出口順序流。

包容網(wǎng)關(guān)的功能取決于其入口與出口順序流:

  • 分支:流程會計算所有出口順序流的條件。對于每一條計算為true的順序流,流程都會創(chuàng)建一個并行執(zhí)行。
  • 合并:所有到達包容網(wǎng)關(guān)的并行執(zhí)行,都會在網(wǎng)關(guān)處等待。直到每一條具有流程標志(process token)的入口順序流,都有一個執(zhí)行到達。這是與并行網(wǎng)關(guān)的重要區(qū)別。換句話說,包容網(wǎng)關(guān)只會等待可以被執(zhí)行的入口順序流。在合并后,流程穿過合并并行網(wǎng)關(guān)繼續(xù)。

>>> 如果包容網(wǎng)關(guān)同時具有多條入口與出口順序流,可以同時具有分支與合并的行為。在這種情況下,網(wǎng)關(guān)首先合并所有具有流程標志的入口順序流,然后為每一個條件計算為true的出口順序流分裂出并行執(zhí)行路徑。

包容網(wǎng)關(guān)的匯聚行為比并行網(wǎng)關(guān)更復(fù)雜。所有到達包容網(wǎng)關(guān)的并行執(zhí)行,都會在網(wǎng)關(guān)等待,直到所有“可以到達”包容網(wǎng)關(guān)的執(zhí)行都“到達”包容網(wǎng)關(guān)。 判斷方法為:計算當前流程實例中的所有執(zhí)行,檢查從其位置是否有一條到達包容網(wǎng)關(guān)的路徑(忽略順序流上的任何條件)。如果存在這樣的執(zhí)行(可到達但尚未到達),則不會觸發(fā)包容網(wǎng)關(guān)的匯聚行為。

  • xml表示:
    定義包容網(wǎng)關(guān)需要一行XML:
<inclusiveGateway id="myInclusiveGateway" />

實際行為(分支,合并或兩者皆有),由連接到該包容網(wǎng)關(guān)的順序流定義。

例如,上面的模型表現(xiàn)為下面的XML:

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

在上面的例子中,當流程啟動后,如果流程變量paymentReceived == false且shipOrder == true,會創(chuàng)建兩個任務(wù)。如果只有一個流程變量等于true,則只會創(chuàng)建一個任務(wù)。如果沒有條件計算為true,會拋出異常(可通過指定默出口順序流避免)。在下面的例子中,只會創(chuàng)建ship order(傳遞訂單)一個任務(wù):

HashMap<String, Object> variableMap = new HashMap<String, Object>(); variableMap.put("receivedPayment", true); variableMap.put("shipOrder", true);ProcessInstance pi = runtimeService.startProcessInstanceByKey("forkJoin");TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();List<Task> tasks = query.list(); assertEquals(1, tasks.size());Task task = tasks.get(0); assertEquals("Ship Order", task.getName());

當這個任務(wù)完成后,第二個包容網(wǎng)關(guān)會合并這兩個執(zhí)行。并且由于它只有一條出口順序流,所有不會再創(chuàng)建并行執(zhí)行路徑,而只會激活A(yù)rchive Order(存檔訂單)任務(wù)。

>>> 包容網(wǎng)關(guān)不需要“平衡”(也就是說,對應(yīng)的包容網(wǎng)關(guān),其入口/出口順序流的數(shù)量不需要匹配)。包容網(wǎng)關(guān)會簡單地等待所有入口順序流,并為每一條出口順序流創(chuàng)建并行執(zhí)行,不受流程模型中的其他結(jié)構(gòu)影響。

>>> 包容網(wǎng)關(guān)不需要“平衡”(也就是說,前后對應(yīng)的兩個包容網(wǎng)關(guān),其入口/出口順序流的數(shù)量不需要一致)。每個包容網(wǎng)關(guān)都會簡單地等待所有入口順序流,并為每一條出口順序流創(chuàng)建并行執(zhí)行,不受流程模型中的其他結(jié)構(gòu)影響。

?

4.3.4、 基于事件的網(wǎng)關(guān)

  • 描述:
    基于事件的網(wǎng)關(guān)(event-based gateway)提供了根據(jù)事件做選擇的方式。網(wǎng)關(guān)的每一條出口順序流都需要連接至一個捕獲中間事件。當流程執(zhí)行到達基于事件的網(wǎng)關(guān)時,與等待狀態(tài)類似,網(wǎng)關(guān)會暫停執(zhí)行,并且為每一條出口順序流創(chuàng)建一個事件訂閱。

>>> 基于事件的網(wǎng)關(guān)的出口順序流與一般的順序流不同。這些順序流從不實際執(zhí)行。相反,它們用于告知流程引擎:當執(zhí)行到達一個基于事件的網(wǎng)關(guān)時,需要訂閱什么事件。有以下限制:

  • 一個基于事件的網(wǎng)關(guān),必須有兩條或更多的出口順序流。
  • 基于事件的網(wǎng)關(guān),只能連接至intermediateCatchEvent(捕獲中間事件)類型的元素(Flowable不支持在基于事件的網(wǎng)關(guān)之后連接“接收任務(wù) Receive Task”)。
  • 連接至基于事件的網(wǎng)關(guān)的intermediateCatchEvent,必須只有一個入口順序流。
  • 圖示:
    基于事件的網(wǎng)關(guān),用內(nèi)部帶有特殊圖標的網(wǎng)關(guān)(菱形)表示。

  • xml表示:
    用于定義基于事件的網(wǎng)關(guān)的XML元素為eventBasedGateway。

  • 示例:
    下面是一個帶有基于事件的網(wǎng)關(guān)的示例流程。當執(zhí)行到達基于事件的網(wǎng)關(guān)時,流程執(zhí)行暫停。流程實例訂閱alert信號事件,并創(chuàng)建一個10分鐘后觸發(fā)的定時器。流程引擎會等待10分鐘,并同時等待信號事件。如果信號在10分鐘內(nèi)觸發(fā),則會取消定時器,流程沿著信號繼續(xù)執(zhí)行,激活Handle alert用戶任務(wù)。如果10分鐘內(nèi)沒有觸發(fā)信號,則會繼續(xù)執(zhí)行,并取消信號訂閱。

<definitions id="definitions"xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"xmlns:flowable="http://flowable.org/bpmn"targetNamespace="Examples"><signal id="alertSignal" name="alert" /><process id="catchSignal"><startEvent id="start" /><sequenceFlow sourceRef="start" targetRef="gw1" /><eventBasedGateway id="gw1" /><sequenceFlow sourceRef="gw1" targetRef="signalEvent" /><sequenceFlow sourceRef="gw1" targetRef="timerEvent" /><intermediateCatchEvent id="signalEvent" name="Alert"><signalEventDefinition signalRef="alertSignal" /></intermediateCatchEvent><intermediateCatchEvent id="timerEvent" name="Alert"><timerEventDefinition><timeDuration>PT10M</timeDuration></timerEventDefinition></intermediateCatchEvent><sequenceFlow sourceRef="timerEvent" targetRef="exGw1" /><sequenceFlow sourceRef="signalEvent" targetRef="task" /><userTask id="task" name="Handle alert"/><exclusiveGateway id="exGw1" /><sequenceFlow sourceRef="task" targetRef="exGw1" /><sequenceFlow sourceRef="exGw1" targetRef="end" /><endEvent id="end" /></process> </definitions>

?

4.4、任務(wù)

一個任務(wù)表示工作需要被外部實體完成, 比如人工或自動服務(wù)。

任務(wù)被描繪成一個圓角矩形,一般內(nèi)部包含文字。 任務(wù)的類型(用戶任務(wù),服務(wù)任務(wù),腳本任務(wù),等等)顯示在矩形的左上角,用小圖標區(qū)別。 根據(jù)任務(wù)的類型, 引擎會執(zhí)行不同的功能。

?

4.4.1、用戶任務(wù)

  • 描述:
    “用戶任務(wù)(user task)”,也叫人工任務(wù),見名知意,是用于對需要人工執(zhí)行的任務(wù)進行建模。當流程執(zhí)行到達用戶任務(wù)時,會為指派至該任務(wù)的用戶或組的任務(wù)列表創(chuàng)建一個新任務(wù)。

  • 圖示:
    用戶任務(wù)用左上角有一個小用戶圖標的標準任務(wù)(圓角矩形)表示。

  • xml表示:
    用戶任務(wù)在XML中如下定義。其中id是必須屬性,name是可選屬性。

<userTask id="theTask" name="Important task" />

也可以為用戶任務(wù)添加描述(description)。事實上任何BPMN 2.0元素都可以有描述。描述由documentation元素定義。

<userTask id="theTask" name="Schedule meeting" ><documentation>Schedule an engineering meeting for next week with the new hire.</documentation>
  • 到期日期
    每個任務(wù)都可以使用一個字段標志該任務(wù)的到期日期(due date)。可以使用查詢API,查詢在給定日期前或后到期的任務(wù)。
    可以在任務(wù)定義中使用擴展指定表達式,以在任務(wù)創(chuàng)建時設(shè)定到期日期。該表達式必須解析為java.util.Date,java.util.String (ISO8601格式),ISO8601時間長度(例如PT50M),或者null。例如,可以使用在流程里前一個表單中輸入的日期,或者由前一個服務(wù)任務(wù)計算出的日期。如果使用的是時間長度,則到期日期基于當前時間加上給定長度計算。例如當dueDate使用“PT30M”時,任務(wù)在從現(xiàn)在起30分鐘后到期。
<userTask id="theTask" name="Important task" flowable:dueDate="${dateVariable}"/>

任務(wù)的到期日期也可以使用TaskService,或者在TaskListener中使用傳遞的DelegateTask修改。

  • 用戶指派:
    用戶任務(wù)可以直接指派(assign)給用戶。可以定義humanPerformer子元素來實現(xiàn)。humanPerformer需要resourceAssignmentExpression來實際定義用戶。目前,只支持formalExpressions。
<process >...<userTask id='theTask' name='important task' ><humanPerformer><resourceAssignmentExpression><formalExpression>kermit</formalExpression></resourceAssignmentExpression></humanPerformer></userTask>

只能指定一個用戶作為任務(wù)的humanPerformer。在Flowable術(shù)語中,這個用戶被稱作辦理人(assignee)。擁有辦理人的任務(wù),在其他人的任務(wù)列表中不可見,而只能在該辦理人的個人任務(wù)列表中看到。

可以通過TaskService獲取特定用戶辦理的任務(wù):

List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();

任務(wù)也可以放在用戶的候選任務(wù)列表中。在這個情況下,需要使用potentialOwner(潛在用戶)結(jié)構(gòu)。用法與humanPerformer結(jié)構(gòu)類似。請注意需要指定表達式中的每一個元素為用戶還是組(引擎無法自行判斷)。

<process >...<userTask id='theTask' name='important task' ><potentialOwner><resourceAssignmentExpression><formalExpression>user(kermit), group(management)</formalExpression></resourceAssignmentExpression></potentialOwner></userTask>

可用如下方法獲取定義了potentialOwner結(jié)構(gòu)的任務(wù):

List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");

將獲取所有kermit作為候選用戶的任務(wù),也就是說,表達式含有user(kermit)的任務(wù)。同時也將獲取所有指派給kermit為其成員的組的任務(wù)(例如,kermit時management組的成員,且任務(wù)指派給management組)。組在運行時解析,并可通過身份服務(wù)管理。

如果并未指定給定字符串是用戶還是組,引擎默認其為組。下列代碼與聲明group(accountancy)效果一樣。

<formalExpression>accountancy</formalExpression>
  • 用于任務(wù)指派的Flowable擴展
    很明顯,當指派關(guān)系不復(fù)雜時,這種用戶與組的指派方式十分笨重。為避免這種復(fù)雜性,可以在用戶任務(wù)上使用自定義擴展。

  • assignee(辦理人)屬性:這個自定義擴展用于直接將用戶指派至用戶任務(wù)。
<userTask id="theTask" name="my task" flowable:assignee="kermit" />

與上面定義的humanPerformer結(jié)構(gòu)效果完全相同。

  • candidateUsers(候選用戶)屬性:這個自定義擴展用于為任務(wù)指定候選用戶。
<userTask id="theTask" name="my task" flowable:candidateUsers="kermit, gonzo" />

與使用上面定義的potentialOwner結(jié)構(gòu)效果完全相同。請注意不需要像在potentialOwner中一樣,使用user(kermit)的聲明,因為這個屬性只能用于用戶。

  • candidateGroups(候選組)attribute:這個自定義擴展用于為任務(wù)指定候選組。
<userTask id="theTask" name="my task" flowable:candidateGroups="management, accountancy" />

與使用上面定義的potentialOwner結(jié)構(gòu)效果完全相同。請注意不需要像在potentialOwner中一樣,使用group(management)的聲明,因為這個屬性只能用于組。

  • 可以定義在一個用戶任務(wù)上同時定義candidateUsers與candidateGroups。

?

4.4.2、腳本任務(wù)

  • 描述:
    腳本任務(wù)(Script Task)是一個自動化任務(wù)。當流程到達腳本任務(wù)時,自動執(zhí)行編寫的腳本,完畢后繼續(xù)執(zhí)行后繼路線。

  • 圖示:
    腳本任務(wù)用左上角有一個小“腳本”圖標的標準BPMN 2.0任務(wù)(圓角矩形)表示。

  • xml表示:
    腳本任務(wù)使用script與scriptFormat元素定義。

<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy"><script>sum = 0for ( i in inputArray ) {sum += i}</script> </scriptTask>

scriptFormat屬性的值,必須是兼容JSR-223(Java平臺腳本)的名字。默認情況下,JavaScript包含在每一個JDK中,因此不需要添加任何JAR文件。如果想使用其它(兼容JSR-223的)腳本引擎,則需要在classpath中添加相應(yīng)的jar,并使用適當?shù)拿帧@?#xff0c;Flowable單元測試經(jīng)常使用Groovy,因為其語法與Java十分相似。

請注意Groovy腳本引擎與groovy-all JAR捆綁在一起。在Groovy 2.0版本以前,腳本引擎是Groovy JAR的一部分。因此,必須添加如下依賴:

<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-all</artifactId><version>2.x.x<version> </dependency>
  • 腳本中的變量:
    到達腳本引擎的執(zhí)行中,所有的流程變量都可以在腳本中使用。在這個例子里,腳本變量'inputArray'實際上就是一個流程變量(一個integer的數(shù)組)。
<script>sum = 0for ( i in inputArray ) {sum += i} </script>

也可以簡單地調(diào)用execution.setVariable("variableName", variableValue),在腳本中設(shè)置流程變量。默認情況下,變量不會自動儲存(請注意,在一些早期版本中是會儲存的!)。可以將scriptTask的autoStoreVariables參數(shù)設(shè)置為true,以自動保存任何在腳本中定義的變量(例如上例中的sum)。

<scriptTask id="script" scriptFormat="JavaScript" flowable:autoStoreVariables="false">

這個參數(shù)的默認值為false。也就是說如果在腳本任務(wù)定義中忽略這個參數(shù),則腳本聲明的所有變量將只在腳本執(zhí)行期間有效。

在腳本中設(shè)置變量的例子:

<script>def scriptVar = "test123"execution.setVariable("myVar", scriptVar) </script>

>>> 下列名字是保留字,不能用于變量名:out,out:print,lang:import,context,elcontext。

  • 腳本任務(wù)的結(jié)果:
    腳本任務(wù)的返回值,可以通過為腳本任務(wù)定義的'flowable:resultVariable'屬性設(shè)置為流程變量。可以是已經(jīng)存在的,或者新的流程變量。如果指定為已存在的流程變量,則流程變量的值會被腳本執(zhí)行的結(jié)果值覆蓋。如果不指定結(jié)果變量名,則腳本結(jié)果值將被忽略。
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" flowable:resultVariable="myVar"><script>#{echo}</script> </scriptTask>

在上面的例子中,腳本執(zhí)行的結(jié)果(解析表達式'#{echo}'的值),將在腳本完成后,設(shè)置為名為'myVar'的流程變量。

?

4.4.3、服務(wù)任務(wù)

服務(wù)任務(wù)(Service Task)是一個自動化任務(wù)。當流程到達系統(tǒng)任務(wù)時,它會調(diào)用一些服務(wù)(例如web service,java service等等),完畢后繼續(xù)執(zhí)行后繼路線。

?

4.4.3.1、Java服務(wù)任務(wù)

  • 描述:
    Java服務(wù)任務(wù)(Java service task)用于調(diào)用Java類。

  • 圖示:
    服務(wù)任務(wù)用左上角有一個小齒輪圖標的圓角矩形表示。

  • xml表示:

有四種方法聲明如何調(diào)用Java邏輯:

  • 指定實現(xiàn)了JavaDelegate或ActivityBehavior的類
  • 調(diào)用解析為委托對象(delegation object)的表達式
  • 調(diào)用方法表達式(method expression)
  • 對值表達式(value expression)求值

使用flowable:class屬性提供全限定類名(fully qualified classname),指定流程執(zhí)行時調(diào)用的類。

<serviceTask id="javaService"name="My Java Service Task"flowable:class="org.flowable.MyJavaDelegate" />

也可以使用解析為對象的表達式。該對象必須遵循的規(guī)則,與使用flowable:class創(chuàng)建的對象規(guī)則相同。

<serviceTask id="serviceTask" flowable:delegateExpression="${delegateExpressionBean}" />

delegateExpressionBean是一個實現(xiàn)了JavaDelegate接口的bean,定義在Spring容器中。

使用flowable:expression屬性指定需要計算的UEL方法表達式。

<serviceTask id="javaService"name="My Java Service Task"flowable:expression="#{printer.printMessage()}" />

將在名為printer的對象上調(diào)用printMessage方法(不帶參數(shù))。

也可以為表達式中使用的方法傳遞變量。

<serviceTask id="javaService"name="My Java Service Task"flowable:expression="#{printer.printMessage(execution, myVar)}" />

將在名為printer的對象上調(diào)用printMessage方法。傳遞的第一個參數(shù)為DelegateExecution,名為execution,在表達式上下文中默認可用。傳遞的第二個參數(shù),是當前執(zhí)行中,名為myVar變量的值。

可以使用flowable:expression屬性指定需要計算的UEL值表達式。

<serviceTask id="javaService"name="My Java Service Task"flowable:expression="#{split.ready}" />

會調(diào)用名為split的bean的ready參數(shù)的getter方法,getReady(不帶參數(shù))。該對象會被解析為執(zhí)行的流程變量或(如果可用的話)Spring上下文中的bean。

  • 實現(xiàn):

要實現(xiàn)可以在流程執(zhí)行中調(diào)用的類,需要實現(xiàn)org.flowable.engine.delegate.JavaDelegate接口,并在execute方法中提供所需邏輯。當流程執(zhí)行到達該活動時,會執(zhí)行方法中定義的邏輯,并按照BPMN 2.0的默認方法離開活動。

下面是一個Java類的示例,用于將流程變量String改為大寫。這個類需要實現(xiàn)org.flowable.engine.delegate.JavaDelegate接口,因此需要實現(xiàn)execute(DelegateExecution)方法。這個方法就是引擎將調(diào)用的方法,需要實現(xiàn)業(yè)務(wù)邏輯。可以通過DelegateExecution接口(點擊鏈接獲取該接口操作的詳細Javadoc)訪問流程實例信息,如流程變量等。

public class ToUppercase implements JavaDelegate {public void execute(DelegateExecution execution) {String var = (String) execution.getVariable("input");var = var.toUpperCase();execution.setVariable("input", var);}}
  • 服務(wù)任務(wù)的結(jié)果:
    服務(wù)執(zhí)行的返回值(僅對使用表達式的服務(wù)任務(wù)),可以通過為服務(wù)任務(wù)定義的'flowable:resultVariable'屬性設(shè)置為流程變量。可以是已經(jīng)存在的,或者新的流程變量。 如果指定為已存在的流程變量,則流程變量的值會被服務(wù)執(zhí)行的結(jié)果值覆蓋。 如果使用'flowable:useLocalScopeForResultVariable',則會將結(jié)果值設(shè)置為局部變量。 如果不指定結(jié)果變量名,則服務(wù)任務(wù)的結(jié)果值將被忽略。
<serviceTask id="aMethodExpressionServiceTask"flowable:expression="#{myService.doSomething()}"flowable:resultVariable="myVar" />

?

4.4.3.2、Web服務(wù)任務(wù)

  • 描述:
    Web服務(wù)任務(wù)(Web service task)用于同步地調(diào)用外部的Web服務(wù)。

  • 圖示:
    Web服務(wù)任務(wù)與Java服務(wù)任務(wù)圖標一樣。

  • xml表示:
    使用Web服務(wù)之前,需要導(dǎo)入其操作及復(fù)雜的類型。可以使用導(dǎo)入標簽(import tag)指向Web服務(wù)的WSDL,自動處理:
<import importType="http://schemas.xmlsoap.org/wsdl/"location="http://localhost:63081/counter?wsdl"namespace="http://webservice.flowable.org/" />

按照上面的聲明,Flowable會導(dǎo)入定義,但不會創(chuàng)建條目定義(item definition)與消息。如果需要調(diào)用一個名為’prettyPrint’的方法,則需要先為請求及回復(fù)消息創(chuàng)建對應(yīng)的消息與條目定義:

<message id="prettyPrintCountRequestMessage" itemRef="tns:prettyPrintCountRequestItem" /> <message id="prettyPrintCountResponseMessage" itemRef="tns:prettyPrintCountResponseItem" /><itemDefinition id="prettyPrintCountRequestItem" structureRef="counter:prettyPrintCount" /> <itemDefinition id="prettyPrintCountResponseItem" structureRef="counter:prettyPrintCountResponse" />

在聲明服務(wù)任務(wù)前,需要定義實際引用Web服務(wù)的BPMN接口與操作。基本上,是定義“接口”與所需的“操作”。對每一個操作都可以重復(fù)使用之前定義的“傳入”與“傳出”消息。例如,下面的聲明定義了“counter”接口及“prettyPrintCountOperation”操作:

<interface name="Counter Interface" implementationRef="counter:Counter"><operation id="prettyPrintCountOperation" name="prettyPrintCount Operation"implementationRef="counter:prettyPrintCount"><inMessageRef>tns:prettyPrintCountRequestMessage</inMessageRef><outMessageRef>tns:prettyPrintCountResponseMessage</outMessageRef></operation> </interface>

這樣就可以使用##WebService實現(xiàn),聲明Web服務(wù)任務(wù),并引用Web服務(wù)操作。

<serviceTask id="webService"name="Web service invocation"implementation="##WebService"operationRef="tns:prettyPrintCountOperation">

參考:

【1】:Flowable BPMN 用戶手冊 (v 6.3.0)
【2】:第 3 章 BPMN 2.0
【3】:BPMN 2.0 / Flowable
【4】:業(yè)務(wù)流程模型和標記法
【5】:BPMN2.0十分鐘就夠了
【6】:基于BPMN2.0的工作流(Workflow)
【7】:?AWS BPMN2 Event參考指南
【8】:【activiti 入門】activiti6.0的中間事件,包含信號事件(捕獲與拋出)
【9】:AWS BPMN2 Activity參考指南
【10】:AWS BPMN2 Gateway參考指南

總結(jié)

以上是生活随笔為你收集整理的Flowable学习笔记(二、BPMN 2.0-基础 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。