1.OSWorklow的基本概念

Osworkflow是完全用java語(yǔ)言編寫(xiě)的開(kāi)放源代碼的工作流引擎,具有顯著的靈活性及完全面向有技術(shù)背景的用戶(hù)的特點(diǎn)。用戶(hù)可以根據(jù)自身的需求利用這款開(kāi)源軟件設(shè)計(jì)簡(jiǎn)單或是復(fù)雜的工作流。Osworkflow幾乎提供了所有用戶(hù)可能在實(shí)際流程定義中需要用到的工作流構(gòu)成元素,如:環(huán)節(jié)(step)、條件(conditions)、循環(huán)(loops)、分支(splits)、合并(joins)、角色(roles)等等。
   
    用戶(hù)可以在OpenSymphony的網(wǎng)站上下載osworkflow的發(fā)布。當(dāng)前的最高版本是2.8(OSWorkflow已不再維護(hù)),解壓縮發(fā)布的軟件包,即得到二進(jìn)制程序、源代碼、API文檔、說(shuō)明文檔等。說(shuō)明文檔里面有一些概念描繪和例子,可以作為入門(mén)學(xué)習(xí)的資料。
   
    在osworkflow中最重要的概念是step,每個(gè)工作流包含了多個(gè)step,讀者可以把環(huán)節(jié)想象成工作流中每一個(gè)重要的活動(dòng)。每個(gè)step可以有一些諸如“已完成”、“正在處理”、“已添加至處理隊(duì)列”、“未處理”等的狀態(tài),設(shè)計(jì)工作流的人可以根據(jù)需要自己定義這些狀態(tài)。

    在每個(gè)step,action被用戶(hù)指定為自動(dòng)或手動(dòng)地執(zhí)行。每個(gè)動(dòng)作執(zhí)行后,都有一個(gè)結(jié)果(result)。結(jié)果決定了工作流的流轉(zhuǎn)方向:可以停留在同一step,跳轉(zhuǎn)到另一step,跳轉(zhuǎn)到一個(gè)split,或者匯集到一個(gè)join等。

    最后兩個(gè)概念涉及用戶(hù)對(duì)業(yè)務(wù)流程的并發(fā)執(zhí)行,split把工作流分解為兩個(gè)并行的step,join則在用戶(hù)滿(mǎn)足一定條件后,把兩個(gè)并行的環(huán)節(jié)合并成一個(gè)。

    動(dòng)作的執(zhí)行代表了業(yè)務(wù)流程的執(zhí)行,每個(gè)動(dòng)作都有一組預(yù)處理功能(pre-functions)和一組后處理功能(post-functions)。一個(gè)在動(dòng)作觸發(fā)之前執(zhí)行,一個(gè)在動(dòng)作觸發(fā)之后執(zhí)行。一個(gè)簡(jiǎn)單的例子是:可以在預(yù)處理功能中檢驗(yàn)申請(qǐng)表格數(shù)據(jù)的正確性,而后在后處理貢功能中把經(jīng)檢驗(yàn)的數(shù)據(jù)保存至數(shù)據(jù)庫(kù)。

    動(dòng)作的執(zhí)行結(jié)果可以是有條件的(conditional)或無(wú)條件的(unconditional)。對(duì)于有條件的結(jié)果,引擎將首先檢查是否條件被滿(mǎn)足,然后再交給工作流來(lái)處理。如果條件不滿(mǎn)足的話(huà),引擎將進(jìn)一步判斷下一個(gè)有條件結(jié)果是否得到滿(mǎn)足,以此類(lèi)推,直到系統(tǒng)最終執(zhí)行到無(wú)條件結(jié)果進(jìn)行處理。如果所有的條件結(jié)果都沒(méi)有得到滿(mǎn)足會(huì)如何呢?事實(shí)上,每個(gè)動(dòng)作都強(qiáng)制要求具有唯一一個(gè)無(wú)條件結(jié)果。與此對(duì)應(yīng)的,可以有多個(gè)有條件的結(jié)果。業(yè)務(wù)規(guī)則常常在最終結(jié)果中帶有條件判斷,比如,“如果申請(qǐng)來(lái)自于一個(gè)老客戶(hù),則流轉(zhuǎn)到環(huán)節(jié)1”或者“如果當(dāng)前系統(tǒng)的用戶(hù)的角色是經(jīng)理的話(huà),直接流轉(zhuǎn)道最后一個(gè)環(huán)節(jié)”。

    最后一個(gè)重要的概念是流程狀態(tài)(process state),在osworkflow中,當(dāng)前狀態(tài)是所有當(dāng)前step狀態(tài)的集合。讀者可能會(huì)認(rèn)為工作流在運(yùn)行過(guò)程中只能有一個(gè)狀態(tài),但現(xiàn)實(shí)的情況是:因?yàn)閷?duì)分支和合并的支持,引擎能夠做到對(duì)環(huán)節(jié)的并發(fā)控制,因此工作流的當(dāng)前狀態(tài)就可能出現(xiàn):“等待風(fēng)險(xiǎn)分析及已核查財(cái)務(wù)歷史”的情況。

    激活動(dòng)作的用戶(hù)被順理成章地稱(chēng)為觸發(fā)者(caller),每個(gè)step都有一個(gè)所有者(owner),以代表在當(dāng)前環(huán)節(jié)中負(fù)責(zé)執(zhí)行動(dòng)作的角色或用戶(hù)。當(dāng)用戶(hù)在step中運(yùn)轉(zhuǎn)流程的時(shí)候,已完成的環(huán)step被保存至歷史表中(history),用戶(hù)當(dāng)前所處的環(huán)節(jié)成為current steps。

    注冊(cè)器(register)是一個(gè)全局變量,它在工作流運(yùn)行時(shí)被解析,可以被每個(gè)function和condition 使用
    propertyset是全局范圍的持久數(shù)據(jù)集合(如果用數(shù)據(jù)庫(kù)存儲(chǔ),它為os_propertyentry表)
    transientVars是一個(gè)保存臨時(shí)數(shù)據(jù)的Map對(duì)象,它應(yīng)用于所有的functions和conditons。這個(gè)transientVars里面包括所有的registers(全局變量),用戶(hù)輸入,以及當(dāng)前工作流的上下文和狀態(tài)。它僅在一次工作流調(diào)用的生命周期中存在

