Osworkflow是完全用java语言编写的开放源代码的工作流引擎,具有显著的灵活性及完全面向有技术背景的用户的特点。用户可以根据自身的需求利用这款开源软件设计简单或是复杂的工作流。通过使用,用户就可以把工作中心放在业务和规则的定义上,而不需通过硬编码的方式实现一个Petri网或是一个有穷自动机。用户可以以最小的代价把osworkflow整合到自己的程序中来。Osworkflow几乎提供了所有用户可能在实际流程定义中需要用到的工作流构成元素,如:环节(step)、条件(conditions)、循环(loops)、分支(spilts)、合并(joins)、角色(roles)等等。
xml定义整个流程的业务描述和流转规则,而不含如何业务的osworkflow解析器会先把流程xml读入,然后根据你的doAction做了哪个动作,把这个动作做完后产生的后果数据存储起来。而再通过查询后果数据得到我们所要的业务需要数据。这个就是osworkflow在流程系统中启的主要作用。
OSWorkflow的流程定义使用自己的xml格式,不遵守XPDL规范。
这个xml文件为某一个给定的工作流进行描述steps、states,transitions,和functionality。下面阐述一下此xml的一般规则:
1、 一个工作流由多个steps组成
2、 对于每个step,可以包括多个actions。一个action可以被设置成自动运行或者需要通过人工交互才可以运行。
3、 每个action都要包括至少一个unconditional result和0或多个conditional results。
4、 假如设定了多个concitioanl results,所有当中的第一个将被执行,假如没有设定conditional
results或者没有conditions满足,那么执行unconditional result
5、 一个result过后可能依旧停留在当前的step中,一个新的step,一个split,一个join。在所有的情形中,工作流的state跟着变化(例子工作流中的states分别为:Underway,Queued,和finished)
6、 假如一个result引起一个split,这个result会指定split的属性,以指向一个split元素。
7、 一个split可以有一个或者多个unconditional results,但是没有conditional
results。Unconditional results。Unconditional results需要指定steps。
8、 一个propertyset是一个持久层数据的map,在全局应用中都是可用的。
9、 还有一种叫做transientVars的map,它只存活于一个工作流调用过程中的一定的生命周期,它将会对所有functions和conditions,包括所有的registers,user,input,以及工作流上下文状态等起作用。
具体的业务描述和利用osworkFlow的xml流程描述,可以参看:
(主题:基于开源工作流引擎OSWorkflow的业务系统实例——请假审批系统 http://www.javaeye.com/topic/100499)
我觉得他写的挺具体的。
以下是我个人在实际开发中写的一个工作流的xml流程描述,跟大家分享一下:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.8//EN" "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">
<workflow>
<meta name="created">Wed Dec 12 14:55:50 CST 2007</meta>
<meta name="lastModified">Wed Dec 12 15:02:49 CST 2007</meta>
<meta name="generator">OSWOrkflow Designer</meta>
<initial-actions>
<action id="4" name="启动工作流">
<results>
<unconditional-result id="5" old-status="Finished" status="Queued" step="1" />
</results>
</action>
</initial-actions>
<steps>
<step id="1" name="经办人审核">
<actions>
<action id="5" name="审批" view="add" >
<restrict-to>
<conditions>
<condition name="check.usergroup" type="class">
<arg name="group">经办人</arg>
<arg name="class.name">com.gzepfund.workflow.OStartup</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<!-- 通过时给出时间-->
<arg name="class.name">com.gzepfund.workflow.SetOptionFuntion</arg>
</function>
</pre-functions>
<results>
<result old-status="Finished" status="Queued" step="7">
<conditions>
<!--审批不通过,直接结束当前工作流,并把当前未通过反馈给企业-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给办公室 -->
<result old-status="Finished" status="Queued" step="3">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==3
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给副主任 -->
<result old-status="Finished" status="Queued" step="4">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==4
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给主任 -->
<result old-status="Finished" status="Queued" step="5">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==5
</arg>
</condition>
</conditions>
</result>
<unconditional-result id="7" old-status="Finished" status="Queued" step="2"/>
</results>
</action>
</actions>
</step>
<step id="2" name="部门审批">
<actions>
<action id="6" name="审批" view="upd" >
<restrict-to>
<conditions>
<condition name="check.usergroup" type="class">
<arg name="group">部门负责人</arg>
<arg name="class.name">com.gzepfund.workflow.OStartup</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<!-- 设置审批是否通过-->
<arg name="class.name">com.gzepfund.workflow.SetOptionFuntion</arg>
</function>
</pre-functions>
<results>
<result old-status="Finished" status="Queued" step="1">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给副主任 -->
<result old-status="Finished" status="Queued" step="4">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==4
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给主任 -->
<result old-status="Finished" status="Queued" step="5">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==5
</arg>
</condition>
</conditions>
</result>
<unconditional-result id="7" old-status="Finished" status="Queued" step="3"/>
</results>
</action>
</actions>
</step>
<step id="3" name="办公室审批">
<actions>
<action id="7" name="审批" view="upd" >
<restrict-to>
<conditions>
<condition name="check.usergroup" type="class">
<arg name="group">办公室</arg>
<arg name="class.name">com.gzepfund.workflow.OStartup</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<!-- 设置审批是否通过-->
<arg name="class.name">com.gzepfund.workflow.SetOptionFuntion</arg>
</function>
</pre-functions>
<results>
<!-- 审批不通过返回给经办人 -->
<result old-status="Finished" status="Queued" step="1">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==1
</arg>
</condition>
</conditions>
</result>
<!-- 审批不通过返回给部门负责人 -->
<result old-status="Finished" status="Queued" step="2">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==2
</arg>
</condition>
</conditions>
</result>
<!-- 审批通过提交给主任 -->
<result old-status="Finished" status="Queued" step="5">
<conditions type="AND">
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==1
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==5
</arg>
</condition>
</conditions>
</result>
<unconditional-result id="7" old-status="Finished" status="Queued" step="4"/>
</results>
</action>
</actions>
</step>
<step id="4" name="副主任审批">
<actions>
<action id="8" name="审批" view="upd">
<restrict-to>
<conditions>
<condition name="check.usergroup" type="class">
<arg name="group">副主任</arg>
<arg name="class.name">com.gzepfund.workflow.OStartup</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<!-- 设置审批是否通过-->
<arg name="class.name">com.gzepfund.workflow.SetOptionFuntion</arg>
</function>
</pre-functions>
<results>
<!-- 审批不通过返回给经办人 -->
<result old-status="Finished" status="Queued" step="1">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==1
</arg>
</condition>
</conditions>
</result>
<!-- 审批不通过返回给部门负责人 -->
<result old-status="Finished" status="Queued" step="2">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==2
</arg>
</condition>
</conditions>
</result>
<!-- 审批不通过返回给经办人 -->
<result old-status="Finished" status="Queued" step="4">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==4
</arg>
</condition>
</conditions>
</result>
<unconditional-result id="9" old-status="Finished" status="Queued" step="5" />
</results>
</action>
</actions>
</step>
<step id="5" name="主任审批">
<actions>
<action id="9" name="审批" view="upd">
<restrict-to>
<conditions>
<condition name="check.usergroup" type="class">
<arg name="group">主任</arg>
<arg name="class.name">com.gzepfund.workflow.OStartup</arg>
</condition>
</conditions>
</restrict-to>
<pre-functions>
<function type="class">
<!-- 设置审批是否通过-->
<arg name="class.name">com.gzepfund.workflow.SetOptionFuntion</arg>
</function>
</pre-functions>
<results>
<result old-status="Finished" status="Queued" step="1">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==1
</arg>
</condition>
</conditions>
</result>
<result old-status="Finished" status="Queued" step="2">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==2
</arg>
</condition>
</conditions>
</result>
<result old-status="Finished" status="Queued" step="3">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==3
</arg>
</condition>
</conditions>
</result>
<result old-status="Finished" status="Queued" step="4">
<conditions type="AND">
<!--根据提交意见决定流程走向,1,审批通过,0,未通过,需要修改-->
<condition type="beanshell">
<arg name="script">
propertySet.getInt("ispass")==0
</arg>
</condition>
<condition type="beanshell">
<arg name="script">
propertySet.getInt("position")==4
</arg>
</condition>
</conditions>
</result>
<unconditional-result id="11" old-status="Finished" status="Queued" step="7" />
</results>
<post-functions>
<function type="class">
<!-- 设置项目状态为是否通过技术评审-->
<arg name="class.name">com.gzepfund.workflow.ApproveFunction</arg>
</function>
</post-functions>
</action>
</actions>
</step>
<step id="7" name="流程结束"></step>
</steps>
</workflow>
注:XPDL(XML Process Definition Language)是由Workflow Management Coalition所提出的一个标准化规格,使用XML文件让不同的工作流程软件能够交换商业流程定义。