The important thing in life is to have a great aim , and the determination

常用链接

统计

IT技术链接

保险相关

友情链接

基金知识

生活相关

最新评论

一个Jbpm员工请假流程的实例(转载)

一个 Jbpm 员工请假流程的实例

 

 

作者:吴大愚

Email:dywu_xa@sina.com

2006-10-26

 

 

适用于 jbpm3.1 版本

1.   概述

此实例包括的是一个员工请假审批的流程实例,和流程相关的代码以及相应的测试代码。此流程在 Eclipse3.1.2 ,JBoss-IDE 1.6 环境下测试通过。

说明,这篇文章说使用的流程实例是,学习《一个 JBPM 工作流管理示例》文章中的流程而来。原文中的流程实例不是 jbpm3.1 版本,不能适用于 jbpm3.1 。本人将其改写,并加入自己的设计和实现。原文地址为 http://blogger.org.cn/blog/more.asp?name=lhwork&id=16137 。可以对照学习。

2.   流程说明

假设应用背景如下:

在某一公司中,部门员工要休假的话需要部门主管的批准。如果休假天数大于 10 天的话,在部门主管的同意后,还必须老板批准。如果是部门主管要休假只要老板批准即可。在休假被批准之前,申请人可以撤销休假申请。

每次休假申请结束之后,不管通过未通过或是否取消,都必须记录下来。主管在批复申请之后,系统要将批复结果 Email 给申请人。对于大于 10 天的申请,如果部门主管已批准同意而上级主管还未批准,这时申请人撤销申请后,系统应发 Email 通知部门主管申请已撤销。  

3.   流程定义

3.1. 原文件

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

<process-definition

  xmlns="urn:jbpm.org:jpdl-3.1"  name="MyRequest">

   <start-state name="SS_Request">

 

      <transition name="" to="TN_WriteRequest"></transition>

   </start-state>

   <task-node name="TN_WriteRequest">

      <task name="Task_WriteRequest">

         <controller>

            <variable name="dayCount" access="read,write,required"></variable>

         </controller>

         <assignment class="com.myrequest.task.WriteRequestAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_WriteLeave" to="Fork_request">

         <action name="Ac_WriteLeave" class="com.myrequest.action.WriteLeaveActionHandler"></action>

      </transition>

   </task-node>

   <fork name="Fork_request">

      <transition name="Tr_Cancel" to="TN_RequesterCancel"></transition>

      <transition name="Tr_Request" to="Deci_IsChiefHere">

         <action name="Ac_GetChiefState" class="com.myrequest.action.GetChiefStateActionHandler"></action>

      </transition>

   </fork>

   <decision name="Deci_IsChiefHere">

      <handler class="com.myrequest.decision.IsChiefHereDecisionHandler"/>

      <transition name="Tr_Chief" to="TN_ChiefDecide"></transition>

      <transition name="Tr_Boss" to="TN_BossDecide"></transition>

   </decision>

   <task-node name="TN_RequesterCancel">

      <task name="Task_CancelRequest">

         <assignment class="com.myrequest.task.CancelRequestAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_RequestCancel" to="Join_Request">

         <action name="Ac_RequestCancel" class="com.myrequest.action.RequestCancelActionHandler"></action>

      </transition>

   </task-node>

   <task-node name="TN_ChiefDecide">

      <task name="Task_ChiefDecide">

         <assignment class="com.myrequest.task.ChiefDecideAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_ChiefApprove" to="Deci_NeedBossDecide">

         <action name="Ac_ChiefApprove" class="com.myrequest.action.ChiefApproveActionHandler"></action>

      </transition>

      <transition name="Tr_ChiefNotApprove" to="Join_Request">

         <action name="Ac_ChiefNotApprove" class="com.myrequest.action.ChiefNotApproveActionHandler"></action>

      </transition>

   </task-node>

   <join name="Join_Request">

      <transition name="Tr_Join" to="Deci_DoSomething"></transition>

   </join>

   <decision name="Deci_NeedBossDecide">

      <handler class="com.myrequest.decision.NeedBossDecideDecisionHandler"/>     

      <transition name="Tr_Need" to="TN_BossDecide"></transition>

      <transition name="Tr_NotNeed" to="Join_Request">

         <action name="Ac_NotNeed" class="com.myrequest.action.NotNeedActionHandler"></action>

      </transition>

   </decision>

   <task-node name="TN_BossDecide">

      <task name="Task_BossDecide">

         <assignment class="com.myrequest.task.BossDecideAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_BossApprove" to="Join_Request">

         <action name="Ac_BossApprove" class="com.myrequest.action.BossApproveActionHandler"></action>

      </transition>

      <transition name="Tr_BossNotApprove" to="Join_Request">

         <action name="Ac_BossNotApprove" class="com.myrequest.action.BossNotApproveActionHandler"></action>

      </transition>

   </task-node>

   <decision name="Deci_DoSomething">

       <handler class="com.myrequest.decision.DoSomethingDecisionHandler"/>

      <transition name="Tr_Approve" to="ES_Finished">

         <action name="Ac_Approve" class="com.myrequest.action.ApproveActionHandler"></action>

      </transition>

      <transition name="Tr_NotApprove" to="ES_Finished">

         <action name="Ac_NotApprove" class="com.myrequest.action.NotApproveActionHandler"></action>

      </transition>

      <transition name="Tr_Cancel" to="ES_Finished">

         <action name="Ac_Cancel" class="com.myrequest.action.CancelActionHandler"></action>

      </transition>

   </decision>

   <end-state name="ES_Finished">

                     <event type="node-enter">

                            <action name="Ac_Finished" class="com.myrequest.action.FinishedActionHandler"></action>

                     </event>

   </end-state>