2.OSWorkflow的流程配置
    工作流包括四個(gè)方面:流程定義、流程加載、流程運(yùn)行和流程監(jiān)控。下面簡(jiǎn)單分析一下其流程配置文件,這個(gè)流程如下圖所示:


用戶(hù)提出申請(qǐng),等待上級(jí)審批,審批通過(guò)后流程結(jié)束,審批拒絕重寫(xiě)打回申請(qǐng)人繼續(xù)申請(qǐng),流程非常的簡(jiǎn)單,復(fù)雜點(diǎn)就是加了回退功能,并且回退到起始申請(qǐng)人,審批回到上次的審批人。其xml配置文件如下:

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <!DOCTYPE workflow PUBLIC 
  3                  "-//OpenSymphony Group//DTD OSWorkflow 2.8//EN"
  4                  "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">
  5 <workflow>
  6   <initial-actions>
  7     <action id="100" name="Start Workflow">
  8           <pre-functions>
  9             <function type="class">
 10                 <arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
 11             </function>
 12         </pre-functions>
 13         <results>
 14             <unconditional-result old-status="Finished" status="Underway" step="1" owner="${caller}"/>
 15         </results>
 16     </action>
 17   </initial-actions>
 18   <steps>
 19     <step id="1" name="Customer Apply">
 20       <actions>
 21         <action id="1" name="Submit Customer Apply">
 22           <restrict-to>
 23             <conditions>
 24               <condition type="class">
 25                 <arg name="class.name">
 26                    com.opensymphony.workflow.util.StatusCondition
 27                 </arg>
 28                 <arg name="status">Underway</arg>
 29               </condition>
 30             </conditions>
 31           </restrict-to>
 32           <results>
 33             <unconditional-result old-status="Finished" status="Underway" 
 34                                            step="2"  owner="${caller}"/>
 35           </results>
 43         </action>
 44         <action id="3" name="Edit Customer Apply">
 45           <restrict-to>
 46             <conditions>
 47               <condition type="class">
 48                 <arg name="class.name">
 49                    com.opensymphony.workflow.util.StatusCondition
 50                 </arg>
 51                 <arg name="status">Back</arg>
 52               </condition>
 53             </conditions>
 54           </restrict-to>
 55           <pre-functions>
 56             <function type="class">
 57                 <arg name="class.name">com.opensymphony.workflow.util.MostRecentOwner</arg>
 58                 <arg name="stepId">2</arg>
 59             </function>
 60           </pre-functions>
 61           <results>
 62             <unconditional-result old-status="Finished" status="Underway" 
 63                                            step="2"  owner="${mostRecentOwner}"/>
 64           </results>
 65         </action>
 66       </actions>
 67     </step>
 68     <step id="2" name="Customer Apply Approve" >
 69         <actions>
 70           <action id="2" name="Approve Customer Apply">
 71           <restrict-to>
 72             <conditions type="AND">
 73               <condition type="class">
 74                 <arg name="class.name">
 75                     com.opensymphony.workflow.util.StatusCondition
 76                 </arg>
 77                 <arg name="status">Underway</arg>
 78               </condition>
 79               <condition type="class">
 80                 <arg name="class.name">
 81                   com.opensymphony.workflow.util.AllowOwnerOnlyCondition
 82                 </arg>
 83               </condition>
 84             </conditions>
 85           </restrict-to>
 86           <pre-functions>
 87             <function type="class">
 88                 <arg name="class.name">com.opensymphony.workflow.util.MostRecentOwner</arg>
 89                 <arg name="stepId">1</arg>
 90             </function>
 91           </pre-functions>
 92           <results>
 93             <result old-status="Finished" status="Back" step="1" owner="${mostRecentOwner}">
 94                 <conditions type="AND">
 95                     <condition type="beanshell">
 96                         <arg name="script">
 97                             "Reject".equals("${conclusion}");
 98                         </arg>
 99                     </condition>
