OSWorkFlow深入浅出(7)---Step3详解

在《step2详解》中,我们介绍了split和join的使用,其实还是有一些细节的东西存在遗漏,所以决定增加着一个小节作为补充,在开始之前,我们先来思考两个问题

第一:在初始化之后是否就可以进行split操作

第二:split和join是否存在一些逻辑的影响,也就是说当某个条件成立执行split,当某个条件不成立则执行其他的step。

上述两种情况,在工作流中是最合理不过的需求了比如,我们就希望某个工作任务开启的瞬间,需要两个前置条件才能让他向下流转,我们也存在当提交某个申请时,通过与拒绝存在较大的差异,通过则需要split,拒绝则继续到某个step中。这样说也许有一点不太具象,我们通过状态图和配置文件以及测试代码来进行进一步的分析。


上面的图描述了一个从一开始就进入split的情况,然后当两个动作执行完毕之后,再一次合并,到了一个新的动作状态,我们通过配置文件和junit测试代码实现以下;

workflow的配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_6_1.dtd">

<workflow>
	<initial-actions>
		<action id="100" name="初始化">
			<results>
				<unconditional-result old-status="Finished"
					status="Underway" split="1" />
			</results>
		</action>
	</initial-actions>
	<steps>
		<step id="1" name="第一个步骤">
			<actions>
				<action id="1" name="你一个步骤的动作">
					<restrict-to>
						<conditions type="AND">
							<condition type="class">
								<arg name="class.name">
									com.opensymphony.workflow.util.StatusCondition
								</arg>
								<arg name="status">Underway</arg>
								<arg name="stepId">2</arg>
							</condition>
						</conditions>
					</restrict-to>
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" join="1" />
					</results>
				</action>
			</actions>
		</step>
		<step id="2" name="第二个步骤">
			<actions>
				<action id="2" name="第二个步骤的动作">
					<restrict-to>
						<conditions type="AND">
							<condition type="class">
								<arg name="class.name">
									com.opensymphony.workflow.util.StatusCondition
								</arg>
								<arg name="status">Underway</arg>
								<arg name="stepId">2</arg>
							</condition>
						</conditions>
					</restrict-to>
					<results>
						<unconditional-result old-status="Finished"
							status="Underway" join="1" />
					</results>
				</action>
			</actions>
		</step>

		<step id="3" name="结束了"></step>

	</steps>
	<splits>
		<split id="1">
			<unconditional-result old-status="Finished"
				status="Underway" step="1" />
			<unconditional-result old-status="Finished"
				status="Underway" step="2" />
		</split>
	</splits>
	<joins>
		<join id="1">
			<conditions type="AND">
				<condition type="beanshell">
					<arg name="script"><![CDATA[
"Finished".equals(jn.getStep(1).getStatus())
&& "Finished".equals(jn.getStep(2).getStatus())
          ]]></arg>
				</condition>
			</conditions>
			<unconditional-result old-status="Finished"
				status="Underway" owner="test" step="3" />
		</join>
	</joins>
</workflow>

Junit测试代码如下所示:

package com.wangwenjun.osworkflow;

import java.util.Collections;
import java.util.List;

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;
import com.opensymphony.workflow.spi.SimpleStep;
import com.opensymphony.workflow.spi.WorkflowEntry;

