轉自: 阿Q的家
1. OSWorkFlow基本概念
在商用和開源世界裡,OSWorkflow 都不同於這些已有的工作流程系統。最大不同在於 OSWorkflow 有著非常優秀的靈活性。在開始接觸 OSWorkflow 時可能較難掌握(有人說不適合工作流程新手入門),比如,OSWorkflow 不要求圖形化工具來開發工作流程,而推薦手工編寫 xml 格式的工作流程描述符。它能為應用程式開發人員提供整合,也能與現有的代碼和資料庫進行整合。這一切似乎給正在尋找快速“隨插即用”工作流程解決方案的人製造 了麻煩,但研究發現,那些“隨插即用”方案也不能在一個成熟的應用程式中提供足夠的靈活性來實現所有需求。
2. OSWorkFlow主要優勢
OSWorkflow 給你絕對的靈活性。OSWorkflow 被認為是一種“低層級”工作流程實現。與其他工作流程系統能用表徵圖表現“Loops(迴路)”和“Conditions(條件)”相比,OSWorkflow 只是手工“編碼(Coded)”來實現的。但這並不能說實際的代碼是需要完全手工編碼的,指令碼語言能勝任這種情形。OSWorkflow 不希望一個非技術使用者修改工作流程,雖然一些其他工作流程系統提供了簡單的 GUI 用於工作流程編輯,但像這樣改變工作流程,通常會破壞這些應用。所以,進行工作流程調整的最佳人選是開發人員,他們知道該怎麼改變。不過,在最新的版本中, OSWorkflow 也提供了 GUI 設計器來協助工作流程的編輯。
OSWorkflow 基於有限狀態機器概念。每個 state 由 step ID 和 status 聯合表現(可簡單理解為 step 及其 status 表示有限狀態機器的 state)。一個 state 到另一 state 的 transition 依賴於 action 的發生,在工作流程生命期內有至少一個或多個活動的 state。這些簡單概念展現了 OSWorkflow 引擎的核心思想,並允許一個簡單 XML 檔案解釋工作流程商務程序。
3. OSWorkFlow核心概念
3.1. 概念定義
步驟(Step)
一個 Step 描述的是工作流程所處的位置。可能從一個 Step Transtion(流轉)到另外一個 Step,或者也可以在同一個 Step 內流轉(因為 Step 可以通 Status 來細分,形成多個State)。一個流程裡面可以多個Step。
狀態(Status)
工作流程 Status 是用來描述工作流程中具體Step(步驟)狀態的字串。OSWorkflow 的有 Underway(進行中)、Queued(等候處理中)、Finished(完成)三種 Status。一個實際State(狀態)真正是由兩部分組成:State = (Step + Status) 。
流轉(Transtion)
一個State到另一個State的轉移。
動作(Action)
Action 觸發了發生在 Step 內或 Step 間的流轉,或者說是基於 State 的流轉。一個 step 裡面可以有多個Action。Action 和Step 之間的關係是,Step 說明“在哪裡”,Action 說明“去哪裡”。 一個 Action 典型地由兩部分組成:可以執行此Action(動作)的
Condition(條件),以及執行此動作後的 Result(結果)。
條件(Condition)
類似於邏輯判斷,可包含“AND”和“OR”邏輯。比如一個請假流程中的“本部門審批階段”,該階段利用“AND”邏輯,判斷流程狀態是否為等候處理中,以及審批者是否為本部門主管。
結果(Result)
Result 代表執行Action(動作)後的結果,指向新的 Step 及其 Step Status,也可能進入 Split 或者 Join。Result 分為兩種, Contidional-Result (有條件結果),只有條件為真時才使用該結果,和 Unconditional-Result(無條件結果),當條件不滿足或沒有條件時使用該結果。
分離/串連(Split/Join)
流程的切分和融合。很簡單的概念,Split 可以提供多個 Result(結果);Join 則判斷多個 Current Step 的態提供一個 Result(結果)。
3.2. 步驟、狀態和動作(Step, Status, and Action)
工作流程要描述步驟(Step)、步驟的狀態(Status)、各個步驟之間的關係以及執行各個步驟的條件和許可權,每個步驟中可以含有一個或多個動作(Action),動作將會使一個步驟的狀態發生改變。
對於一個執行的工作流程來講,步驟的切換是不可避免的。一個工作流程在某一時刻會有一個或多個當前步驟,每個當 前步驟都有一個狀態值,當前步驟的狀態值組成了工作流程執行個體的狀態值。一旦完成了一個步驟,那麼這個步驟將不再是當前步驟(而是切換到一個新的步驟),通常 一個新的當前步驟將隨之建立起來,以保證工作流程繼續執行。完成了的步驟的最終狀態值是用Old-Status屬性指定的,這個狀態值的設定將發生在切換到 其他步驟之前。Old-Status的值可以是任意的,但在一般情況下,我們設定為Finished。
切換本身是一個動作(Action)的執行結果。每個步驟可以含有多個動作,究竟要載入哪個動作是由最終用 戶、外來事件或者Tiggerd的自動調用決定的。隨著動作的完成,一個特定的步驟切換也將發生。動作可以被限制在使用者、使用者組或目前狀態。每一個動作都 必須包含一個Unconditional Result和0個或多個Conditional Results。
所以,總體來說,一個工作流程由多個步驟組成。每個步驟有一個目前狀態(例如:Queued, Underway or Finished),一個步驟包含多個動作。每個步驟含有多個可以執行的動作。每個動作都有執行的條件,也有要執行的函數。動作包含有可以改變狀態和當前 工作流程步驟的results。
3.3. 結果、分支和串連(Results, Joins, and Splits)
3.3.1. 無條件結果(Unconditional Result)
對於每一個動作來講,必須存在一個Unconditional Result。一個result是一系列指令,這些指令將告訴OSWorkFlow下一個任務要做什麼。這包括使工作流程從一個狀態切換到另一個狀態。
3.3.2. 有條件結果(Conditional Result)
Conditional Result是Unconditional Result的一個擴充。它需要一個或多個Condition子標籤。第一個為true的Conditional(使用AND或OR類型),會指明發生切 換的步驟,這個切換步驟的發生是由於某個使用者執行了某個動作的結果導致的。
3.3.3. 三種不同的Results(conditional or unconditional)
一個新的、單一的步驟和狀態的組合。
一個分裂成兩個或多個步驟和狀態的組合。
將這個和其他的切換組合成一個新的單一的步驟和狀態的組合。
每種不同的result對應了不同的xml描述,你可以閱讀http://www.opensymphony.com/osworkflow/workflow_2_7.dtd,擷取更多的資訊。
注意:通常,一個split或一個join不會再導致一個split 或 join的發生。
3.4. 自動步驟(Auto actions)
有的時候,我們需要一些動作可以基於一些條件自動地執行。為了達到這個目的,你可以在action中加入auto="true"屬性。流程將考察這個動作 的條件和限制,如果條件符合,那麼將執行這個動作。 Auto action是由當前的調用者執行的,所以將對該動作的調用者執行許可權檢查。
3.5. 整合抽象執行個體(Integrating with Abstract Entities)
建議在你的核心實體中,例如"Document" 或 "Order",在內部建立一個新的屬性:workflowId。這樣,當新的"Document" 或 "Order"被建立的時候,它能夠和一個workflow執行個體關聯起來。那麼,你的代碼可以通過OSWorkflow API尋找到這個workflow執行個體並且得到這個workflow的資訊和動作。
3.6. 工作流程執行個體狀態(Workflow Instance State)
有的時候,為整個workflow執行個體指定一個狀態是很有協助的,它獨立於流程的執行步驟。OSWorkflow提供一些workflow執行個體中可以包含 的"meta-states"。這些"meta-states"可以是CREATED, ACTIVATED, SUSPENDED, KILLED 和 COMPLETED。當一個工作流程執行個體被建立的時候,它將處於CREATED狀態。然後,只要一個動作被執行,它就會自動的變成ACTIVATED狀態。 如果調用者沒有明確地改變執行個體的狀態,工作流程將一直保持這個狀態直到工作流程結束。當工作流程不可能再執行任何其他的動作的時候,工作流程將自動的變成 COMPLETED狀態。
然而,當工作流程處於ACTIVATED狀態的時候,調用者可以終止或掛起這個工作流程(設定工作流程的狀態為 KILLED 或 SUSPENDED)。一個終止了的工作流程將不能再執行任何動作,而且將永遠保持著終止狀態。一個被掛起了的工作流程會被凍結,他也不能執行任何的動作,除 非它的狀態再變成ACTIVATED。
4. OSWorkFlow包用途分析及代碼片斷
4.1. com.opensymphony.workflow
該包為整個OSWorkflow 引擎提供核心介面。例如 com.opensymphony.workflow.Workflow 介面,可以說,實際開發中的大部分工作都是圍繞該介面展開的,該介面有 BasicWorkflow、EJBWorkflow、OfbizWorkflow 三個實作類別。
4.2. com.opensymphony.workflow.basic
該包有兩個類,BasicWorkflow 與 BasicWorkflowContext。BasicWorkflow 不支援事務,儘管依賴持久實現,事務也不能包裹它。BasicWorkflowContext 在實際開發中很少使用。
public void setWorkflow(int userId) {
Workflow workflow = new BasicWorkflow(Integer.toString(userId));
}
4.3. com.opensymphony.workflow.config
該包有一個介面和兩個該介面的實作類別。在 OSWorkflow 2.7 以前,狀態由多個地方的靜態欄位維護,這種方式很方便,但是有很多缺陷和約束。最主要的缺點是無法通過不同配置運行多個 OSWorkflow 執行個體。實作類別 DefaultConfiguration 用於一般的設定檔載入。而 SpringConfiguration 則是讓 Spring 容器管理配置資訊。
public void setWorkflow(int userId) {
Workflow workflow = new BasicWorkflow(Integer.toString(userId));
}
4.4. com.opensymphony.workflow.ejb
該包有兩個介面 WorkflowHome 和 WorkflowRemote。該包的若干類中,最重要的是 EJBWorkflow,該類和 BasicWorkflow 的作用一樣,是 OSWorkflow 的核心,並利用 EJB 容器管理事務,也作為工作流程 session bean 的封裝器。
4.5. com.opensymphony.workflow.loader
該包有若干類,用得最多的是 XxxxDescriptor,如果在工作流程引擎運行時需要瞭解指定的動作、步驟的狀態、名字,等資訊時,這些描述符會起到很大作用。
public String findNameByStepId(int stepId,String wfName) {
WorkflowDescriptor wd = workflow.getWorkflowDescriptor(wfName);
StepDescriptor stepDes = wd.getStep(stepId);
return stepDes.getName();
}
4.6. com.opensymphony.workflow.ofbiz
OfbizWorkflow 和 BasicWorkflow 在很多方面非常相似,除了需要調用 ofbiz 的 TransactionUtil 來封裝事務。
4.7. com.opensymphony.workflow.query
該包主要為查詢而設計,但不是所有的工作流程儲存都支援查詢。通常,Hibernate 和 JDBC 都支援,而記憶體工作流程儲存不支援。值得注意的是 Hibernate 儲存不支援混合型查詢(例如,一個查詢同時包含了 history step 上下文和 current step 上下文)。執行一個查詢,需要建立 WorkflowExpressionQuery 執行個體,接著調用 Workflow 對象的 query 方法來得到最終查詢結果。
public List queryDepAdmin(int userId,int type) {
int[] arr = getSubPerson(userId,type);
//構造運算式
Expression[] expressions = new Expression[1 + arr.length];
Expression expStatus = new FieldExpression(FieldExpression.STATUS,
FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, "Queued");
expressions[0] = expStatus;
for (int i = 0; i < arr.length; i++) {
Expression expOwner = new FieldExpression(FieldExpression.OWNER,
FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS,
Integer.toString(arr[i]));
expressions[i + 1] = expOwner;
}
//查詢未完成流編號
List wfIdList = null;
try {
WorkflowExpressionQuery query = new WorkflowExpressionQuery(
new NestedExpression(expressions, NestedExpression.AND));
wfIdList = workflow.query(query);
} catch (Exception e) {
e.printStackTrace();
}
}
4.8. com.opensymphony.workflow.soap
OSWorkflow 通過 SOAP 來支援遠端調用。這種調用藉助 WebMethods 實現。
4.9. com.opensymphony.workflow.spi
該包可以說是 OSWorkflow 與持久層打交道的途徑,如當前工作流程的實體,其中包括:EJB、Hibernate、JDBC、Memory、Ofbiz、OJB、Prevayler。
HibernateWorkflowEntry hwfe = (HibernateWorkflowEntry) getHibernateTemplate()
.find("from HibernateWorkflowEntry where Id="
+ wfIdList.get(i)).get(0);
4.10. com.opensymphony.workflow.util
該包是 OSWorkflow 的工具包,包括了對 BeanShell、BSF、EJB Local、EJB Remote、JNDI 的支援。
5. OSWorkFlow表結構分析
5.1. OS_WFENTRY
工作流程主表,存放工作流程名稱和狀態
欄位名 資料類型 說明
ID NUMBER 自動編號
NAME VARCHAR2(20) 工作流程名稱
STATE NUMBER 工作流程狀態
5.2. OS_CURRENTSTEP
當前步驟表,存放當前進行中步驟的資料
欄位名 資料類型 說明
ID NUMBER 自動編號
ENTRY_ID NUMBER 工作流程編號
STEP_ID NUMBER 步驟編號
ACTION_ID NUMBER 動作編號
OWNER VARCHAR2(20) 步驟的所有者
START_DATE DATE 開始時間
FINISH_DATE DATE 結束時間
DUE_DATE DATE 授權時間
STATUS VARCHAR2(20) 狀態
CALLER VARCHAR2(20) 操作人員的帳號名稱
5.3. OS_CURRENTSTEP_PREV
前步驟表,存放當前步驟和上一個步驟的關聯資料
欄位名 資料類型 說明
ID NUMBER 當前步驟編號
PREVIOUS NUMBER 前步驟編號
5.4. OS_HISTORYSTEP
曆史步驟表,存放當前進行中步驟的資料
欄位名 資料類型 說明
ID NUMBER 自動編號
ENTRY_ID NUMBER 工作流程編號
STEP_ID NUMBER 步驟編號
ACTION_ID NUMBER 動作編號
OWNER VARCHAR2(20) 步驟的所有者
START_DATE DATE 開始時間
FINISH_DATE DATE 結束時間
DUE_DATE DATE 授權時間
STATUS VARCHAR2(20) 狀態
CALLER VARCHAR2(20) 操作人員的帳號名稱
5.5. OS_HISTORYSTEP_PREV
前曆史步驟表,存放曆史步驟和上一個步驟的關聯資料
欄位名 資料類型 說明
ID NUMBER 當前曆史步驟編號
PREVIOUS NUMBER 前曆史步驟編號
5.6. OS_PROPERTYENTRY
屬性工作表,存放臨時變數
欄位名 資料類型 說明
GLOBAL_KEY VARCHAR2(255) 全域關鍵字
ITEM_KEY VARCHAR2(255) 條目關鍵字
ITEM_TYPE NUMBER 項目類型
STRING_VALUE VARCHAR2(255) 字元值
DATE_VALUE DATE 日期值
DATA_VALUE BLOB 資料值
FLOAT_VALUE FLOAT 浮點值
NUMBER_VALUE NUMBER 數字值