昨天说了那么多,想必有些人对OSWorkFlow 有一个大体上的认识,但是还是不够详细,那么我们就对照着第一篇中的脑图进行逐个突破,先来说说最为重要的Step元素吧
一个workflow的实例是由一个或者多个step组成,在某一个特定的时刻,workflow可执行的step也存在一个或者多个,甚至会有并发执行的情况(split我们在后面介绍),先来看看step的结构,从他的dtd来看最合适不过了!
<!ELEMENT step (meta*, pre-functions?, external-permissions?, actions?, post-functions?)>
<!ATTLIST step
id CDATA #REQUIRED
name CDATA #REQUIRED
>
<!ELEMENT steps (step+)>从DTD的描述中可以看到steps必须有一个以上的step标签,而step中的元素详解如下:
1、meta:0~n个,主要起到解释的作用,没有很多实际的意义,比如你要描述这一段step代表什么,就可以填充meta标签;
2、pre-functions:0~1个,主要是在进入step之后,执行Action之前调用的函数,我们也会有专门的章节介绍这个标签,并且自己实现一个pre-functions。
3、external-permissions:0~1个,主要是进行外部权限的判断,比如我们在oswf中加入了角色之后,这个标签就会起到他的作用,在后文中介绍。
4、Actions:0~1个,进入step之后触发的动作,这也是我们在后面需要重点讲解的标签;
5、post-function:0~1个,主要是当step执行完之后需要触发的函数,在后文中同样需要讲解。
了解了上述标签的意思之后,我们来看看具体的例子,在一些具体的单元测试中,也许有些标签在这一章中并未涉及,但是不要太过担心,在后文中都会一一解释。
pre-function测试
<?xml version="1.0" encoding="UTF-8"?>看到了吗,我们在step1中配置了一个pre-functions,其中有一个function,类型为beanshell,参数为script,并且执行了propertySet.setString方法设置了preKey的值。上面的pre-function中包含了丰富的内容,首先在osworkflow中嵌入了beanshell,java脚本语言的执行引擎,因此我们可以动态执行beanshell的脚本,参数中propertySet为osworkflow的一个内置对象,我们在讲解源码的时候会说到这个东西,他是引用了另外一个开源项目PropertySet。
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd">
<workflow>
<initial-actions>
<action id="1" name="Start Workflow">
<results>
<unconditional-result old-status="Finished"
status="Underway" step="1" owner="step" />
</results>
</action>
</initial-actions>
<steps>
<step id="1" name="First Step">
<pre-functions>
<function type="beanshell" name="bsh.function">
<arg name="script">
propertySet.setString("prekey", "prevalue")
</arg>
</function>
</pre-functions>
<actions>
<action id="2" name="action2" finish="true">
<results>
<unconditional-result old-status="Finished" status="FinalFinished" step="-1"/>
</results>
</action>
</actions>
</step>
</steps>
</workflow>
解释完我们的配置之后,我们来说说我们要达到什么目的,我们在action执行之前执行了pre-function,那么是否在java代码中我们可以获取到prekey的值呢?并且必须在执行action之前,有这样的一个预期,我们就动手编写单元测试。
单元测试代码
package com.wangwenjun.osworkflow;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.opensymphony.workflow.InvalidActionException;
import com.opensymphony.workflow.InvalidEntryStateException;
import com.opensymphony.workflow.InvalidInputException;
import com.opensymphony.workflow.InvalidRoleException;
import com.opensymphony.workflow.Workflow;
import com.opensymphony.workflow.WorkflowException;
import com.opensymphony.workflow.basic.BasicWorkflow;
/**
* This class is for test step element on flow configuration.
* @author Alex(QQ:532500648)
*/
public class StepTest {
private Workflow wf = null;
@Before
public void init() {
wf = new BasicWorkflow("step");
}
@Test
public void testPreFunctionOnStep()
{
long id;
try {
id = wf.initialize("step", 1, null);
/*Determine the prekey value whether is equal*/
Assert.assertEquals("prevalue",wf.getPropertySet(id).getString("prekey"));
wf.doAction(id, 2, null);
/*after execute action*/
Assert.assertEquals("prevalue",wf.getPropertySet(id).getString("prekey"));
} catch (InvalidActionException e) {
e.printStackTrace();
} catch (InvalidRoleException e) {
e.printStackTrace();
} catch (InvalidInputException e) {
e.printStackTrace();
} catch (InvalidEntryStateException e) {
e.printStackTrace();
} catch (WorkflowException e) {
e.printStackTrace();
}
}
}
单元测试顺利通过,符合我们的预期,但是我们又执行了一下action,并且在action执行之后试图再次进行测试,我们发现结果也符合预期,其实这就是propertySet框架的作用,他就像hashMap一样,保留了很多key-value对。
post-function测试
稍微修改一下流程配置文件,在Actions标签之后增加如下的配置信息
<post-functions>针对上面的配置,我们期望得到的结果是,在执行action之前prekey的值为prevalue,当执行完action即将推出step时,prekey的值应该变为changed,看看junit测试代码吧
<function type="beanshell" name="bsh.function">
<arg name="script">
propertySet.setString("prekey", "changed")
</arg>
</function>
</post-functions>
@Test单元测试畅通无阻的执行,一路绿灯,我们的判断没有丝毫的问题,好了,我们在下一节中将会讲解如下几个标签
public void testPostFunctionOnStep()
{
long id;
try {
id = wf.initialize("step", 1, null);
/*Determine the prekey value whether is equal*/
Assert.assertEquals("prevalue",wf.getPropertySet(id).getString("prekey"));
wf.doAction(id, 2, null);
/*after execute action value not equals*/
Assert.assertFalse("prevalue".equals(wf.getPropertySet(id).getString("prekey")));
/*prevalue changed is our excepted.*/
Assert.assertEquals("changed",wf.getPropertySet(id).getString("prekey"));
} catch (InvalidActionException e) {
e.printStackTrace();
} catch (InvalidRoleException e) {
e.printStackTrace();
} catch (InvalidInputException e) {
e.printStackTrace();
} catch (InvalidEntryStateException e) {
e.printStackTrace();
} catch (WorkflowException e) {
e.printStackTrace();
}
}
1、join
2、split