</process-definition>

3.2. 流程图片

3.3. 说明

3.3.1.     命名规则

start-state 的定义为 SS_

end-state 的定义为 ES_

task-node 的定义为 TN_

fork 的定义为 Fork_

join 的定义为 Join_

task 的定义为 Task_

transition 的定义为 Tr_

action 的定义为 Ac_

3.3.2.     join 节点类型

join 结点 Join_Request ,采用的是 Discriminator 模式,即只要有一个 fork 发出的分支到达 join ,流程就可以向下进行。

Join 共有三中模式:

l          默认的是所有 fork 发出的分支都到达,流程才向下进行;

l          第二种就是 Discriminator 模式,只要有一个 fork 发出的分支到达 join ,流程就可以向下进行;

l          第三种是设置当有 n 个分支到达之后,流程就可以向下进行。

jpdl 语言在 jbpm3.1 版本中还不支持对第二,第三两种模式的设置。需要在流程实例化之后,来制定 join 的模式。具体如何实现,参见后面有关代码部分。

3.3.3.     申请状态

系统存在一个有关申请的状态。系统用流程变量 RequestState 来存储。共有五个状态。存储在 com.myrequest.RequestState.java 文件中。

在用户启动此请假流程,完成第一个填写请假申请的任务实例后,此状态置为 REQUEST 。在完成取消请求任务之后,状态改为 CANCEL 。等等,读者可以仔细阅读流程定义和对应的代码。

要说明的是所有的状态修改都在完成任务之后的边上执行 Action 中来修改的。这样虽然增加了很多 Action ,但是状态修改明确。但对于这样的简单问题,前台代码在实际任务完整之后,就可以调用修改此状态变量。此处将这些修改都放在 Action 里面,也有一定演示的含义。

3.3.4.     取消请假任务说明

fork 节点后,产生两个并行分支。其中一个 TN_RequestCancel 任务节点包含一个 Task_CancelRequest 的任务。当此分支执行到这里时,会把这个任务分配给启动流程的用户。在流程没有结束的时候,如果用户执行这个任务,就表示用户要取消请假申请。在这个取消申请的任务会修改请假状态,在此任务结束后,就会首先到达 join 节点。表示取消了此次申请操作。

4.   代码说明

4.1. 代码包结构

本实例是在 Eclipse3.1.2 里面实现的。

src/java 目录下面,有包 :

l          com.myrequest

n          存放流程的公共信息,包括:

n          interface RequestState ,用来存放请求状态的 5 种状态

n          interface RequestVariable 存放流程实例的变量名

l          com.myrequest.action

n          存放流程中所有的 ActionHandler

n          共有 12 个类,每个类对应流程中一个 action 的代码。

l          com.myrequest.task

n          存放流程中所有的 task AssignmentHandler 分配类

n          共有 4 个类,对应 4 task

l          com.myrequest.decision

n          存放流程中所有的 decision 节点的判断类

n          包括 3 个类,对应 3 Decision 节点

src/test 目录下面,有包:

l          com.myrequest

n          包含此流程的测试类 MyRequestProcessTest.java

processes 目录下面,有:

l          流程定义文件夹 MyRequest ,包含:

n          Gpd.xml

n          Processdefinition.xml

n          Processimage.jpg

4.2. 流程代码说明

对流程中使用到的和 Action task decision 相关的类,以及测试类进行说明。

4.2.1.     Action 代码说明

流程中的 Action 都使用指定类的形式来完成 Action 的操作。

例如:

<transition name="Tr_WriteLeave" to="Fork_request">

<action name="Ac_WriteLeave" class="com.myrequest.action.WriteLeaveActionHandler"></action>

</transition>

当流程执行到边 Tr_WriteLeave 后,就会自动去执行 Action 里面指定的类 WriteLeaveActionHandler

WriteLeaveActionHandler 实现了接口 ActionHandler 。此接口就一个函数

public void execute(ExecutionContext executionContext)

当流程执行这个类的时候,就会去调用这个函数。所以我们 Action 所要完成的工作也都写在这个函数中。

RequestBeginActionHandler.execute() 中,我们只做了将整个流程的请求状态设置为 REQEUST 状态。

4.2.2.     Task 代码说明

所有 Task 都是在 Task-node 中描述的。 Task 都是人工任务,也就是说需要先将 task 分配给那个人,然后由这个人来完成。在人开始任务的时候,可以调用 taskInstance start() 操作,表明任务开始。( start ()操作是可选的,也可以不调用) 在任务结束后,可以调用 taskInstance end() 操作,表示任务实例结束。如果是整个 task-node 中的最后一个 task end() 操作,那么就会这个 end 操作就会触发流程继续向下走。

例如:

<task name="Task_WriteRequest">

<controller>

   <variable name="dayCount" access="read,write,required"></variable>

</controller>

<assignment class="com.myrequest.task.WriteRequestAssignmentHandler"></assignment>

</task>

