Flowable4-Flowable API


Process Engine API和服務(wù)

API是與Flowable進(jìn)行交互的最常見(jiàn)的方式. 最主要的就是 ProcessEngine, 從 ProcessEngine 中, 您可以獲取包含工作流程/BPM方法的各種服務(wù).

ProcessEngine和服務(wù)對(duì)象是線程安全的, 所以你可以保留對(duì)整個(gè)服務(wù)器的引用.

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();

ProcessEngines.getDefaultProcessEngine() 將在第一次被調(diào)用時(shí)初始化和構(gòu)建流程引擎, 并且總是返回相同的流程引擎. 正確創(chuàng)建和關(guān)閉所有流程引擎可以使用ProcessEngines.init()和完成ProcessEngines.destroy().

ProcessEngines 類將掃描所有 flowable.cfg.xmlflowable-context.xml 文件. 對(duì)于 flowable.cfg.xml 文件, 流程引擎將以典型的Flowable方式構(gòu)建:

ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()

對(duì)于所有的 flowable-context.xml 文件, 流程引擎都是以Spring的方式構(gòu)建的: 首先創(chuàng)建Spring應(yīng)用程序上下文, 然后從該應(yīng)用程序上下文獲取流程引擎.

RepositoryService 引擎工作時(shí)所需要的第一個(gè)服務(wù). 這項(xiàng)服務(wù)提管理流程倉(cāng)庫(kù)凭豪,例如部署最域,刪除驯绎,讀取流程資源等.

deployment 是Flowable引擎內(nèi)的包裝單位. deployment 可以包含多個(gè)BPMN 2.0 XML文件和任何其他資源. 包含在deployment 中的資源或文件選擇取決于開(kāi)發(fā)人員.

process definition 定義了一個(gè)流程中不同步驟的結(jié)構(gòu)和行為. 對(duì)于每個(gè)流程定義, 通常有許多實(shí)例同時(shí)運(yùn)行.

此外, 這項(xiàng)服務(wù)允許你:

  1. 查詢引擎已知的部署和流程定義.
  2. 暫停和激活整個(gè)部署或特定的流程定義. 暫停意味著不能對(duì)它們進(jìn)行下一步的操作, 而激活是相反的, 并且能夠再次進(jìn)行操作.
  3. 檢索各種資源, 例如引擎自動(dòng)生成的部署或流程中包含的文件.
  4. 檢索流程定義的POJO版本.

常用的流程定義文件擴(kuò)展名有:bpmn20.xml和bpmn. 流程定義的圖片一般用png格式.


RuntimeService

雖然 RepositoryService 主要是關(guān)于靜態(tài)信息, 但 RuntimeService 正好相反.

RuntimeService 主要用于管理流程在運(yùn)行時(shí)產(chǎn)生的數(shù)據(jù)(流程參數(shù), 事件, 流程實(shí)例, 以及執(zhí)行情況)以及對(duì)正在運(yùn)行的流程進(jìn)行操作的API.

系統(tǒng)用戶需要執(zhí)行的任務(wù)是Flowable等BPM引擎的核心. 而任務(wù)周圍的任務(wù)都被分組到TaskService中, 如:

  1. 查詢分配給用戶或組的任務(wù).
  2. 創(chuàng)建新的獨(dú)立任務(wù). 這些是與流程實(shí)例無(wú)關(guān)的任務(wù).
  3. 操作向哪個(gè)用戶分配任務(wù)或者哪個(gè)用戶以某種方式參與任務(wù).
  4. 聲稱和完成一項(xiàng)任務(wù). 聲稱意味著有人決參與任務(wù), 這也意味著該用戶將完成該任務(wù). 完成意味著完成任務(wù)的工作.

IdentityService

IdentityService是非常簡(jiǎn)單的. 它支持組和用戶的管理(創(chuàng)建, 更新,
刪除, 查詢).

Flowable實(shí)際上不會(huì)在運(yùn)行時(shí)對(duì)用戶進(jìn)行任何檢查. 例如, 可以將任務(wù)分配給任何用戶, 但是引擎不驗(yàn)證該用戶是否被系統(tǒng)知曉. 這是意味著Flowable引擎也可以與LDAP, Active Directory等服務(wù)結(jié)合使用.


FormService

