camunda之-bpmn-消息事件(Message Events)

消息事件(Message Event):

  • 消息事件是一個引用了被命名的消息的事件
  • 一個消息有一個名稱和對應的消息負載
  • 與信號不一樣据沈,消息事件始終指向單一的接收人
  • 消息支持表達式,例如:<message id="messageId" name="name-${execution.processBusinessKey}" />這樣就會動態(tài)的從流程參數(shù)中去獲取到對應的值,并解析消息名稱
  • 消息開始事件名稱不支持表達式拾因,但是子流程的消息開始事件是支持表達式的

一、消息的API(Message Api):

  • 1.作為一個內嵌的流程引擎(Camunda engine)壳坪,camunda不關心消息接收的部分识藤。消息接收部分依賴于流程引擎所在的環(huán)境,并且需要平臺特殊活動咳秉,例如:連接到JMS的隊列/主題(Topic),或者一個web服務鸯隅,或者一個rest請求澜建,所以接收消息是用戶需要去實現(xiàn)的部分即:用戶自己實現(xiàn)從哪里接收消息,mq或者web服務或者rest接口蝌以。接到消息后炕舵,你可以選擇關聯(lián)到觸發(fā)一個新的流程實例,或者觸發(fā)一個等待的執(zhí)行(execution)
  • 2.使用運行時服務(Runtime Service’s )關聯(lián)消息和流程實例的方法:
    ????- 流程引擎(Camunda engine)提供了一個基本的關聯(lián)消息和流程實例的機制饼灿,這會通知(signal)一個等待特殊消息的執(zhí)行(execution幕侠,即:消息中間事件),或者用匹配的消息開始事件實例化一個流程碍彭,RuntimeService提供了流式消息管理API
  • 3.關聯(lián)消息的結果是一個MessageCorrelationResult對象晤硕,不管是一個execution或者是一個processDefinition。如果是一個execution庇忌,則消息關聯(lián)的是一個捕獲消息中間事件(intermediate message catch event)舞箍,如果是一個processDefinition,則消息關聯(lián)的是一個消息開始事件皆疹。如果是execution疏橄,則可以通過result.getExecution(),獲取Execution略就,如果是processDefinition則可以通過result.getProcessInstance()來獲取ProcessInstance捎迫。
  • 4.你可以通過messageName和businessKey來直接觸發(fā)關聯(lián),也可以明確的查詢出這個subscription(subscription:大意是消息事件創(chuàng)建的一個event subscription)來進行觸發(fā)
// 通過messageName和businessKey來直接觸發(fā)關聯(lián)(開始一個流程)
MessageCorrelationResult result = runtimeService.createMessageCorrelation("messageName")
  .processInstanceBusinessKey("AB-123")
  .setVariable("payment_type", "creditCard")
  .correlateWithResult();
ProcessInstance pi = runtimeService.startProcessInstanceByKey("processWaitingInReceiveTask");
// 注釋:messageName標識是定義在bpmn流程圖的xml文件中的name屬性中的
// 關聯(lián)成功后只會返回Process Definition或者Execution (Process Instance)中的一個

//明確的查詢出這個subscription(subscription:大意是消息事件創(chuàng)建的一個event subscription表牢,即:觸發(fā)一個消息中間事件)來進行觸發(fā)
EventSubscription subscription = runtimeService.createEventSubscriptionQuery()
  .processInstanceId(pi.getId())
  .eventType("message")
  .singleResult();
runtimeService.messageEventReceived(subscription.getEventName(), subscription.getExecutionId());
  • 5.使用一個messageName關聯(lián)一個消息到多個匹配的executions窄绒,觸發(fā)消息中間事件,或者實例化多個流程實例(批量操作):
List<MessageCorrelationResult> results = runtimeService
  .createMessageCorrelation("aMessageName")
  .correlateAllWithResult();
  • 6.在發(fā)起一個流程時崔兴,還可以獲取到流程參數(shù)彰导,通過一個布爾參數(shù)shouldDeserializeValues指定是否獲取
MessageCorrelationResultWithVariables result = runtimeService
  .createMessageCorrelation("aMessageName")
  .setVariable("name", "value")
  .correlateWithResultAndVariables(shouldDeserializeValues);
//流程參數(shù)
VariableMap processVariables = result.getVariables();
  • 7.還提供了通過本地執(zhí)行參數(shù)(local execution variables)關聯(lián)消息的能力,所謂local execution variables是指的當前作用域蛔翅,我的理解是當前流程實例,例如當前在子流程里位谋,就使用的子流程的變量山析,不會涉及到父流程的變量
