OSWorkflow 概念
在商用和开源世界里,OSWorkflow 都不同于这些已有的工作流系统。最大不同在于 OSWorkflow 有着非常优秀的灵活性。在开始接触 OSWorkflow 时可能较难掌握(有人说不适合工作流新手入门),比如,OSWorkflow 不要求图形化工具来开发工作流,而推荐手工编写 xml 格式的工作流程描述符。它能为应用程序开发者提供集成,也能与现有的代码和数据库进行集成。这一切似乎给正在寻找快速“即插即用”工作流解决方案的人制造了麻烦,但研究发现,那些“即插即用”方案也不能在一个成熟的应用程序中提供足够的灵活性来实现所有需求。
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 文件解释工作流业务流程。
Osworkflow是完全用java语言编写的开放源代码的工作流引擎,具有显著的灵活性及完全面向有技术背景的用户的特点。用户可以根据自身的需求利用这款开源软件设计简单或是复杂的工作流。通过使用,用户就可以把工作中心放在业务和规则的定义上,而不需通过硬编码的方式实现一个Petri网或是一个有穷自动机。用户可以以最小的代价把osworkflow整合到自己的程序中来。Osworkflow几乎提供了所有用户可能在实际流程定义中需要用到的工作流构成元素,如:环节(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)、角色(roles)等等。
首先,在osworkflow中需要了解得最重要的概念是环节,每个工作流包含了多个环节,可 以把环节想象成工作流中每一个重要的活动。每个环节可以有一些诸如“已完成”、“正在处理”、“已添加至处理队列”、“未处理”等的状态,设计工作流的人可以根据需要自己定义状态。
在每个环节,动作被用户指定为自动或手动地执行。每个动作执行后,都有一个结果(result)。结果决定了工作流的流转方向:可以停留在同一环节,跳转到另一环节,跳转到一个分支,或者汇集到一个合并等。
最后两个概念涉及用户对业务流程的并发执行,分支把工作流分解为两个并行的环节,合并则在用户满足一定条件后,把两个并行的环节合并成一个。
动作的执行代表了业务流程的执行,每个动作都有一组预处理功能(pre-functions)和一组后处理功能(post-functions)。其作用正如读者想象的那样,一个在动作触发之前执行,一个在动作触发之后执行。一个简单的例子是:可以在预处理功能中检验申请表格数据的正确性,而后在后处理贡功能中把经检验的数据保存至数据库。
动作的执行结果可以是有条件的(conditional)或无条件的(unconditional)。对于有条件的结果,引擎将首先检查是否条件被满足,然后再交给工作流来处理。如果条件不满足的话,引擎将进一步判断下一个有条件结果是否得到满足,以此类推,直到系统最终执行到无条件结果进行处理。
如果所有的条件结果都没有得到满足会如何呢?事实上,每个动作都强制要求具有唯一一个无条件结果。与此对应的,可以有多个有条件的结果。
业务规则常常在最终结果中带有条件判断,比如,“如果申请来自于一个老客户,则流转到环节1”或者“如果当前系统的用户的角色是经理的话,直接流转道最后一个环节”。
最后一个重要的概念是步骤状态(process state),在osworkflow中,当前步骤状态是所有当前环节状态的集合。读者可能会认为工作流在运行过程中只能有一个状态,但现实的情况是:因为对分支和合并的支持,引擎能够做到对环节的并发控制,因此工作流的当前状态就可能出现:“等待风险分析及已核查财务历史”的情况。
激活动作的用户被顺理成章地称为触发者(caller),每个环节都有一个所有者(owner),以代表在当前环节中负责执行动作的角色或用户。
当用户在环节中运转流程的时候,已完成的环节被保存至历史表中(history),用户当前所处的环节成为当前环节(current steps)。
最后,在osworkflow中并不存在其他工作流引擎中所包含的工作项(workitem)的概念。这是因为osworkflow是“十分底层”的工作流实现,怎样实现或定义工作项完全交由用户来决定。笔者认为工作项的概念太过抽象,用业务数据来称呼它或许更为贴切一些。
Osworkflow 的文档中介绍了更多的构造元素,如寄存器(Registers),共用方法(common functions)等,但建议在建立好第一个工作流以后再去研究它们。它们是osworkflow基本元素外的高级特性,而我们前面所认识的元素则是osworkflow的根本所在。
OSWorkflow 核心概念
step(步骤)
一个 step 是工作流所处的位置。可能从一个 step 流转到另外一个 step(或者有时候还是停留在一样的 step)。举例来说,一个 OA 系统的请假流程,它的 step 名称可能有“本部门审批阶段”,“办公室审批阶段”,“总经理审批阶段”等。
status(状态)
工作流 status 是一个用来描述工作流程中具体步骤状态的字符串。OSWorkflow 的有 Underway(进行中)、Queued(等候处理中)、Finished(完成)三种 status。
action(动作)
action 指定了可能发生在 step 内的转变,会导致 step 的变更。在 OA 系统中,“本部门审批阶段”可能有“拒绝”或“批准”两个 action。action 和 step 之间的关系是,step 说明“在哪里”,action 说明“可以去哪里”。 一个 action 典型地由两部分组成:可以执行此动作的 condition(条件),以及执行此动作的 result(结果)。
condition(条件)
类似于逻辑判断,可包含“AND”和“OR”逻辑。比如一个请假流程中的“本部门审批阶段”,该阶段利用“AND”逻辑,判断流程状态是否为等候处理中,以及审批者是否为本部门主管。
result(结果)
Result 代表指向新的 step 及其 step status,也可能进入 split 或者 join。Result 分为两种, contidional-result (有条件结果),只有条件为真时才使用该结果,和 unconditional-result(无条件结果),当条件不满足或没有条件时使用该结果。
split/join(分离/连接)
流程的切分和融合。很简单的概念,split 提供多个 result;join 则判断多个 current step 的状态,提供一个 result。
OSWorkflow 包用途分析及代码片断
com.opensymphony.workflow
该包为整个 OSWorkflow 引擎提供核心接口。例如 com.opensymphony.workflow.Workflow 接口,可以说,实际开发中的大部分工作都是围绕该接口展开的,该接口有 BasicWorkflow、EJBWorkflow、OfbizWorkflow 三个实现类。
com.opensymphony.workflow.basic
该包有两个类,BasicWorkflow 与 BasicWorkflowContext。BasicWorkflow 不支持事务,尽管依赖持久实现,事务也不能包裹它。BasicWorkflowContext 在实际开发中很少使用。
public void setWorkflow(int userId) { Workflow workflow = new BasicWorkflow(Integer.toString(userId)); } |
com.opensymphony.workflow.config
该包有一个接口和两个该接口的实现类。在 OSWorkflow 2.7 以前,状态由多个地方的静态字段维护,这种方式很方便,但是有很多缺陷和约束。最主要的缺点是无法通过不同配置运行多个 OSWorkflow 实例。实现类 DefaultConfiguration 用于一般的配置文件载入。而 SpringConfiguration 则是让 Spring 容器管理配置信息。
public void setConfiguration(SpringConfiguration configuration) { SpringConfiguration configuration = configuration; workflow.setConfiguration(configuration); } |
com.opensymphony.workflow.ejb
该包有两个接口 WorkflowHome 和 WorkflowRemote。该包的若干类中,最重要的是 EJBWorkflow,该类和 BasicWorkflow 的作用一样,是 OSWorkflow 的核心,并利用 EJB 容器管理事务,也作为工作流 session bean 的包装器。
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(); } |
com.opensymphony.workflow.ofbiz
OfbizWorkflow 和 BasicWorkflow 在很多方面非常相似,除了需要调用 ofbiz 的 TransactionUtil 来包装事务。
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(); }
|
com.opensymphony.workflow.soap OSWorkflow 通过 SOAP 来支持远端调用。这种调用借助 WebMethods 实现。
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); |
com.opensymphony.workflow.util
该包是 OSWorkflow 的工具包,包括了对 BeanShell、BSF、EJB Local、EJB Remote、JNDI 的支持。
小 结
由于本人所在公司希望在 OA 系统中引入工作流引擎,经过分析决定采用 OSWorkflow 引擎。利用 OSWorkflow,已经在系统中实现了请假条流程原型,该流程结合 OA 系统中已有的 RBAC 模型进行逐级审核。我个人认为要用 OSWorkflow 让某个流程跑起来似乎很麻烦,主要是需要扩展和自己实现的太多。
另外,引用一段 Quake Wang 的原话:电子政务/OA 如果要使用workflow engine的话,shark,jbpm 之类的workflow engine有点杀鸡用牛刀的味道。shark 和 jbpm 都强迫你使用它的用户模型,怎样把企业现有的用户模型(包括组织结构)映射过来是很繁琐的事情,比如常见的 OA 应用中,申请者对应的部门负责人为下一个流程的人工参与者,使用 shark 或者 jbpm 都得绕一圈,通过现有的人力资源系统,获得用户,再对应过来。这还仅仅是一个简单的需求,更不用说国内企业千奇百怪的组织结构,以及各种特殊流程,用 wfmc 或者其他所谓的 workflow 通用标准去做不怎么标准的事情。吃力不讨好。用 osworkflow 这种基于状态机的 workflow engine 反而会轻松很多,而且它也没有强迫你使用它的用户模型。另外纠正一点:osworkflow 不仅仅支持简单的 BeanShell,还支持 java class,bsf,ejb。如果做电子政务/OA 的话,觉得目前 osworkflow 是最适用的 opensource workflow engine。