当流程实例化 Task_WriteRequest 这个 task 后,首先会使用 WriteRequestAssignmentHandler 类来进行任务的分配。 WriteRequestAssignmentHandler 类实现了 AssignmentHandler 接口,包含一个
public void assign(Assignable assignable, ExecutionContext executionContext)
接口。其中参数 assignable 就是此任务实例的引用( TaskInstance 实现了 Assignable 接口)。因此我们只要调用 assignable.setActorId(String userid) ,就可以把这个任务分配给 userid 所代表的用户来执行了。

				
						
								
										    
								对于前台,当用户登陆后,通过org.jbpm.db.TaskMgmtSession.findTaskInstances(java.lang.String actorId)就可以得到当前用户所有要执行的任务了,这里的任务是属于多个不同的流程实例的。如果查看数据库就会发现在jbpm_taskInstance表中,每一个taskinstanceactorId_字段记录的是次任务实例分配人员的用户名。这也就是上面所说的findTaskInstances方法如何工作的关键之处。
				
		
				
						
								
										
								
								WriteRequestAssignmentHandler .assign()里面,我们首先读入流程变量userId,然后将任务分配给这个userId
				
		
				
						
								
										    
								如何调用任务实例的end,来表示任务实例的完成呢?真正的系统中应该是在前台,当客户通过web或是客户端触发操作,然后执行对应的任务实例的end操作。但是在我们的代码中只能通过在junit的测试代码中来模拟。具体参见后面讲解测试代码部分。
				
		

4.2.3.     Decision 代码说明

Decision 节点可以有多种方式来进行条件判断。

方法一是在每条出边上加一个 beanshell 的表达式, jbpm 引擎会按照流程定义文档中边的顺序一次调用,来判断那个表达式为 true ,当发现第一个为 true 的时候,流程就走这条边了。

方法二就是对 Decision 节点配置一个 handler 。通过一个类来实现条件判断。

 

例如:

   <decision name="Deci_IsChiefHere">

      <handler class="com.myrequest.decision.IsChiefHereDecisionHandler"/>

      <transition name="Tr_Chief" to="TN_ChiefDecide"></transition>

      <transition name="Tr_Boss" to="TN_BossDecide"></transition>

   </decision>

表示当执行到 Deci_IsChiefHere 节点后,会自动执行 IsChiefHereDecisionHandler 类。 IsChiefHereDecisionHandler 实现了 DecisionHandler 接口。此接口包含一个方法 public String decide(ExecutionContext executionContext) throws Exception 这个方法应该返回一个 transition name ,表示选择走那条边。

IsChiefHereDecisionHandler.decide() 操作中,我们首先读取流程变量 isChiefHere ,然后判断走那条边。

4.3. 流程测试类代码说明

4.3.1.     测试类整体说明

测试类为 com.myrequest. MyRequestProcessTest

包含三个设施函数,分别为

l          test14DayAndBossNotApprove()

n          测试员工申请 14 天假期,部门主管批准,但老板不批准

l          test4DayAndChiefApprove()

n          测试员工申请 14 天假期,部门主管批准,(不需要老板批准)

l          test14DayAndChiefApproveAndUserCancel()

n          测试员工申请 14 天假期,部门主管批准,在老板审批前员工自己撤销申请

 

每个测试前都执行 setUp() 操作,这个操作用来设置流程中两个变量,一个是用户 id ,另外一个是部门主管是否在岗的状态。可以修改这两个参数,进行不同的测试。尤其是第二个参数,会影响流程的走向,可以分别设置为 true false 以观察流程的走向和结果。

 

在测试类中还有 7 个辅助函数。分别为:

l          deployProcessDefinition()

n          流程部署

l          createProcessInstance()

n          创建流程实例

n          设置 join 节点的性质为 Discriminator 模式(参见流程定义部分)

n          设置流程相关变量

n          启动流程

l          userWriteRequest(int daycount)

n          模拟申请员工完成 Task_WriteRequest 任务,参数为请假的天数

l          chiefDecide(boolean isApprove)

n          模拟部门主管完成 Task_ ChiefDecide 任务,参数为部门主管是否批准

l          bossDecide(boolean isApprove)

n          模拟老板完成 Task_ BossDecide 任务,参数为老板是否批准

l          userCancel()

n          模拟申请员工完成 Task_ CancelRequest 任务

l          checkTasks()

n          检查整个流程中所有的任务的相关信息

4.3.2.     checkTasks() 说明

checkTasks() 的核心是 pi.getTaskMgmtInstance().getTaskInstances(); 返回流程实例的所有任务实例列表。但要说明的是所返回的任务实例列表和当前流程执行的位置有关,在流程开始处,流程执行中间,和流程执行结束处调用得到的任务实例列表不同。列表包含已经完成的任务实例和当前任务实例。

本来在此方法中还有现实每个任务实例起始时间和结束时间的操作。但发现返回全部为 null 。这说明在没有使用数据库是,有关时间的属性是不可用的。也就是说,这些时间属性都是记录在数据库 jbpm_taskInstance 表中的。没有用数据库自然就得不到,它不会保留在内存的流程实例中。要说明的是 jbpm_taskInstance 表的 start 字段如果有时间,表示任务实例已经开始执行。如果 end 字段有时间,表示任务实例已经结束,此任务已经完成。

4.3.3.     测试中有关任务实例获取的说明