FormService 是一個(gè)可選的服務(wù). 該服務(wù)引入了開(kāi)始表和任務(wù)表的概念. 開(kāi)始形式是流程實(shí)例啟動(dòng)前顯示給用戶的一種形式, 而任務(wù)形式是當(dāng)一個(gè)用戶要填寫(xiě)一份表的時(shí)候進(jìn)行顯示.


HistoryService

HistoryService 服務(wù)公開(kāi)有關(guān)正在進(jìn)行和歷史進(jìn)程實(shí)例的信息.

這與運(yùn)行時(shí)信息不同, 因?yàn)榇诉\(yùn)行時(shí)信息僅在任何特定時(shí)刻包含實(shí)際運(yùn)行時(shí)狀態(tài), 并且針對(duì)運(yùn)行時(shí)進(jìn)程執(zhí)行性能進(jìn)行了優(yōu)化. 歷史信息(誰(shuí)做了哪些任務(wù), 完成任務(wù)需要多長(zhǎng)時(shí)間, 每個(gè)流程實(shí)例遵循哪條路徑, 等等)經(jīng)過(guò)優(yōu)化, 易于查詢, 并且永久保存.


ManagementService

ManagementService 為流程引擎上的管理和維護(hù)操作提供服務(wù). 此外, 它還暴露了查詢功能和作業(yè)管理操作. 作業(yè)在Flowable中用于各種事情, 如定時(shí)器, 異步延續(xù), 延遲掛起/激活等等.


DynamicBpmnService

DynamicBpmnService 可以用來(lái)改變流程定義的一部分, 而無(wú)需重新部署. 例如, 可以在流程定義中更改用戶任務(wù)的受理人或者更改服務(wù)任務(wù)的類名稱.


異常

FlowableWrongDbException: 當(dāng)Flowable引擎發(fā)現(xiàn)數(shù)據(jù)庫(kù)模式版本和引擎版本之間不匹配時(shí)拋出.
FlowableOptimisticLockingException: 在同一數(shù)據(jù)項(xiàng)的并發(fā)訪問(wèn)導(dǎo)致數(shù)據(jù)存儲(chǔ)區(qū)發(fā)生樂(lè)觀鎖時(shí)拋出.
FlowableClassLoadingException: 當(dāng)沒(méi)有找到請(qǐng)求加載的類時(shí)或加載時(shí)發(fā)生錯(cuò)誤(例如JavaDelegates, TaskListeners, ...)時(shí)拋出.
FlowableObjectNotFoundException: 當(dāng)一個(gè)被請(qǐng)求或被執(zhí)行的對(duì)象不存在時(shí)拋出.
FlowableIllegalArgumentException: 表示在Flowable API調(diào)用中提供了非法參數(shù)的異常, 在引擎配置中配置了非法值, 或者提供了非法值,
或者在進(jìn)程定義中使用了非法值.
FlowableTaskAlreadyClaimedException: 當(dāng)一個(gè)任務(wù)已經(jīng)被聲明,taskService.claim(…?)被調(diào)用的時(shí)候拋出.


查詢API

查詢引擎有兩種方式: 查詢API和SQL查詢.

查詢API允許您使用API編程來(lái)安全的查詢. 您可以為查詢添加各種條件(所有這些條件都作為邏輯“與”一起應(yīng)用).以下代碼顯示了一個(gè)示例:

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("kermit")
    .processVariableValueEquals("orderId", "0815")
    .orderByDueDate().asc()
    .list();

有時(shí)您需要更強(qiáng)大的查詢, 例如使用 OR 運(yùn)算符的查詢或使用查詢API無(wú)法表達(dá)的約束.

對(duì)于這些情況, 我們有SQL查詢, 它允許您編寫(xiě)自己的SQL查詢. 返回類型由您使用的Query對(duì)象定義, 數(shù)據(jù)映射到正確的對(duì)象(Task, ProcessInstance, Execution, ...).

由于查詢將在數(shù)據(jù)庫(kù)中被觸發(fā), 因此必須使用數(shù)據(jù)庫(kù)中定義的表名和列名稱; 這需要一些有關(guān)內(nèi)部數(shù)據(jù)結(jié)構(gòu)的知識(shí), 建議小心使用SQL查詢. 表名可以通過(guò)API檢索, 以保持依賴性盡可能小.

List<Task> tasks = taskService.createNativeTaskQuery()
  .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) +
      " T WHERE T.NAME_ = #{taskName}")
  .parameter("taskName", "gonzoTask")
  .list();

