流程啟動>>
前面分析流程流轉的執行邏輯時,并沒有講到流程的啟動。實際上,有了前面的基礎,再加上對流程定義文件加載的過程有清晰認識之后,流程啟動邏輯是很容易理解的。大致情況如下:
- 調用DefaultConfiguration的getWorkflow,傳入流程名稱,然后返回一個WorkflowDescriptor實例,流程定義文件的加載就是在這個時候完成的;
- 然后做一些準備工作,比如:獲取WorkflowStore實例、準備好transientVars和propertySet等等;
- 調用WorkflowDescriptor的getInitialAction方法,獲取initial action(如果有的話),注意此前的第一步中,流程定義文件已經成功加載;
- 調用transitionWorkflow,執行流程的流轉(就是前面提到doAction執行邏輯時調用的那個重要的方法);
在transitionWorkflow方法中,與流程啟動后step間的流轉稍有不同的是:當發現action為initial action時,將會把流程設置為activated狀態,表示流程啟動。就是下面這段代碼:
if ((wf.getInitialAction(action.getId()) != null) && (entry.getState() != WorkflowEntry.ACTIVATED)) {
changeEntryState(entry.getId(), WorkflowEntry.ACTIVATED);
}
WorkflowStore和WorkflowEntry>>
前面提到過,在AbstractWorkflow中,包含流程流轉關鍵邏輯的transitionWorkflow方法,會創建新的step。而這一創建工作是通過調用另一個member method實現的,也就是createNewCurrentStep。其執行邏輯大致如下:
int nextStep = theResult.getStep();
if (nextStep == -1) {
if (currentStep != null) {
nextStep = currentStep.getStepId();
}
}
…
if (currentStep != null) {
store.markFinished(currentStep, actionId, new Date(), oldStatus, context.getCaller());
store.moveToHistory(currentStep);
}
…
Step newStep = store.createCurrentStep(entry.getId(), nextStep, owner, startDate, dueDate, status, previousIds);
從這段代碼中,我們首先可以看到,osworkflow可以支持step節點自身再次被“激活”的行為,也就是重復執行某個step。而另一方面,隨后的創建工作則是調用了store.createCurrentStep。
這個store變量就是一個實現了WorkflowStore接口的實例變量,缺省是MemoryWorkflowStore。WorkflowStore除了創建step之外,還提供了一系列find和query方法。在其內部分別保存著step的歷史記錄(history steps)以及當前處于“激活”狀態的step(current steps),以MemoryWorkflowStore為例,分別對應了兩個HashMap,而JDBCWorkflowStore則利用數據庫表來記錄這些信息。
實際上,WorkflowStore可以同時保存多個流程的記錄,這樣就可以滿足同時存在多個流程的情況。為此,osworkflow提供了一個WorkflowEntry接口用來描述流程信息,其中包含了流程名稱、流程ID、當前狀態等等。WorkflowEntry中定義了如下幾個流程狀態常量:
public static final int CREATED = 0; //創建
public static final int ACTIVATED = 1; // 激活
public static final int SUSPENDED = 2; // 掛起
public static final int KILLED = 3; // 異常終止
public static final int COMPLETED = 4; // 正常結束
public static final int UNKNOWN = -1;
在WorkflowStore提供的接口方法中有如下幾個方法供維護WorkflowEntry使用:
public WorkflowEntry createEntry(String workflowName) throws StoreException;
public WorkflowEntry findEntry(long entryId) throws StoreException;
public void setEntryState(long entryId, int state) throws StoreException;
具體的方法實現,各個具現類有所不同。比如。在MemoryWorkflowStore中,是通過維護一個存儲SimpleWorkflowEntry實例(實現了WorkflowEntry接口)的HashMap達到目的的。