因为没有使用数据库,所以不能使用 org.jbpm.db.TaskMgmtSession.findTaskInstances(java.lang.String actorId) 得到不同用户的当前任务。所以只能便利当前流程实例任务列表,从中找到相应的任务来操作。

如果有人有更好的办法,请留言告知,谢谢:)

5.   实例不足和待学习地方

5.1. 不足

没有使用 swimlane ,可以添加 swimlane 来进行任务分配。像 websale 就是有角色的。主要的原因是对 swimlane 的使用我还没有搞清楚。我有关 swimlane 的学习心得会在下一篇对 jbpm 自带实例 websale 的分析中来描述。

5.2. 学习点

				
						
								
										    
								
						
						通过这个实例,我发现
				
				org.jbpm.module.exe.ModuleInstance
				
						类有很多创建任务实例的方法,例如
				
				createTaskInstance(Task task)
				
						等等。我一直认为任务的实例化是在流程执行过程中,又工作流引擎来做的工作。不知道在我们写的代码中需要用到创建流程这样的方法吗?如果要用的话,在什么情况下会用到呢?
						
								
								
						
				
		
				
						       
						
						
				
		
				
						       
				
				
						此外还有很多问题没有搞懂,比如
				
				jbpm
				
						的模块化思想,它的
				
				Ioc
				
						实现等等。慢慢学习吧。
				
		

6.   完整代码

代码太多,贴还是不贴呢,这是个问题啊。

 

6.1. MyRequestProcessTest

package com.myrequest;

 

import org.jbpm.graph.node.*;

import java.io.FileInputStream;

import java.util.*;

 

import org.jbpm.graph.def.ProcessDefinition;

import org.jbpm.graph.exe.ProcessInstance;

import org.jbpm.taskmgmt.*;

import org.jbpm.identity.*;

import org.jbpm.context.exe.ContextInstance;

import org.jbpm.taskmgmt.exe.*;

 

import junit.framework.TestCase;

 

import com.myrequest.*;

 

 

public class MyRequestProcessTest extends TestCase {

       //static JbpmConfiguration cfg = JbpmConfiguration.getInstance();

       ProcessDefinition pdf ;

       ProcessInstance pi;      

       String userId;

       boolean isChiefHere;

      

       public void setUp(){

              userId = "dust";

              isChiefHere=true;

       }

       public void test14DayAndBossNotApprove() throws Exception {            

              this.deployProcessDefinition() ;

              this.createProcessInstance() ;

              this.userWriteRequest(14) ;

              this.chiefDecide(true) ;

              this.bossDecide(false);

              this.checkTasks();        

       }

       public void test4DayAndChiefApprove() throws Exception {            

              this.deployProcessDefinition() ;

              this.createProcessInstance() ;

              this.userWriteRequest(4) ;

              this.chiefDecide(true) ;

              this.checkTasks();        

       }

       public void test14DayAndChiefApproveAndUserCancel() throws Exception {         

              this.deployProcessDefinition() ;

              this.createProcessInstance() ;

              this.userWriteRequest(14) ;

              this.chiefDecide(true) ;

              this.userCancel();

              this.checkTasks();        

       }

      

       protected void deployProcessDefinition() throws Exception{

             

              System.out.println("==MyRequestProcessTest.deployProcessDefinition()==");

              FileInputStream fis = new FileInputStream("processes/MyRequest/processdefinition.xml");

              pdf = ProcessDefinition.parseXmlInputStream(fis);

              assertNotNull("Definition should not be null", pdf);       

       }

 

       protected void createProcessInstance() throws Exception{

              System.out.println("==MyRequestProcessTest.createProcessInstance()==");

              assertNotNull("Definition should not be null", pdf);

              pi = new ProcessInstance(pdf);

              assertNotNull("processInstance should not be null", pi);

             

              Join join_Request = (Join)pi.getProcessDefinition().getNode("Join_Request");

              assertNotNull("should find join_request node !",join_Request);

              join_Request.setDiscriminator( true);

              // 设置申请人

              pi.getContextInstance() .createVariable(RequestVariable.userId,this.userId);

              // 设置流程运行是,部门主管是否在岗

              pi.getContextInstance() .createVariable(RequestVariable.isChiefHere,new Boolean(this.isChiefHere));

              // 启动流程

              pi.getRootToken().signal();   

             

       }

       /**

        * @param daycount  请假天数

        * */

       protected void userWriteRequest(int daycount){

              System.out.println("==MyRequestProcessTest.userWriteRequest()==");

              TaskInstance wr = (TaskInstance)pi.getTaskMgmtInstance().getTaskInstances().iterator() .next() ;

              assertEquals(this.userId,wr.getActorId()) ;

              ContextInstance ci = pi.getContextInstance();

              ci.setVariable("dayCount",new Integer(daycount));

              wr.end();

       }

       /**

        * @param isApprove 部门主管是否同意请假

        * */