long count = taskService.createNativeTaskQuery()
  .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, " +
      managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
  .count();

變量

每個(gè)流程實(shí)例都需要使用數(shù)據(jù)來(lái)執(zhí)行它所組成的步驟.

在Flowable中, 這個(gè)數(shù)據(jù)被稱為變量, 它們被存儲(chǔ)在數(shù)據(jù)庫(kù)中. 在調(diào)用外部服務(wù)時(shí), 變量可以用在表達(dá)式中(例如, 在專用網(wǎng)關(guān)中選擇正確的傳出序列流).

流程實(shí)例可以包含變量(稱為流程變量), 也可以包含執(zhí)行用戶任務(wù)時(shí)包含的變量. 一個(gè)流程實(shí)例可以有任意數(shù)量的變量. 每個(gè)變量都存儲(chǔ)在ACT_RU_VARIABLE數(shù)據(jù)庫(kù)表中的一行.

所有 startProcessInstanceXXX 方法都有一個(gè)可選參數(shù), 用于在創(chuàng)建和啟動(dòng)流程實(shí)例時(shí)提供變量.

ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);

變量可以在流程執(zhí)行過(guò)程中添加

void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);

變量也可以被檢索, 如下所示. 請(qǐng)注意, TaskService 上存在類似的方法. 這意味著任務(wù)(如執(zhí)行)可以具有僅在任務(wù)期間處于活動(dòng)狀態(tài)的局部變量.

Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);

瞬態(tài)變量

瞬態(tài)變量是像變量一樣的變量, 但不會(huì)被持久化.

以下內(nèi)容適用于瞬態(tài)變量:

  1. 對(duì)于瞬態(tài)變量沒(méi)有存儲(chǔ)歷史.
  2. 瞬態(tài)變量只能由setTransientVariable(name,value)設(shè)置, 但是在調(diào)用getVariable(name)時(shí)也會(huì)返回瞬態(tài)變量, 其原因是為了使表達(dá)式的寫(xiě)作變得容易, 并且使用變量的現(xiàn)有邏輯適用于這兩種類型.
  3. 一個(gè)瞬態(tài)變量會(huì)隱藏一個(gè)具有相同名稱的流程變量. 這意味著, 如果在流程實(shí)例上設(shè)置了流程變量和瞬態(tài)變量, 并調(diào)用getVariable("someVariable"), 則將返回瞬態(tài)變量值.
  4. 流程變量只能在流程定義中的下一個(gè)等待狀態(tài)之前被訪問(wèn). 這里, 等待狀態(tài)意就是流程實(shí)例中保存數(shù)據(jù)的點(diǎn).

您可以在常規(guī)變量暴露的大多數(shù)地方設(shè)置和獲取瞬態(tài)變量:

  1. DelegateExecution 在 JavaDelegate 實(shí)現(xiàn)
  2. DelegateExecution 在 ExecutionListener 實(shí)現(xiàn)和DelegateTask上的TaskListener實(shí)現(xiàn)
  3. 在通過(guò)執(zhí)行對(duì)象的腳本任務(wù)中
  4. 通過(guò)運(yùn)行時(shí)服務(wù)啟動(dòng)流程實(shí)例時(shí)
  5. 完成任務(wù)時(shí)
  6. 調(diào)用runtimeService.trigger方法時(shí)

表達(dá)式

Flowable使用UEL進(jìn)行表達(dá)式解析. UEL代表統(tǒng)一表達(dá)式語(yǔ)言(Unified Expression Language).
值表達(dá)式: 解析為一個(gè)值. 默認(rèn)情況下, 所有的過(guò)程變量都可以使用.

$ {myVar} 
$ {myBean.myProperty}

方法表達(dá)式: 調(diào)用帶或不帶參數(shù)的方法. 當(dāng)調(diào)用一個(gè)沒(méi)有參數(shù)的方法時(shí), 一定要在方法名之后加上空的圓括號(hào). 傳遞的參數(shù)可以是字面值或自己解析的表達(dá)式.

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