100                 </conditions>
101             </result>
102             <unconditional-result old-status="Finished" status="Finished" step="3"/>
103           </results>
104         </action>
105       </actions>
106     </step>
107     <step id="3" name="End Apply" />
108   </steps>  
109 </workflow>

上面一共有三個(gè)step,最后一個(gè)step什么也不錯(cuò),就是結(jié)束流程。每一個(gè)step和action都有一個(gè)編號(hào),用于流程跳轉(zhuǎn)和選擇action執(zhí)行。上面pre-functions用戶(hù)查找某個(gè)step最近的owner,目的是讓回退回到原始的申請(qǐng)者和由同一審批人審批此申請(qǐng)。


3.Osworkflow流程運(yùn)行和接口

     流程的加載是引擎自動(dòng)執(zhí)行的。在osworkflow.xml中,配置流程定義文件的地址,workflows.xml(可自定義)配置具體的流程定義文件,如下:

 1 osworkflow.xml
 2 
 3 <osworkflow>
 4   <persistence class="com.aicent.osworkflow.ofbiz.NewOfbizWorkflowStore" />
 5   <factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
 6     <property key="resource" value="workflows.xml" />
 7   </factory>
 8 </osworkflow>
 9 
10 workflows.xml
11 
12 <workflows>
13     <workflow name="customerApply" type="resource" location="customerApply.xml"/>
14 </workflows>


Osworkflow最主要的接口是Workflow,這個(gè)接口也是整個(gè)工作流引擎的入口點(diǎn)。是整個(gè)系統(tǒng)的門(mén)面(facade)。
     接口的實(shí)現(xiàn)主要關(guān)注具體的業(yè)務(wù)操作能力,這個(gè)接口定義了工作流查詢(xún),獲取當(dāng)前的可執(zhí)行動(dòng)作,執(zhí)行動(dòng)作,顯示歷史環(huán)節(jié)等。
     工作流被持久化在工作流存儲(chǔ)體(Workflow Store)中,osworkflow提供了幾種持久化的方法,包括Hibernate持久化集成,JDBC持久化集成和OFBiz持久化集成等。OFBiz持久化集成類(lèi)為OfbizWorkflowStore.java,但是其中有一個(gè)重要的方法沒(méi)有實(shí)現(xiàn),即query方法,我將這個(gè)類(lèi)重寫(xiě)了,將query方法實(shí)現(xiàn)了,見(jiàn)附件。

流程的啟動(dòng):
Workflow workflow = WorkFlowFactory.getWorkFlow(UserUtil.getUserName());
long workflowId = workflow.initialize("customerApply"100null);

執(zhí)行申請(qǐng):
Workflow workflow = WorkFlowFactory.getWorkFlow(UserUtil.getUserName());
Map
<String, String> inputs = new HashMap<String, String>();
inputs.put(
"caller", approver);
workflow.doAction(workflowId.longValue(), 
1, inputs);


http://www.tkk7.com/Files/persister/NewOfbizWorkflowStore.rar