       protected void chiefDecide(boolean isApprove){

              System.out.println("==MyRequestProcessTest.chiefDecide()==");

              //String chiefId="today123";

              /**

               * 如果后台使用数据库的话,就可以使用

               * org.jbpm.db.TaskMgmtSession.findTaskInstances(java.lang.String actorId) 得到所有分配给 chiefId taskInstance

               * */

              Collection coll = pi.getTaskMgmtInstance().getTaskInstances();

              Iterator it = coll.iterator();

              while(it.hasNext()){

                     TaskInstance ti = (TaskInstance)it.next();

                     if(ti.getName().equals("Task_ChiefDecide")){

                            assertEquals("today123",ti.getActorId());

                            if(isApprove)

                                   ti.end("Tr_ChiefApprove");

                            else

                                   ti.end("Tr_ChiefNotApprove");

                            return;

                     }

              }

             

       }

      

       /**

        * @param isApprove 老板是否同意请假

        * */

       protected void bossDecide(boolean isApprove){

              System.out.println("==MyRequestProcessTest.bossDecide()==");

              //String bossId="elena";

              /**

               * 如果后台使用数据库的话,就可以使用

               * org.jbpm.db.TaskMgmtSession.findTaskInstances(java.lang.String actorId) 得到所有分配给 bossId taskInstance

               * */      

              Collection coll = pi.getTaskMgmtInstance().getTaskInstances();

              Iterator it = coll.iterator();

              while(it.hasNext()){

                     TaskInstance ti = (TaskInstance)it.next();

                     if(ti.getName().equals("Task_BossDecide")){

                            assertEquals("elena",ti.getActorId());

                            if(isApprove)

                                   ti.end("Tr_BossApprove");

                            else

                                   ti.end("Tr_BossNotApprove");

                            return;

                     }

              }

       }

       protected void userCancel(){

              System.out.println("==MyRequestProcessTest.userCancel()==");

              /**

               * 如果后台使用数据库的话,就可以使用

               * org.jbpm.db.TaskMgmtSession.findTaskInstances(java.lang.String actorId) 得到所有分配给 userid taskInstance

               * */      

              Collection coll = pi.getTaskMgmtInstance().getTaskInstances();

              Iterator it = coll.iterator();

              while(it.hasNext()){

                     TaskInstance ti = (TaskInstance)it.next();

                     if(ti.getName().equals("Task_CancelRequest")){

                            assertEquals(this.userId,ti.getActorId());

                            ti.end();

                            return;

                     }

              }

       }

      

       protected void checkTasks(){      

              System.out.println("==MyRequestProcessTest.checkTasks()==");

              Collection coll = pi.getTaskMgmtInstance().getTaskInstances();

              Iterator it = coll.iterator();

              System.out.println("====Process has task:====");

              while(it.hasNext()){

                     TaskInstance ti = (TaskInstance)it.next();

                     System.out.println("=="+ti.getName()+"==");

                     System.out.println("=="+ti.getActorId()+"==");

                     System.out.println("=="+ti.getVariables().toString() +"==");

              }

              System.out.println("====end====");  

       }    

}

6.2. ApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.*;

 

public class ApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

             

              System.out.println("==ApproveActionHandler.execute()==");

              String user =(String)executionContext.getContextInstance().getVariable(RequestVariable.userId);

              int dayCount = ((Integer)executionContext.getContextInstance().getVariable(RequestVariable.dayCount)).intValue();

              /**

               * 发送邮件给申请人 user ,告知其请假被批准。

               *

               * */

              System.out.println("== 发送邮件给 "+user+" ,告知其 "+dayCount+" 天的请假申请,已经被批准。 ==");

       }    

}

6.3. BossApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

import com.myrequest.*;

public class BossApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.APPROVE );

              System.out.println("==BossApproveActionHandler.execute()==");

       }

 

}

6.4. BossNotApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

import com.myrequest.*;

public class BossNotApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.DISAPPROVE );

              System.out.println("==BossNotApproveActionHandler.execute()==");

       }

 

}

6.5. CancelActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.RequestVariable;

import com.myrequest.*;

public class CancelActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              System.out.println("==CancelActionHandler.execute()==");

              String user =(String)executionContext.getContextInstance().getVariable(RequestVariable.userId);

              // 如果取消的时候,部门主管已经批准过,那么需要给部门主管发送邮件,通知其请假已经取消

              if(executionContext.getContextInstance().hasVariable(RequestVariable.isChiefHere) && ((Boolean)executionContext.getContextInstance().getVariable(RequestVariable.isChiefHere)).booleanValue()){

                     int dayCount = ((Integer)executionContext.getContextInstance().getVariable(RequestVariable.dayCount)).intValue();

              // 通过 user 找到对应的 chief

              /**

               * 发送邮件给 chief ,告知其请假被批准。

               *

               * */

              System.out.println("== 发送邮件给部门主管,告知其部门员工 "+user+" "+dayCount+" 天请假申请,已经取消。 ==");

              }

       }

}

6.6. ChiefApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.RequestState;

import com.myrequest.RequestVariable;

import com.myrequest.*;

public class ChiefApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.CHIEFAPPROVE );

              System.out.println("==ChiefApproveActionHandler.execute()==");

 

       }

 

}

6.7. ChiefNotApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

import com.myrequest.*;

public class ChiefNotApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.DISAPPROVE );

              System.out.println("==ChiefNotApproveActionHandler.execute()==");

 

       }

 

}

6.8. FinishedActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.*;

 