在所有的流程變量之上, 有幾個(gè)可以在表達(dá)式中使用的默認(rèn)對(duì)象:
execution: DelegateExecution 持有關(guān)于持續(xù)執(zhí)行的附加信息.
task: DelegateTask持有關(guān)于當(dāng)前任務(wù)的附加信息. 注意: 只適用于任務(wù)監(jiān)聽(tīng)器評(píng)估的表達(dá)式.
authenticatedUserId: 當(dāng)前通過(guò)身份驗(yàn)證的用戶的ID. 如果沒(méi)有用戶通過(guò)身份驗(yàn)證, 該變量不可用.


Web應(yīng)用程序中的流程引擎

這個(gè) ProcessEngine 是一個(gè)線程安全的類, 可以很容易地在多個(gè)線程之間共享. 在Web應(yīng)用程序中, 這意味著可以在容器啟動(dòng)時(shí)創(chuàng)建一次流程引擎坊萝,并在容器關(guān)閉時(shí)關(guān)閉引擎.

下面的代碼片斷展示了如何編寫(xiě)一個(gè)簡(jiǎn)單的 ServletContextListener 在簡(jiǎn)單的Servlet環(huán)境中初始化和銷毀??流程引擎:

public class ProcessEnginesServletContextListener implements ServletContextListener {

  public void contextInitialized(ServletContextEvent servletContextEvent) {
    ProcessEngines.init();
  }

  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ProcessEngines.destroy();
  }

}

contextInitialized 方法將委托給 ProcessEngines.init(). 這將 flowable.cfg.xml 在類路徑中查找資源文件, 并創(chuàng)建一個(gè)ProcessEngine . 如果在類路徑中有多個(gè)這樣的資源文件, 請(qǐng)確保它們都有不同的名稱.

當(dāng)需要流程引擎時(shí), 可以使用以下方法獲取流程引擎:

ProcessEngines.getDefaultProcessEngine()

ProcessEngines.getProcessEngine("myName");
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枕磁,一起剝皮案震驚了整個(gè)濱河市造挽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌褐荷,老刑警劉巖勾效,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異叛甫,居然都是意外死亡层宫,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)合溺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)卒密,“玉大人,你說(shuō)我怎么就攤上這事棠赛∠妫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵睛约,是天一觀的道長(zhǎng)鼎俘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)辩涝,這世上最難降的妖魔是什么贸伐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮怔揩,結(jié)果婚禮上捉邢,老公的妹妹穿的比我還像新娘。我一直安慰自己商膊,他們只是感情好伏伐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著晕拆,像睡著了一般藐翎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上实幕,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天吝镣,我揣著相機(jī)與錄音,去河邊找鬼昆庇。 笑死末贾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凰锡。 我是一名探鬼主播未舟,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼圈暗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了裕膀?” 一聲冷哼從身側(cè)響起员串,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昼扛,沒(méi)想到半個(gè)月后寸齐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抄谐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年渺鹦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛹含。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡毅厚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浦箱,到底是詐尸還是另有隱情吸耿,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布酷窥,位于F島的核電站咽安,受9級(jí)特大地震影響寺董,放射性物質(zhì)發(fā)生泄漏悬垃。R本人自食惡果不足惜热监,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一坡贺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莫湘,春花似錦哄尔、人聲如沸振愿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至留特,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玛瘸,已是汗流浹背蜕青。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留糊渊,地道東北人右核。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渺绒,于是被迫代替她去往敵國(guó)和親贺喝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子菱鸥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)躏鱼,斷路器氮采,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法染苛,內(nèi)部類的語(yǔ)法鹊漠,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法茶行,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,639評(píng)論 18 399
  • 昌平鄭各莊記錄了清朝唯一一個(gè)太子的最后時(shí)光躯概,見(jiàn)證了清朝唯一一座不在內(nèi)城的王府興衰,還流傳著一段令三位皇帝頭疼的煙云...
    GordonTJ閱讀 317評(píng)論 0 1
  • 2016年因自己宮寒太嚴(yán)重引起的痛經(jīng)畔师,腿冷腰疼等癥狀娶靡,以前也用過(guò)很多方法去治療,結(jié)果都是不怎么樣看锉,當(dāng)去年10月接觸...
    小小小龐閱讀 314評(píng)論 0 1
  • 后來(lái)我常常反思人生重要關(guān)口我自己的選擇度陆,我為什么要做出這樣的抉擇艾凯?也許答案就埋伏在我小學(xué)畢業(yè)時(shí)那個(gè)炎炎夏季...
    emma歲月靜好閱讀 231評(píng)論 0 0