/**
 * 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 testJoinInInitial()
	{
		long id;
		try {
			id = wf.initialize("joinsplit2", 100, null);
			List currentSteps=wf.getCurrentSteps(id);
			/*由于一开始就拆分了两个,所以应该有两个可用的step*/
			Assert.assertEquals(2, currentSteps.size());
			/*执行其中的一个步骤动作*/
			wf.doAction(id, 1, null);
			
			/*当前的历史执行步骤有一个step对象*/
			List historySteps = wf.getHistorySteps(id);
			Assert.assertEquals(1, historySteps.size());
			
			/*执行完一个,应该还剩下另外一个*/
			currentSteps=wf.getCurrentSteps(id);
			Assert.assertEquals(1, currentSteps.size());
			
			wf.doAction(id, 2, null);
			/*
			 * 当前的历史执行步骤有两个step对象?
			 * 你错了,其实是三个,因为执行完毕2之后有进入了合并,然后理所当然的到了step3
			 * */
			historySteps = wf.getHistorySteps(id);
			Assert.assertEquals(3, historySteps.size());
			
			
		} catch (InvalidActionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidRoleException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidInputException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidEntryStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (WorkflowException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Test
	public void testJoinAndSplit()
	{
		long id ;
		try {
			id = wf.initialize("joinsplit", 100, null);
			List currentSteps = wf.getCurrentSteps(id);
			/*系统初始化之后只有一个step可以执行,那就是step,也就是请假单发起的步骤*/
			Assert.assertEquals(1, currentSteps.size());
			Assert.assertEquals(1,((SimpleStep)currentSteps.get(0)).getId());
			/*执行请假申请流程*/
			wf.doAction(id, 1, Collections.EMPTY_MAP);
			/*接下来应该到直接上级*/
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(1, currentSteps.size());
			/*直接上级的step为2*/
			Assert.assertEquals(2,((SimpleStep)currentSteps.get(0)).getId());
			/*获取执行历史*/
			List historySteps = wf.getHistorySteps(id);
			/*只有一个执行历史*/
			Assert.assertEquals(1, currentSteps.size());
			/*直接上级审批通过*/
			wf.doAction(id, 2, Collections.EMPTY_MAP);
			
			/*接下来应该到了两位部门领导哪里,因此需要执行的步骤应该有两个才对*/
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(2, currentSteps.size());
			
			/*部门领导A审批*/
			wf.doAction(id, 4, Collections.EMPTY_MAP);
			/*部门领导B审批*/
			wf.doAction(id, 5, Collections.EMPTY_MAP);
			
			/*接下来应该到了最高领导哪里,因此需要执行的步骤应该有1个才对*/
			
			currentSteps = wf.getCurrentSteps(id);
			Assert.assertEquals(1, currentSteps.size());
			/*最高领导审批*/
			wf.doAction(id, 6, Collections.EMPTY_MAP);
			/*流程执行完毕*/
			Assert.assertEquals(WorkflowEntry.COMPLETED, wf.getEntryState(id));
			
			historySteps = wf.getHistorySteps(id);
			Assert.assertEquals(5, historySteps.size());
		} 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();
		}
	}
	
/*	@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();
		}
	}*/
	
	@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();
		}
	}
}

好了,再来写一个Step结合split进行流程跳转的例子吧,如果大致懂了配置文件,下面的配置信息还是比较简单的,您一看就能明白

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE workflow PUBLIC
"-//OpenSymphony Group//DTD OSWorkflow 2.8//EN"
"http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">
<workflow>
  <initial-actions>
    <action id="1" name="Start Workflow">
      <results>
        <unconditional-result old-status="Finished" status="Queued" step="1"/>
      </results>
    </action>
  </initial-actions>
  <steps>
    <step id="1" name="First Part">
      <actions>
        <action id="2" name="Finish First Part">
          <results>
            <unconditional-result old-status="Finished" status="Queued" split="1"/>
          </results>
        </action>
      </actions>
    </step>
    <step id="2" name="Second Part">
      <actions>
        <action id="3" name="Back to First Part">
          <results>
            <unconditional-result old-status="Rejected" status="Queued" step="1"/>
          </results>
        </action>
        <action id="4" name="Finish">
          <results>
            <unconditional-result old-status="Finished" status="Queued" join="1"/>
          </results>
        </action>
      </actions>
    </step>
    <step id="3" name="Another Second Part">
      <actions>
        <action id="5" name="Back to First Part">
          <results>
            <unconditional-result old-status="Rejected" status="Queued" step="1"/>
          </results>
        </action>
        <action id="6" name="Finish">
          <results>
            <unconditional-result old-status="Finished" status="Queued" join="1"/>
          </results>
        </action>
      </actions>
    </step>
    <step id="4" name="End">
      <actions>
        <action id="7" name="Finish" finish="true">
          <results>
            <unconditional-result old-status="Finished" status="Game Over" step="4"/>
          </results>
        </action>
      </actions>
    </step>
  </steps>
  <splits>
    <split id="1">
      <unconditional-result old-status="Finished" status="Queued" step="2"/>
      <unconditional-result old-status="Finished" status="Queued" step="3"/>
    </split>
  </splits>
  <joins>
    <join id="1">
      <conditions type="AND">
        <condition type="beanshell">
          <arg name="script">
            "Finished".equals(jn.getStep(2).getStatus())
          </arg>
        </condition>
        <condition type="beanshell">
          <arg name="script">
            "Finished".equals(jn.getStep(3).getStatus())
          </arg>
        </condition>
      </conditions>
      <unconditional-result old-status="Finished" status="Queued" step="4"/>
    </join>
  </joins>
</workflow> 
执行的测试代码如下所示:

    public void testJoinNodesOrder() throws Exception {
        long id = workflow.initialize("orders", 1, null);
        workflow.doAction(id, 2, null);
        workflow.doAction(id, 3, null);
        workflow.doAction(id, 2, null);
        workflow.doAction(id, 4, null);
        workflow.doAction(id, 6, null);
        workflow.doAction(id, 7, null);
    }



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值