public class FinishedActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              System.out.println("==FinishedActionHandler.execute()==");

              String user = (String)executionContext.getContextInstance().getVariable( RequestVariable.userId);

              Integer dayCount = (Integer)executionContext.getContextInstance().getVariable( RequestVariable.dayCount);

              String requestState = (String)executionContext.getContextInstance().getVariable( RequestVariable.requestState);

             

              /**

               * 将上述信息进行记录,保存每一次员工请假的信息,无论是否批准还是取消请求

               *

               * */

              System.out.print("== 在系统中记录: "+user+" ,申请请假 "+dayCount+" 天, ");

              if(requestState.compareTo(RequestState.APPROVE)==0)

                     System.out.print(" 被批准。 ");

              else if(requestState.compareTo(RequestState.DISAPPROVE)==0)

                     System.out.print(" 未被批准。 ");

              else if(requestState.compareTo(RequestState.CANCLE)==0)

                     System.out.print(" 已取消。 ");

              else{                    

                     System.out.println("");

                     System.out.println("==== 系统出现问题,最终申请状态为: "+requestState+"====");

                     System.out.println("");

              }

             

              System.out.println("==");

 

       }

 

}

6.9. NotApproveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.RequestVariable;

 

public class NotApproveActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              System.out.println("==NotApproveActionHandler.execute()==");

              String user =(String)executionContext.getContextInstance().getVariable(RequestVariable.userId);

              int dayCount = ((Integer)executionContext.getContextInstance().getVariable(RequestVariable.dayCount)).intValue();

             

              /**

               * 发送邮件给申请人 user ,告知其请假没有被批准。

               *

               * */

              System.out.println("== 发送邮件给 "+user+" ,告知其 "+dayCount+" 天的请假申请,没有被批准。 ==");

       }

 

}

6.10.    NotNeedActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

import com.myrequest.*;

public class NotNeedActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.APPROVE );

              System.out.println("==NotNeedActionHandler.execute()==");

       }

 

}

6.11.    RequestCancelActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

import com.myrequest.*;

public class RequestCancelActionHandler implements ActionHandler {

 

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              String requestState = (String)executionContext.getContextInstance().getVariable(RequestVariable.requestState);

             

              // 只有两种状态下允许撤销

              if(requestState.compareTo(RequestState.REQEUST)==0 || requestState.compareTo(RequestState.CHIEFAPPROVE)==0 ){

                    

                     // 如果撤销请求的时候,请求状态为“部门主管批准”状态

                     if(requestState.compareTo(RequestState.CHIEFAPPROVE)==0){

                            executionContext.getContextInstance().createVariable(RequestVariable.isChiefHere,new Boolean(true));

                     }                  

                     executionContext.getContextInstance().setVariable(RequestVariable.requestState,RequestState.CANCLE );

              }

              else{

                     System.out.println("==can't canel request==");

              }

             

              System.out.println("==RequestCancelActionHandler.execute()==");

       }

 

}

6.12.    WriteLeaveActionHandler

package com.myrequest.action;

 

import org.jbpm.graph.def.ActionHandler;

import org.jbpm.graph.exe.ExecutionContext;

 

import com.myrequest.RequestState;

import com.myrequest.RequestVariable;

import com.myrequest.*;

 

public class WriteLeaveActionHandler implements ActionHandler {

 

       /**

        * 设置请假状态为请求

        * */

       public void execute(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              // 设置请求状态为请求

              executionContext.getContextInstance().createVariable(RequestVariable.requestState,RequestState.REQEUST);

              System.out.println("==RequestBeginActionHandler.execute()==");

       }

 

}

6.13.    DoSomethingDecisionHandler

package com.myrequest.decision;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.graph.node.DecisionHandler;

import com.myrequest.*;

public class DoSomethingDecisionHandler implements DecisionHandler {

 

      

       public String decide(ExecutionContext executionContext) throws Exception {

 

             

              String requestState = (String)executionContext.getContextInstance().getVariable(RequestVariable.requestState);

              if(requestState.compareTo(RequestState.APPROVE)==0){

                     return "Tr_Approve";

              }

              else if(requestState.compareTo(RequestState.DISAPPROVE)==0){

                     return "Tr_NotApprove";

              }

              else if(requestState.compareTo(RequestState.CANCLE)==0){

                     return "Tr_Cancel";

              }    

              else{

                    

                     System.out.println("== 状态不对 ==");

                     throw new Exception(" 到达的状态不对,为 :"+requestState);

              }

       }

 

}

6.14.    IsChiefHereDecisionHandler

package com.myrequest.decision;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.graph.node.DecisionHandler;

 

import com.myrequest.RequestVariable;

 

public class IsChiefHereDecisionHandler implements DecisionHandler {

 

       public String decide(ExecutionContext executionContext) throws Exception {

              /**

               * 根据主管是否休假来判断走哪条边

               * */

              System.out.println("==IsChiefHereDecisionHandler.decide()==");

              // 主管在

              if(((Boolean)executionContext.getContextInstance().getVariable(RequestVariable.isChiefHere)).booleanValue())

                    

                     return "Tr_Chief";

              else

                     return "Tr_Boss";

       }

}

6.15.    NeedBossDecideDecisionHandler

package com.myrequest.decision;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.graph.node.DecisionHandler;

 

import com.myrequest.*;

 

public class NeedBossDecideDecisionHandler implements DecisionHandler {

 

