Osworkflow与目前绝大多书的工作流系统是不同的,而最大的不同点体现在它的韧性上和灵活程度上,在商业界和开源世界都存在它的影子。最开始大家可能比较难于理解,举个例子:osworkflow并不强制要求您用图形工具来开发工作流,推荐的首选办法是手写xml文件(即手写过程定义的xml文档,而图形工具操作的实质也是操作此xml,图形工具只是给非专业人士如业务分析人员,过程定义人员使用的)。它充分胜任这种整合,就想现存代码和数据库之间整合一样。虽然这样似乎看起来并不太适合进行快速所谓的“即插即用”工作流解决方案,但是osworkflow所提供的解决方案能够提供足够的灵活度来满足一个大型各种应用的所有需求。
Osworkflow的韧性:
可以把osworkflow看做一个低层次的工作流实现。在其他工作流系统中像loops和conditions这样的情况可以以图形图标形式展现出来,在osworkflow中必须进行编码。就是说最起码的脚本语言必须来如此设定。所以并不希望非技术人员来修改工作流。尽管一些系统提供了GUI操作来完成简单的工作流编辑,但是这种做法并不是十全十美的,如当这样改变流程后,此工作流周边的应用往往被破坏。所以osworkflow始终认为最好的变更控制办法就是以开发人员(前提:熟知每个变化)来做这些操作。Osworkflow在2.5.0版本就开始支持图形操作(designer),2.6.0和2.7.0做了许多改进。打算在3.0中正式推出。所以现在在使用GUI操作时候还是需要进行一些适当的预防手段的。
Osworkflow内部使用的是有限状态机的概念(对于这部分理解不好的,可以参看UML中的状态图部分,就可以有个初步理解)。每个状态都是通过一个step ID和一个状态来共同描述的。一个变迁(从一个状态到另外一个状态)只有在一个action发生的前提下才会被触发。在一个工作流的生命周期中始终会有一个或多个活动的状态。简单的讲就是以工作流引擎和简单xml为基础来完成商务工作流过程处理。
先决知识准备部分:
Osworkflow包括:
Oscore 2.0.1+
Propertryset 1.2+
Jakarta commons-logging
Beanshell(可选)
BSF(可选)
EJB接口(并不是一定要在EJB container中)
Xml解析(在jdk1.4中并不是必须的)
Osworkflow 的api部分将会支持jdk1.3+。GUI designer部分需要1.4的JVM。
关于soap和工作调度:GLUE部分(我还没接触过,不敢乱讲,大家看原英文解释部分吧。)大致意思是说如果需要soap或者远程作业调度支持的,就需要下载GLUE专业库。另外还有就是Quartz来支持。如果在应用服务器上run Quartz,那么就经过适当配置就不再需要GLUE了,但是必须把作业调度的local参数设置为true。
运行例子:
简单的部署没有什么特别说。仅仅把osworkflow所带的例子拷贝到tomcat(举例)的webapps下就可以了。所带的这个例子不需要配置什么DB,当然也就做不了持久性处理(即所有的所有都没存储到实际数据库中。)当然这并不是实际应用当中所想见到的,这个例子的意义就在于简单的理解osworkflow。
对于进行持久数据存储的例子在英文原件中有,我就不复制粘贴过来了。大家自己去看就可以了。具体都是如何修改配置文件,如果tomcat的server.xml文件,以及必要的jar拷贝工作。这些实际应用的例子会在后继文档中也许会有阐述,如果特别简单就不多写这方面东西了。感觉上不会复杂。呵呵^_^
持久存储:
Osworkflow共提供了五种存储机制:memorystore(默认)自带的例子就是如此,SerializableStore,JDBCStore,ofbizstore,和EJBStore.如果上述这些都没满足您的要求,那就得自己来实现osworkflow的接口com.opensymphony.workflow.spi.workflows了。具体看api吧。本文只是入门篇,大致知道有这么一回事的。
不同的存储实现需要不同的配置设置工作。推荐大家看api(此部分)来完成配置。原文中给出了JDBC的配置例子:
请参看原文。
工作流定义部分:
Osworkflow 尽最大可能使用配置来保证灵活度。仅一个文件osworkflow.xml需要在classpath中。这个文件设置了持久存储的方法(jdbc,ejb,ofbiz),工作流工厂类被用来加载工作流定义内容。
默认的工厂是:com.opensymphony.workflow.loader.xmlworkflowfactory。从classpath中加载文件。
在测试的时候,更改工作流定义文件然后重新加载它,你可以通过一个reload参数来指定是否完成自动重载。如果想指定自己的工作流定义,需要继承com.opensymphony.workflow.loader.Abstractworkflowfactory。然后剩下的就是你自己的任务了。
com.opensymphony.workflow.loader.JDBCWorkflowFactory是一个选择工厂,他允许你存储工作流定义为数据库内容而不是在xml文件中。
一般配置如下:
osworkflow.xml:
<osworkflow>
<persistence class="com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore">
<arg name="foo" value="bar"/>
...
</persistence>
<factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
<property key="resource" value="workflows.xml" />
</factory>
</osworkflow>
|
workflows.xml:
<workflows>
<workflow name="example" type="resource" location="example.xml"/>
</workflows>
|
理解osworkflow.xml:
加载osworkflow.xml过程:
1)DefaultConfiguration中,在load方法中调用getInputStream()以获取系统的osworkflow.xml文件
在getInputStream方法中:
protected InputStream getInputStream(URL url) {
InputStream is = null;
if (url != null) {
try {
is = url.openStream();
} catch (Exception ex) {
}
}
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (is == null) {
try {
is = classLoader.getResourceAsStream("osworkflow.xml");
} catch (Exception e) {
}
}
if (is == null) {
try {
is = classLoader.getResourceAsStream("/osworkflow.xml");
} catch (Exception e) {
}
}
if (is == null) {
try {
is = classLoader.getResourceAsStream("META-INF/osworkflow.xml");
} catch (Exception e) {
}
}
if (is == null) {
try {
is = classLoader.getResourceAsStream("/META-INF/osworkflow.xml");
} catch (Exception e) {
}
}
return is;
}
在load方法中
Document doc = db.parse(is); //开始解析由上面方法传递回来的流
然后可以看到接下来通过xml中指定的工厂类进行init
由上面代码可以看的出defaultconfiguration是如何加载osworkflow.xml的。
load()方法解析文件,并load相应的工厂类.
workflowFactory:
在loader包下提供了多种多种格式的factory,如xmlworkflowfactory、JDBCworkflowfactory、URLworkflowfactory、springworkflowfactory(在实际中jar包中没找到,但是在javadoc中确实有)等等。
这几种工厂类都是在各自的getWorkflow方法体内调用loadWorkflow方法。
private void loadWorkflow(WorkflowConfig c) throws FactoryException {
try {
c.descriptor = WorkflowLoader.load(c.url);
} catch (Exception e) {
throw new FactoryException("Error in workflow descriptor: " + c.url, e);
}
}
而实际调用的则是workflowloader.load方法。可以进一步跟踪到workflowloader中,可以看到如何是将descriptor返回的。
com.opensymphony.workflow.spi spi指server provider identification
在spi包中可以看到各种存储的子包
~~在load方法中将persistenceArgs参数返回会在上面这些包的类中进行处理……