List<MessageCorrelationResult> results = runtimeService
  .createMessageCorrelation("aMessageName")
  .localVariableEquals("localVarName", "localVarValue"))
  .correlateAllWithResult();
  • 8.顯示的觸發(fā)一個消息(Explicitly Triggering a Message)
//觸發(fā)一個消息開始事件
ProcessInstance startedProcessInstance = runtimeService
  .createMessageCorrelation("messageName")
  .processInstanceBusinessKey("businessKey")
  .setVariable("name", "value")
  .correlateStartMessage();
// or
MessageCorrelationResultWithVariables result = runtimeService
  .createMessageCorrelation("aMessageName")
  .processInstanceBusinessKey("businessKey")
  .startMessageOnly()
  .setVariable("name", "value")
  .correlateWithResultAndVariables(shouldDeserializeValues);
ProcessInstance startedProcessInstance = result.getProcessInstance();
VariableMap processVariables = result.getVariables();
//or
ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);
//觸發(fā)消息中間事件
void messageEventReceived(String messageName, String executionId);
void messageEventReceived(String messageName, String executionId, HashMap<String, Object> processVariables);
  • 9.查詢消息事件訂閱(Querying for Message Event Subscriptions:在進行中的消息事件的訂閱,在ACT_RU_EVENT_SUBSCR表中):
    ????- 這個查詢支持消息開始事件和消息中間事件
    ????- 如果是消息開始事件掏父,這個消息事件的訂閱與一個特殊的流程定義笋轨,這個消息訂閱可以用ProcessDefinitionQuery查詢
//消息開始事件,查詢流程定義信息
Execution execution = runtimeService.createExecutionQuery()
  .messageEventSubscriptionName("paymentReceived")
  .processVariableValueEquals("orderId", message.getOrderId())
  .singleResult();

????- 這個查詢只會返回null或者一個流程定義赊淑,如果流程定義發(fā)布了新的版本翩腐,會返回最新版本的流程定義
????- 如果是消息中間事件,會返回一個特定的execution膏燃,這個消息訂閱可以用ExecutionQuery查詢

Execution execution = runtimeService.createExecutionQuery()
  .messageEventSubscriptionName("paymentReceived")
  .processVariableValueEquals("orderId", message.getOrderId())
  .singleResult();

二、消息開始事件(Message Start Event):

  • 消息開始事件可以用作何什,通過一個被命名的消息來開始一個流程實例组哩。這允許我們在一堆的開始事件中選擇正確的開始事件發(fā)起流程
  • 當我們部署一個流程定義,且這個流程定義有一個或多個消息開始事件時处渣,我們要注意以下幾方面:
    ????1.在同一個流程定義中伶贰,不允許存在多個name相同的消息開始事件(例如:離職流程的流程定義中,不允許存在相同name的消息開始事件)
    ????2.在所有的部署的流程定義中罐栈,消息開始事件的name也必須是唯一(例如:離職流程和轉正流程中黍衙,不允許存在相同name的消息開始事件)
    ????3.根據(jù)部署的最新版本的流程定義,之前版本的消息訂閱(部署成功的消息訂閱荠诬,即:老版本的流程定義中的消息開始事件會被取消琅翻,不會跟新版本并行監(jiān)聽消息來發(fā)起流程)將會被取消掉,新版本中沒有出現(xiàn)的消息事件也會被取消
  • 可以用RuntimeService的下列方法柑贞,通過觸發(fā)消息開始事件來開始一個流程:
ProcessInstance startProcessInstanceByMessage(String messageName);
ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);