       public String decide(ExecutionContext executionContext) throws Exception {

              // TODO Auto-generated method stub

              int dayCount =((Integer)executionContext.getContextInstance().getVariable(RequestVariable.dayCount)).intValue();

              int dayLevel= 10;// 是否需要 boss 批准的分界

              if(dayCount>=dayLevel){

                     return "Tr_Need";

              }

              else{

                     return "Tr_NotNeed";

              }

             

       }

 

}

6.16.    BossDecideAssignmentHandler

package com.myrequest.task;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.taskmgmt.def.AssignmentHandler;

import org.jbpm.taskmgmt.exe.Assignable;

 

public class BossDecideAssignmentHandler implements AssignmentHandler {

 

       public void assign(Assignable assignable, ExecutionContext executionContext)

                     throws Exception {

              // TODO Auto-generated method stub

              /**

               * 以角色 boss 到数据库中查找,找到 userid elena

               * */

              String bossId="elena";

              //elena is boss

              assignable.setActorId(bossId);

       }

 

}

6.17.    CancelRequestAssignmentHandler

package com.myrequest.task;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.taskmgmt.def.AssignmentHandler;

import org.jbpm.taskmgmt.exe.Assignable;

 

import com.myrequest.*;

 

public class CancelRequestAssignmentHandler implements AssignmentHandler {

 

       public void assign(Assignable assignable, ExecutionContext executionContext)

                     throws Exception {

              // TODO Auto-generated method stub

 

              String userid=(String)executionContext.getContextInstance() .getVariable(RequestVariable.userId);

              /**

               * 撤销请假请求任务可以由请假发起人执行, demo 里面是 dust

               * */

              assignable.setActorId(userid);

             

              System.out.println("==assign user is:"+userid+" ==");

              System.out.println("==CancelRequestAssignmentHandler.assign()==");

       }

 

}

6.18.    ChiefDecideAssignmentHandler

package com.myrequest.task;

 

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.taskmgmt.def.AssignmentHandler;

import org.jbpm.taskmgmt.exe.Assignable;

 

import com.myrequest.*;

 

public class ChiefDecideAssignmentHandler implements AssignmentHandler {

 

       public void assign(Assignable assignable, ExecutionContext executionContext)

                     throws Exception {

              // TODO Auto-generated method stub

              String userid=(String)executionContext.getContextInstance().getVariable( RequestVariable.userId);

        /**

         * 通过 userid 得到 user 的上级 chief 是谁,这里假设是 today123

         * */             

              String chiefId ="today123";

             

              assignable.setActorId(chiefId);

             

              System.out.println("==assign user is:"+userid+" ==");

              System.out.println("==ChiefDecideAssignmentHandler.assign()==");

 

       }

 

}

6.19.    WriteRequestAssignmentHandler

package com.myrequest.task;

 

import com.myrequest.*;

import org.jbpm.graph.exe.ExecutionContext;

import org.jbpm.taskmgmt.def.AssignmentHandler;

import org.jbpm.taskmgmt.exe.Assignable;

 

public class WriteRequestAssignmentHandler implements AssignmentHandler {

 

       public void assign(Assignable assignable, ExecutionContext executionContext)

                     throws Exception {

              // TODO Auto-generated method stub

              String userid =(String)executionContext.getContextInstance().getVariable(RequestVariable.userId);

             

              assignable.setActorId(userid);

              System.out.println("==assign user is:"+userid+" ==");

              System.out.println("==WriteRequestAssignmentHandler.assign()==");

 

       }

 

}

6.20.    RequestState

package com.myrequest;

 

public interface RequestState {

 

       final static String REQEUST="request";

       final static String APPROVE="approve";

       final static String DISAPPROVE="disapprove";

       final static String CANCLE="cancel";

       final static String CHIEFAPPROVE="chiefapprove";

      

}

6.21.    RequestVariable

package com.myrequest;

 

public interface RequestVariable {

      

       // 请求状态

       final static String requestState="RequestState";

       // 主管是否在岗

       final static String isChiefHere="isChiefHere";

       // 要请假的日期天数

       final static String dayCount = "dayCount";

       // 启动流程,也就是要申请请假的工人的 id

       final static String userId ="userId";

       // 部门主管是否同意

       final static String isChiefApprove="isChiefApprove";

      

 

}

6.22.    Processdefinition.xml

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

