Osworkflow完全用java語言編寫的開放源代碼的工作流引擎,具有顯著的靈活性及完全面向有技術(shù)
背景的用戶的特點。用戶可以根據(jù)自身的需求利用這款開源軟件設計簡單或是復雜的工作流。通過使用,用戶就可以把工作中心放在業(yè)務和規(guī)則的定義上,而不需通
過硬編碼的方式實現(xiàn)一個Petri網(wǎng)或是一個有窮自動機。用戶可以以最小的代價把osworkflow整合到自己的程序中來。Osworkflow幾乎提
供了所有用戶可能在實際流程定義中需要用到的工作流構(gòu)成元素,如:環(huán)節(jié)(step)、條件(conditions)、循環(huán)(loops)、分支
(spilts)、合并(joins)、角色(roles)等等。(假如讀者對這些概念還不熟悉,筆者將在Osworkflow基本概念一節(jié)中進行簡單描
述。)
但是,這款開源軟件的文檔十分匱乏,而且在大多數(shù)現(xiàn)實情形中并不適用。本文將嘗試為讀者填平實際的用例需求與十分簡單的說明文檔間的鴻溝。
用戶可以在OpenSymphony的網(wǎng)站上下載osworkflow的發(fā)布。當前的最高版本是2.7(譯者注:最新版本為2.8). 解壓縮發(fā)布的軟件包,即得到二進制程序、源代碼、API文檔、說明文檔等。用戶可以在軟件的論壇和維基上獲得進一步的幫助。
版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時請務必保留以下作者信息和鏈接
作者:Diego Naya;bugaboo(作者的blog:http://blog.matrix.org.cn/page/bugaboo)
Matrix原文:http://www.matrix.org.cn/resource/article/44/44467_osworkflow.html
關(guān)鍵字:osworkflow;business
什么是工作流?
維基百科(Wikipedia,WP)把工作流定義為“一份工作的操作過程”:任務如何組成、如何操作、相關(guān)順序如何、如何同步、信息如何流動以支持這些任務、以及任務如何被跟蹤等。
一個工作流引擎實現(xiàn)了業(yè)務的流程處理。用戶應可以自動跟蹤過程,這將使得引擎更具效率。同時用戶可以對工作流進行建模,監(jiān)控及統(tǒng)計引擎數(shù)據(jù)等。
示例業(yè)務過程:貸款程序
本
文的示例業(yè)務過程研究一個貸款應用程序的實例。我們將通過一個利用osworkflow工作流引擎的工作流來實現(xiàn)它。這個過程會在每家銀行及金融機構(gòu)中出
現(xiàn), 其區(qū)別僅僅體現(xiàn)為有更過的部門或更多地文檔需要處理. 在本示例中,
我們會用盡量簡單的方法來實現(xiàn)這個業(yè)務流程以便于用戶理解。圖一描述了這個業(yè)務流程

圖一 貸款業(yè)務流程
過程非常簡單,分為如下4步,如下所示:
1)????????填寫表格:銀行客戶填寫表格申請貸款。
2)????????風險分析:一位風險分析家評估不良貸款的風險。
3)????????財務歷史審查:財務管理官員負責檢查客戶歷史貸款、應付賬單、信用卡歷史紀錄等信息。
4)????????最終決定(同意/拒絕):銀行部門主管根據(jù)風險分析情況及財務歷史審查情況最終決定是否貸款給該客戶。
正如我們之前看到的,每個工作流都包含角色,每個角色都包含被分配的任務。下文說明了業(yè)務流程中涉及到的角色:
1)????????前臺職員:在某個銀行部門向顧客提供信貸申請表的雇員。
2)????????財務官員:負責檢查申請者歷史財務情況(往期貸款、未支付帳單等等)的職員。
3)????????風險分析家:負責分析將錢給予借貸申請者的外部因素(比如社會經(jīng)濟情況等)及借貸者本人的個人情況。
4)????????銀行部門經(jīng)理:負責最終決定是否給予借貸者貸款的經(jīng)理。
請記住,“信貸申請表”是一個重要的概念(我們將在系統(tǒng)實現(xiàn)一節(jié)看到其重要性)因為它是流經(jīng)整個工作流的業(yè)務數(shù)據(jù)。
基本工作流概念
筆者在開篇曾介紹osworkflow提供了一些特有的構(gòu)造,現(xiàn)在筆者將逐一介紹它們。
首
先,在osworkflow中讀者需要了解得最重要的概念是環(huán)節(jié),每個工作流包含了多個環(huán)節(jié),讀者可以把環(huán)節(jié)想象成工作流中每一個重要的活動。每個環(huán)節(jié)可
以有一些諸如“已完成”、“正在處理”、“已添加至處理隊列”、“未處理”等的狀態(tài),設計工作流的人可以根據(jù)需要自己定義狀態(tài)。
在每個環(huán)節(jié),動作被用戶指定為自動或手動地執(zhí)行。每個動作執(zhí)行后,都有一個結(jié)果(result)。結(jié)果決定了工作流的流轉(zhuǎn)方向:可以停留在同一環(huán)節(jié),跳轉(zhuǎn)到另一環(huán)節(jié),跳轉(zhuǎn)到一個分支,或者匯集到一個合并等。
最后兩個概念涉及用戶對業(yè)務流程的并發(fā)執(zhí)行,分支把工作流分解為兩個并行的環(huán)節(jié),合并則在用戶滿足一定條件后,把兩個并行的環(huán)節(jié)合并成一個。
動
作的執(zhí)行代表了業(yè)務流程的執(zhí)行,每個動作都有一組預處理功能(pre-functions)和一組后處理功能(post-functions)。其作用正
如讀者想象的那樣,一個在動作觸發(fā)之前執(zhí)行,一個在動作觸發(fā)之后執(zhí)行。一個簡單的例子是:可以在預處理功能中檢驗申請表格數(shù)據(jù)的正確性,而后在后處理貢功
能中把經(jīng)檢驗的數(shù)據(jù)保存至數(shù)據(jù)庫。
動作的執(zhí)行結(jié)果可以是有條件的(conditional)或無條件的(unconditional)。
對于有條件的結(jié)果,引擎將首先檢查是否條件被滿足,然后再交給工作流來處理。如果條件不滿足的話,引擎將進一步判斷下一個有條件結(jié)果是否得到滿足,以此類
推,直到系統(tǒng)最終執(zhí)行到無條件結(jié)果進行處理。
讀者可能會問,如果所有的條件結(jié)果都沒有得到滿足會如何呢?事實上,每個動作都強制要求具有唯一一個無條件結(jié)果。與此對應的,可以有多個有條件的結(jié)果。
業(yè)務規(guī)則常常在最終結(jié)果中帶有條件判斷,比如,“如果申請來自于一個老客戶,則流轉(zhuǎn)到環(huán)節(jié)1”或者“如果當前系統(tǒng)的用戶的角色是經(jīng)理的話,直接流轉(zhuǎn)道最后一個環(huán)節(jié)”。
最
后一個重要的概念是步驟狀態(tài)(process
state),在osworkflow中,當前步驟狀態(tài)是所有當前環(huán)節(jié)狀態(tài)的集合。讀者可能會認為工作流在運行過程中只能有一個狀態(tài),但現(xiàn)實的情況是:因
為對分支和合并的支持,引擎能夠做到對環(huán)節(jié)的并發(fā)控制,因此工作流的當前狀態(tài)就可能出現(xiàn):“等待風險分析及已核查財務歷史”的情況。
激活動作的用戶被順理成章地稱為觸發(fā)者(caller),每個環(huán)節(jié)都有一個所有者(owner),以代表在當前環(huán)節(jié)中負責執(zhí)行動作的角色或用戶。
當用戶在環(huán)節(jié)中運轉(zhuǎn)流程的時候,已完成的環(huán)節(jié)被保存至歷史表中(history),用戶當前所處的環(huán)節(jié)成為當前環(huán)節(jié)(current steps)。
最
后,讀者可能注意到,在osworkflow中并不存在其他工作流引擎中所包含的工作項(workitem)的概念。這是因為osworkflow是“十
分底層”的工作流實現(xiàn),怎樣實現(xiàn)或定義工作項完全交由用戶來決定。筆者認為工作項的概念太過抽象,用業(yè)務數(shù)據(jù)來稱呼它或許更為貼切一些。
Osworkflow
的文檔中介紹了更多的構(gòu)造元素,如寄存器(Registers),共用方法(common
functions)等,但筆者建議在建立好第一個工作流以后再去研究它們。它們是osworkflow基本元素外的高級特性,而我們前面所認識的元素則
是osworkflow的根本所在。
Osworkflow體系結(jié)構(gòu)
我們將在本節(jié)分析控制osworkflow的體系結(jié)構(gòu),我們需要理解它是怎樣適用到我們的程序中來的。如我們所猜想的,Osworkflow最主要的接口是Workflow,這個接口也是整個工作流引擎的入口點。是整個系統(tǒng)的門面(facade)。
接口的實現(xiàn)主要關(guān)注具體的業(yè)務操作能力,這個接口定義了工作流查詢,獲取當前的可執(zhí)行動作,執(zhí)行動作,顯示歷史環(huán)節(jié)等。
工作流被持久化在工作流存儲體(Workflow Store)中,osworkflow提供了幾種持久化的方法,包括Hibernate持久化集成,JDBC持久化集成等。一個存儲體包含了環(huán)節(jié)信息,變量,工作流自身的描述信息等等。
用戶可能遇到的最常見的應用模式如下所示:
1)通過給定的狀態(tài)在工作流存儲體中查詢工作流信息,通常還根據(jù)某一個工作流程中具有需執(zhí)行動作的用戶來進行查詢。這種查詢時通過WorkflowQuery對象中的Workflow.query()方法實現(xiàn)的。
2)通過getAvailableActions()方法列出所有在滿足條件查詢結(jié)果中可執(zhí)行的操作。
3)通過doAction()方法執(zhí)行用戶選擇的動作。在執(zhí)行動作的時候一些執(zhí)行參數(shù)可以以java.util.Map的形式傳遞,以實現(xiàn)在工作流定義的運行期進行信息的傳遞。
4)用戶可以有選擇地通過調(diào)用initialize()實例化一個工作流。
在理想情況下,由業(yè)務邏輯層負責調(diào)用osworkflow中的方法,如圖二所示:

