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", 100, null);
執(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