注釋:
???? 1.messageName是由bpmn的xml文件中的messageEventDefinition元素的messageRef屬性引用的消息元素的name屬性中給出的名稱
???? 2.在啟動流程實例時方椎,需要注意一下幾個問題:
???????? - 消息開始事件只支持最外層的流程,不支持子流程钧嘶,子流程可以用空開始事件
???????? - 如果流程定義有多個消息開始事件棠众,runtimeService.startProcessInstanceByMessage(...)會選擇一個合適的消息開始事件(根據(jù)messageName來確定正常的消息開始事件)
???????? - 如果流程有多個消息開始事件和一個空開始事件,runtimeService.startProcessInstanceByKey(...)和runtimeService.startProcessInstanceById(...)會用空開始事件開始一個流程實例
???????? - 如果流程有多個消息開始事件有决,且沒有空開始事件闸拿,則runtimeService.startProcessInstanceByKey(...)和runtimeService.startProcessInstanceById(...)會拋出異常
???????? - 如果流程只有一個消息開始事件, runtimeService.startProcessInstanceByKey(...)和runtimeService.startProcessInstanceById(...)會通過消息開始事件開始一個流程
???????? - 如果流程是被調用活動開始的书幕,那么消息開始事件只在一下兩種情況下支持:
???????????? 1. 除了消息開始事件之外新荤,流程還有一個空開始事件
???????????? 2.流程只有一個消息開始事件

  • 一個流程可以被多個不同的消息事件發(fā)起,這對于那些需要不同的方式發(fā)起流程按咒,卻最終會以統(tǒng)一的方式運行的流程非常有用


    圖1:多個消息開始事件發(fā)起流程圖

三迟隅、消息中間捕獲事件(Message Intermediate Catching Event):

  • 當一個流程到達消息中間捕獲事件時但骨,它會等待在這里,直到一個有正確name的消息到達智袭,流程才會繼續(xù)往下走


    圖2:消息中間事件和消息邊界事件

四奔缠、消息邊界事件(Message Boundary Event):

  • 邊界事件是一個捕獲事件,它是依賴一個活動(activity吼野,見上圖2的完成訂單的活動)校哎,這意味著,當這個活動是在運行狀態(tài)下瞳步,這個消息邊界事件在監(jiān)聽著一個被命名的消息闷哆,當消息到達后,有兩種情況单起,這兩種情況取決于于邊界事件的配置(中斷消息邊界事件和不中斷消息邊界事件):
    ???? 1.中斷消息邊界事件抱怔,以圖2為例:當消息邊界事件接收到消息被觸發(fā)后,完成訂單的活動(activity)被中斷
    ???? 2.不中斷消息邊界事件:以圖3為例:當不中斷消息邊界事件接收到消息被觸發(fā)后嘀倒,完成訂單的活動和處理訂單取消的活動同時處于running狀態(tài)


    圖3:不中斷消息邊界事件

五屈留、消息中間拋出事件(Message Intermediate Throwing Event):

  • 消息中間拋出事件會向外部服務發(fā)送一個消息,消息中間拋出事件的這個行為跟Service Task類似


    圖4:消息中間拋出事件

六测蘑、消息結束事件(Message End Event):

  • 當流程執(zhí)行到消息結束事件時灌危,當前路徑下的執(zhí)行結束,并且會發(fā)送一條消息碳胳,這個發(fā)消息的行為跟Service Task類似


    圖5:消息結束事件
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末勇蝙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子挨约,更是在濱河造成了極大的恐慌味混,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烫罩,死亡現(xiàn)場離奇詭異惜傲,居然都是意外死亡荚孵,警方通過查閱死者的電腦和手機玲昧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門芯侥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莲兢,“玉大人承璃,你說我怎么就攤上這事落恼×棵唬” “怎么了慢显?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵梨熙,是天一觀的道長开镣。 經(jīng)常有香客問我,道長咽扇,這世上最難降的妖魔是什么邪财? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任陕壹,我火速辦了婚禮,結果婚禮上树埠,老公的妹妹穿的比我還像新娘糠馆。我一直安慰自己,他們只是感情好怎憋,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布又碌。 她就那樣靜靜地躺著,像睡著了一般绊袋。 火紅的嫁衣襯著肌膚如雪毕匀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天癌别,我揣著相機與錄音皂岔,去河邊找鬼。 笑死展姐,一個胖子當著我的面吹牛凤薛,可吹牛的內容都是我干的。 我是一名探鬼主播诞仓,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼速兔!你這毒婦竟也來了墅拭?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤涣狗,失蹤者是張志新(化名)和其女友劉穎谍婉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體镀钓,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡穗熬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了丁溅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唤蔗。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窟赏,靈堂內的尸體忽然破棺而出妓柜,到底是詐尸還是另有隱情,我是刑警寧澤涯穷,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布棍掐,位于F島的核電站,受9級特大地震影響拷况,放射性物質發(fā)生泄漏作煌。R本人自食惡果不足惜掘殴,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粟誓。 院中可真熱鬧奏寨,春花似錦、人聲如沸努酸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽获诈。三九已至仍源,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舔涎,已是汗流浹背笼踩。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亡嫌,地道東北人嚎于。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像挟冠,于是被迫代替她去往敵國和親于购。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349