圖二 在業(yè)務邏輯中集成工作流
在osworkflow
中,業(yè)務邏輯描述在一個XML文件中,稱為工作流描述符(workflow
descriptor.)。我們將在實現(xiàn)小節(jié)中建立一個簡單的描述符。在工作流描述符中的功能(functions)和條件(conditions)中,
用戶可以定義自己的業(yè)務邏輯。筆者將在把工作流集成到應用程序中一節(jié)中進行論述。
實現(xiàn)
本小節(jié)介紹如何把一個業(yè)務邏輯抽象成一個工作流。首先我們要在業(yè)務流程圖中識別出工作流的環(huán)節(jié)。如圖一所示,顯然,我們共有四個環(huán)節(jié),同時包含一個分支及一個合并。在下面的bank.xml文件中,讀者將看到它們在描述符中是如何被表示的。
建立好環(huán)節(jié)以后,必須在每個環(huán)節(jié)中添加一些動作以便于工作流運轉(zhuǎn)。每個動作有唯一的無條件結(jié)果,條件結(jié)果由讀者有選擇地來實現(xiàn)。
<step id="1" name="Form Filling">
<actions>
??<action id="2" name="Fill Form">
?? <results>
????????<unconditional-result old-status="Finished" split="1"/>
?? </results>
??</action>
</actions>
</step>
接下來要并行地執(zhí)行風險分析和財務歷史核查,這里是放置分支的最理想地點。
<splits>
<split id="1">
??<unconditional-result old-status="Finished"
????status="Underway" owner="Risk Analyst" step="2"/>
??<unconditional-result old-status="Finished"
????status="Underway" owner="Financial Officer" step="3"/>
</split>
</splits>
在
部門經(jīng)理最終確認以前,并發(fā)的工作流環(huán)節(jié)必須得到合并。我們可以通過應用一個合并(join)來實現(xiàn)它,合并通過一個條件告訴工作流引擎,是否可以合并并
進行到下一環(huán)節(jié)。在本例中,我們假設這個條件為:前面兩個環(huán)節(jié)都已具有“Finished”的結(jié)束狀態(tài)。即當風險分析或財務審核任何一個未完成前,不能進
行到下一步:
<joins>
<join id="1">
??<conditions type="AND">
?? <condition type="beanshell">
????<arg name="script"><![CDATA[
???? "Finished".equals(jn.getStep(2).getStatus()) &&
????????"Finished".equals(jn.getStep(3).getStatus())
??????]]></arg>
????</condition>
?? </conditions>
??<unconditional-result old-status="Finished"
????status="Underway" owner="Manager" step="4"/>
</join>
</joins>
下面在描述符中加入每個環(huán)節(jié)的所有者,正如我們在基本概念一節(jié)看到的那樣,所有者通常代表了環(huán)節(jié)間交互的角色,角色的引入默認情況下通過osuser框架來實現(xiàn)。
用戶既可以手寫XML描述符文件,也可以通過osworkflow提供的設計器來實現(xiàn)。讀者可以在OpenSymphony的網(wǎng)站上試用這個工具。
測試實現(xiàn)
測試時,我們可以應用osworkflow提供的例子,把bank.xml放到WEB-INF/classes文件夾下,在文件workflows.xml中添加一行以使引擎能夠識別這個工作流。
把工作流集成到應用程序
在建模及測試工作流之后,我們即可以通過下面的幾行代碼把osworkflow集成到我們的程序中。
orkflow wf = new BasicWorkflow(username);
HashMap inputs = new HashMap();
inputs.put("docTitle", request.getParameter("title"));
wf.initialize("workflowName", 1, inputs);
inputs
哈希表包含了初始工作流動作中需要傳出的參數(shù),有幾個實現(xiàn)了Workflow接口的類,其中BasicWorkflow是不支持事務的簡單實現(xiàn)。在工作流
執(zhí)行過程中可以在流程中調(diào)用外部的方法,這種方法應該是實現(xiàn)了FunctionProvider接口的方法類。然后我們就可以用以下的方式調(diào)用它:
<action id="1" name="Execute business rule">
<pre-functions>
??<function type="class">
?? <arg name="class.name">java.net.DroolsExecutorFunction</arg>
?? <arg name="ruleBaseName">BusinessRules.drl</arg>
??</function>
</pre-functions>
...
用戶可以通過實現(xiàn)Condition接口,添加自己的條件控制。FunctionProvider及Condition接口可以調(diào)用工作流中的已知方法,這兩個接口都可以接受來自于XML描述符文件中的參數(shù)。
結(jié)論
把
一個業(yè)務流程抽象成一個工作流的任務并不容易,需要好的方法和合適的工具,osworkflow是一個為我們提供了許多可重用結(jié)構(gòu)的理想工具。希望通過對
本文的閱讀,讀者能夠理解最基本的osworkflow概念。本文論述過程中所采用的方法非常基礎(chǔ)和簡單,但卻值得借鑒。