OSWorkflow使用問(wèn)答1. 從哪兒可以得到OSWorkflow的有關(guān)工作流定義的資料?
答:下載之后,在OSWorkflow的docs目錄下會(huì )有一些dtd文件。其中workflow_2_7.dtd就是2.7的工作流xml使用的dtd。在這個(gè)文件中,作者使用注釋詳細說(shuō)明了每個(gè)元素的含義和作用。
2. 簡(jiǎn)單的描述一下OSWorkflow工作流定義的特點(diǎn)?
答:OSWorkflow把工作流視為一組關(guān)聯(lián)的Step,通過(guò)執行與Step相關(guān)的Action,實(shí)現從一個(gè)Step到另一個(gè)Step的轉換。從而引起工作流狀態(tài)的轉換,推動(dòng)工作的前進(jìn)。目前OSWorkflow并不支持子流程,這一點(diǎn)可以從它的dtd文件看出來(lái)。另一個(gè)主要的特點(diǎn)就是腳本(如beanshell)的支持,OSWorkflow的主要組件,如function、validator等,都支持使用腳本來(lái)編程。
3. 如何定義順序結構?
答:Step1到Step2的轉換,可以這樣來(lái)看:在Step1上執行了一個(gè)Action,這個(gè)Action的結果是轉向到Step2。因此,可以描述成:
<steps>
<step name="Step1" id="1">
<actions>
<action name="Step1_Action" id="11">
<results>
<unconditional-result old-status="Finished" status="Waiting" step="2"/>
</results>
</action>
</actions>
</step>
<step name="Step2" id="2">
......
</step>
<steps>
注意,在OSWorkflow中基本上都是使用id,而不是name。對于status和old-status,前者表示轉向到Step2后的狀態(tài)值(Step2的狀態(tài)),后者表示離開(kāi)Step1后狀態(tài)值(Step1的狀態(tài))。
另外,當轉向的Step是類(lèi)似于<step name="end" id="2"/>時(shí),則流程會(huì )自動(dòng)終止。當轉向的Step中包含的Action集合中存在一個(gè)auto屬性為true的action時(shí),轉向之后Action自動(dòng)觸發(fā)。如:
<step name="Step2" id="2">
<actions>
<action name="Step2_Action" id="21" auto="true">
<results>
<unconditional-result old-status="Finished" status="Ready1" split="100"/>
</results>
</action>
</actions>
</step>
進(jìn)入Step2后,Step2_Action將自動(dòng)執行。
4. 如何定義并行工作中的Split和Join?
答:在狀態(tài)機中表示并行工作的存在著(zhù)2個(gè)特別的元素:分拆和合并。在OSWorkflow中與之對應的則是:<split>和<join>。從Step2分拆成2個(gè)并行任務(wù)(Step31,Step32),再合并并轉向Step4??梢匀绱死斫猓涸赟tep2上執行一個(gè)Action,其結果會(huì )導致Step31和Step32的產(chǎn)生;分別執行Step31和Step32的Action,轉向合并點(diǎn);合并點(diǎn)判斷Step31和Step32都完成后,那么轉向Step4。因此,可以描述為:
<steps>
......
<step name="Step2" id="2">
<actions>
<action name="Step2_Action" id="21">
<results>
<unconditional-result old-status="Finished" status="Ready1" split="100"/>
</results>
</action>
</actions>
</step>
<step name="Split_Step" id="31">
<actions>
<action name="Split_Step_Action" id="311">
<results>
<unconditional-result old-status="finished" status="Ready2" join="200"/>
</results>
</action>
</actions>
</step>
<step name="Split_Step" id="32">
<actions>
<action name="Split_Step_Action" id="321">
<results>
<unconditional-result old-status="finished" status="Ready3" join="200"/>
</results>
</action>
</actions>
</step>
<step name="Join_Step" id="4">
......
</step>
</steps>
<splits>
<split id="100">
<unconditional-result old-status="finished" status="Ready5" step="31" />
<unconditional-result old-status="finished" status="Ready6" step="32" />
</split>
</splits>
<joins>
<join id="200">
<conditions>
<condition type="beanshell">
<arg name="script">
"finished".equals( jn.getStep(31).getStatus())
&&"finished".equals( jn.getStep(32).getStatus());
</arg>
</condition>
</conditions>
<unconditional-result old-status="finished" status="Ready7" step="4" />
</join>
</joins>
注意:<steps>、<splits>和<joins>可以理解為<step>、<split>和<join>對應的集合。關(guān)鍵是<result>(或<unconditional-result>),使得這些離散的建立了關(guān)聯(lián),確定了狀態(tài)轉換的目標。
5. 如何建立分支和循環(huán)結構?
答:對于循環(huán)結構可以由分支結構來(lái)模擬,讓我們主要來(lái)看看分支結構的實(shí)現。通常有2種方法:
- 使用外部程序,因為狀態(tài)改變是Action的結果,而每個(gè)Step可以有多個(gè)Action。通過(guò)在外部程序中決定使用哪個(gè)Action,可以達到分支的效果。這個(gè)方法的本質(zhì)實(shí)際是將分支判斷放到外部程序中。如:
<steps>
<step name="Step1" id="1">
<actions>
<action name="Step1_Action1" id="11">
<results>
<unconditional-result old-status="Finished" status="Waiting" step="2"/>
</results>
</action>
<action name="Step1_Action2" id="12">
<results>
<unconditional-result old-status="Finished" status="Waiting" step="3"/>
</results>
</action>
</actions>
</step>
<step name="Step2" id="2">
......
</step>
<step name="Step3" id="3">
......
</step>
<steps>
當處于Step1時(shí),在外部程序如果調用action11,那么下一步就是Step2;如果是action12,下一步就是Step3。
- 使用帶條件的結果,相對于上個(gè)方法而言,這個(gè)是使用OSWorkflow的內部機制。當然,內部條件使用的數據仍然還是由外部調用決定的。如:
<step name="Step2" id="2">
<actions>
<action name="Step2_Action" id="21">
<results>
<result old-status="Finished" status="Ready1" step="5">
<conditions>
<condition type="beanshell">
<arg name="script">
null== transientVars.get("flag");
</arg>
</condition>
</conditions>
</result>
<unconditional-result old-status="Finished" status="Ready1" split="100"/>
</results>
</action>
</actions>
</step>
上述描述相當于:
if(){
轉向step5;
}else{
轉向split100;
}
從OSWorkflow的DTD中,可以知道<results>的有關(guān)資料:<!ELEMENT results (result*,unconditional-result)>。當有多個(gè)帶條件的result時(shí),滿(mǎn)足條件的第一個(gè)<result>起作用,當沒(méi)有條件滿(mǎn)足時(shí)< unconditional-result >起作用。
6. 如何實(shí)現自定義的功能?
答:OSWorkflow在工作流描述文件中提供了自定義功能的地方:
- ,主要在狀態(tài)改變時(shí)發(fā)生作用,如狀態(tài)改變時(shí)發(fā)送電子郵件通知。對應的元素<function>,用于<pre-functions>和<post-functions>中。針對<step>和<action>都可以使用,pre-function是進(jìn)入<step>或<action>時(shí)起作用;post-functions是離開(kāi)時(shí)起作用。例子:function
- ,自定義條件,如執行action的所需要的條件,在<conditions>中定義。針對<join>、<restrict-to>和<result>起作用。如果在<conditions>包含<conditions>,表示內嵌條件。condition
- ,自定義驗證,如驗證參數或流程的狀態(tài),在<validators>中定義。針對<action>、<result>和<unconditional-result>起作用。validator
- ,為工作流的組件,如function,提供了存取另一個(gè)實(shí)體的方便操作??梢岳斫鉃檫@個(gè)實(shí)體的創(chuàng )建工廠(chǎng),在<registers>中定義。針對工作流的其他組件都起作用。register
上述組件都支持三種類(lèi)型的定義:Java-based、beanshell和bsf,使用方法基本一致。以function為例:
<function type="beanshell">
<arg name="script">
System.out.println("prefunction 2 of action 11");
</arg>
</function>
<function type="class">
<!-- 實(shí)現類(lèi),參見(jiàn)javadoc -->
<arg name="class.name">
workflow.Prefunction1OfStep1
</arg>
<arg name="msg">foxgem is ok!</arg>
</function>
同時(shí)OSWorkflow還提供了對應的一些預置組件,請參見(jiàn)相關(guān)的javadoc。為了方便數據的交互,OSWorkflow提供了一些內置的對象(對于腳本,直接在腳本中按下面的名字使用即可):
- ,臨時(shí)變量Map,包括:register、用戶(hù)輸入和當前的工作流上下文等信息。transientVars
- ,在文件的<arg>中定義的參數Map。args
- ,用于持久化的變量。propertySet
- ,com.opensymphony.workflow.JoinNodes,表示合并的步驟集合。jn
上述對象,前三個(gè)可以使用在前面列出的所有組件中使用。最后一個(gè)主要在join中定義的conditions中使用,見(jiàn)前例。
7. 外部程序如何使用OSWorkflow?
答:外部程序使用OSWorkflow的基本步驟:
1) 定義工作流文件,并配置。OSWorkflow的配置文件基本上是三個(gè)層次:
osworkflow.xml,配置osworkflow的全局信息。如創(chuàng )建工廠(chǎng),持久化機制等。
workflows.xml,指明工作流文件的集合
具體workflow定義,定義具體的工作流描述。
2) 創(chuàng )建工作流:Workflow flow= new BasicWorkflow("tester");。
3) 初始化指定的工作流。
//最后一個(gè)參數,可以傳進(jìn)一些數據供OSWorkflow的組件使用
long id= flow.initialize( "mytest", 1, null);
其中mytest,是在workflows.xml中定義的名字,對應具體的工作流定義文件。在OSWorkflow中有一組特定的Action,<initial-actions>,它的目的就是用來(lái)初始化流程的。典型的<initial-actions>定義如下:
<initial-actions>
<action name="Start Workflow" id="1">
<results>
<unconditional-result old-status="Finished" status="Queued" step="1"/>
</results>
</action>
<action name="Another Entry" id="2">
<results>
<unconditional-result old-status="Finished" status="Underway" step="2"/>
</results>
</action>
</initial-actions>
這其中的每個(gè)Action代表了不同的流程啟動(dòng)點(diǎn)。
4) 執行指定的動(dòng)作,完成流程狀態(tài)的切換。flow.doAction( flowid, 11,null);。其中flowid是初始化時(shí)得到的流程id;11是<action>的id,這個(gè)id應該是全局唯一的;最后一個(gè)參數,是用來(lái)給OSWorkflow傳遞參數用的外部輸入。
以上就是OSWorkflow的基本使用,實(shí)際上最常用的就是2個(gè)方法:initialize和doAction。對于其他的方法和對象,請參見(jiàn)對應的javadoc。
8. 如何將持久化機制用于流程數據?
答:對于持久化的支持,OSWorkflow提供了WorkflowStore接口,可以讓使用者自己實(shí)現自定義的持久化機制。對于數據庫,使用JDBCStore即可。關(guān)于JDBCStore的配置主要集中于osworkflow.xml中,具體的配置方法,參見(jiàn)文檔:1.4Persistence Options。
9. 如何查詢(xún)工作流?
答:主要的類(lèi)型:
- 獲得當前步驟和歷史步驟列表:Workflow的getCurrentSteps和getHistorySteps。
- 獲得當前可用的action:Workflow的getAvailableActions。
- 自定義查詢(xún):首先構造WorkflowExpressionQuery,然后使用Workflow的query。具體例子參見(jiàn):文檔5.4 Queries。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1740612