流程启动>>
前面分析流程流转的执行逻辑时,并没有讲到流程的启动。实际上,有了前面的基础,再加上对流程定义文件加载的过程有清晰认识之后,流程启动逻辑是很容易理解的。大致情况如下:
- 调用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达到目的的。