<process-definition

  xmlns="urn:jbpm.org:jpdl-3.1"  name="MyRequest">

   <start-state name="SS_Request">

 

      <transition name="" to="TN_WriteRequest"></transition>

   </start-state>

   <task-node name="TN_WriteRequest">

      <task name="Task_WriteRequest">

         <controller>

            <variable name="dayCount" access="read,write,required"></variable>

         </controller>

         <assignment class="com.myrequest.task.WriteRequestAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_WriteLeave" to="Fork_request">

         <action name="Ac_WriteLeave" class="com.myrequest.action.WriteLeaveActionHandler"></action>

      </transition>

   </task-node>

   <fork name="Fork_request">

      <transition name="Tr_Cancel" to="TN_RequesterCancel"></transition>

      <transition name="Tr_Request" to="Deci_IsChiefHere"></transition>

   </fork>

   <decision name="Deci_IsChiefHere">

      <handler class="com.myrequest.decision.IsChiefHereDecisionHandler"/>

      <transition name="Tr_Chief" to="TN_ChiefDecide"></transition>

      <transition name="Tr_Boss" to="TN_BossDecide"></transition>

   </decision>

   <task-node name="TN_RequesterCancel">

      <task name="Task_CancelRequest">

         <assignment class="com.myrequest.task.CancelRequestAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_RequestCancel" to="Join_Request">

         <action name="Ac_RequestCancel" class="com.myrequest.action.RequestCancelActionHandler"></action>

      </transition>

   </task-node>

   <task-node name="TN_ChiefDecide">

      <task name="Task_ChiefDecide">

         <assignment class="com.myrequest.task.ChiefDecideAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_ChiefApprove" to="Deci_NeedBossDecide">

         <action name="Ac_ChiefApprove" class="com.myrequest.action.ChiefApproveActionHandler"></action>

      </transition>

      <transition name="Tr_ChiefNotApprove" to="Join_Request">

         <action name="Ac_ChiefNotApprove" class="com.myrequest.action.ChiefNotApproveActionHandler"></action>

      </transition>

   </task-node>

   <join name="Join_Request">

      <transition name="Tr_Join" to="Deci_DoSomething"></transition>

   </join>

   <decision name="Deci_NeedBossDecide">

      <handler class="com.myrequest.decision.NeedBossDecideDecisionHandler"/>     

      <transition name="Tr_Need" to="TN_BossDecide"></transition>

      <transition name="Tr_NotNeed" to="Join_Request">

         <action name="Ac_NotNeed" class="com.myrequest.action.NotNeedActionHandler"></action>

      </transition>

   </decision>

   <task-node name="TN_BossDecide">

      <task name="Task_BossDecide">

         <assignment class="com.myrequest.task.BossDecideAssignmentHandler"></assignment>

      </task>

      <transition name="Tr_BossApprove" to="Join_Request">

         <action name="Ac_BossApprove" class="com.myrequest.action.BossApproveActionHandler"></action>

      </transition>

      <transition name="Tr_BossNotApprove" to="Join_Request">

         <action name="Ac_BossNotApprove" class="com.myrequest.action.BossNotApproveActionHandler"></action>

      </transition>

   </task-node>

   <decision name="Deci_DoSomething">

       <handler class="com.myrequest.decision.DoSomethingDecisionHandler"/>

      <transition name="Tr_Approve" to="ES_Finished">

         <action name="Ac_Approve" class="com.myrequest.action.ApproveActionHandler"></action>

      </transition>

      <transition name="Tr_NotApprove" to="ES_Finished">

         <action name="Ac_NotApprove" class="com.myrequest.action.NotApproveActionHandler"></action>

      </transition>

      <transition name="Tr_Cancel" to="ES_Finished">

         <action name="Ac_Cancel" class="com.myrequest.action.CancelActionHandler"></action>

      </transition>

   </decision>

   <end-state name="ES_Finished">

                     <event type="node-enter">

                            <action name="Ac_Finished" class="com.myrequest.action.FinishedActionHandler"></action>

                     </event>

   </end-state>

</process-definition>

6.23.    gpd.xml

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

 

<process-diagram name="MyRequest" width="804" height="613">

  <node name="SS_Request" x="147" y="5" width="140" height="40">

    <transition name="">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="TN_WriteRequest" x="145" y="71" width="140" height="40">

    <transition name="Tr_WriteLeave">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="Fork_request" x="168" y="134" width="200" height="25">

    <transition name="Tr_Cancel">

      <label x="5" y="-10"/>

    </transition>

    <transition name="Tr_Request">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="Deci_IsChiefHere" x="311" y="179" width="140" height="40">

    <transition name="Tr_Chief">

      <label x="5" y="-10"/>

    </transition>

    <transition name="Tr_Boss">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="TN_RequesterCancel" x="9" y="181" width="140" height="40">

    <transition name="Tr_RequestCancel">

      <label x="-73" y="-5"/>

    </transition>

  </node>

  <node name="TN_ChiefDecide" x="159" y="253" width="140" height="40">

    <transition name="Tr_ChiefApprove">

      <label x="-42" y="-9"/>

    </transition>

    <transition name="Tr_ChiefNotApprove">

      <label x="-28" y="-5"/>

    </transition>

  </node>

  <node name="Join_Request" x="115" y="388" width="200" height="25">

    <transition name="Tr_Join">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="Deci_NeedBossDecide" x="415" y="243" width="166" height="40">

    <transition name="Tr_Need">

      <label x="-30" y="-11"/>

    </transition>

    <transition name="Tr_NotNeed">

      <label x="5" y="-10"/>

    </transition>

  </node>

  <node name="TN_BossDecide" x="663" y="241" width="140" height="40">

    <transition name="Tr_BossApprove">

      <label x="31" y="-13"/>

    </transition>

    <transition name="Tr_BossNotApprove">

      <label x="-19" y="4"/>

    </transition>

  </node>

  <node name="Deci_DoSomething" x="146" y="460" width="140" height="40">

    <transition name="Tr_Approve">

      <label x="5" y="-10"/>

    </transition>

    <transition name="Tr_NotApprove">

      <label x="2" y="5"/>

    </transition>

    <transition name="Tr_Cancel">

      <label x="4" y="-25"/>

    </transition>

  </node>

  <node name="ES_Finished" x="147" y="572" width="140" height="40"/>

</process-diagram>

posted on 2006-12-04 17:16 鸿雁 阅读(2158) 评论(0)  编辑  收藏