转自小小冰 http://blog.csdn.net/kellerdu/archive/2004/11/08/172247.aspx
----------------------------------------------------------------------- ------- ------- ------- --
示例:
在某一公司中,部门员工要休假的话需要部门主管的批准。如果休假天数大于10天的话,在部门主管的同意后,还必须上级主管批准。如果是部门主管要休假只要上级主管批准即可。在休假被批准之前,申请人可以撤销休假申请。
每 个员工还有多少天休假必须管理起来,在员工提交休假申请时要检查申请天数是否超过可用天数。申请批准后,要在可用天数里减去申请天数。每次休假申请结束之 后,不管通过未通过或是否取消,都必须记录下来。主管在批复申请之后,系统要将批复结果Email给申请人。对于大于10天的申请,如果部门主管已批准同 意而上级主管还未批准,这时申请人撤销申请后,系统应发Email通知部门主管申请已撤销。
processdefinition.xml如下:
  1  <? xml version="1.0" encoding="UTF-8" ?>
  2  <!--  edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by keller (zju)  -->
  3  <! DOCTYPE process-definition PUBLIC
  4      "-//jBpm/jBpm Mapping DTD 2.0//EN"
  5      "http://jbpm.org/dtd/processdefinition-2.0.dtd" >
  6  < process-definition   name ="RequestLeave" >
  7    < swimlane  name ="requester" >
  8     < description > 申请者 </ description >
  9    </ swimlane >
 10    < swimlane  name ="chief" >
 11     < description > 部门主管 </ description >
 12     < delegation  class ="kellerdu.jbpm.delegation.ChiefSwimlane" />
 13    </ swimlane >
 14    < swimlane  name ="boss" >
 15     < description > 上级主管 </ description >
 16     < delegation  class ="kellerdu.jbpm.delegation.BossSwimlane" />
 17    </ swimlane >
 18    < start-state  name ="request"  swimlane ="requester" >
 19     < transition  to ="BeginRequest" />
 20    </ start-state >
 21    < fork  name ="BeginRequest" >
 22     < transition  to ="RequesterCancel" />
 23     < transition  to ="IsChief" />
 24    </ fork >
 25    < decision  name ="IsChief" >
 26     < delegation  class ="kellerdu.jbpm.delegation.ChiefDecision" />
 27     < transition  name ="BossApprove"   to ="BossApprove" />
 28     < transition  name ="ChiefApprove"   to ="ChiefApprove" />
 29    </ decision >
 30    < state  name ="RequesterCancel" >
 31     < assignment  swimlane ="requester" />
 32     < transition  name ="cancel"  to ="Decided" >
 33      < action >
 34       <!--  将请假的状态改变为“取消” -->
 35       < delegation  class ="kellerdu.jbpm.action.RequestCancel" />
 36      </ action >
 37     </ transition >
 38    </ state >
 39    < state  name ="ChiefApprove" >
 40     < assignment  swimlane ="chief" />
 41     < transition  name ="approve"  to ="NeedBossApprove" >
 42      < action >
 43       <!--  将请假的状态改变为“主管批准” -->
 44       < delegation  class ="kellerdu.jbpm.action.ChiefApprove" />
 45      </ action >
 46     </ transition >
 47     < transition  name ="disapprove"  to ="Decided" >
 48      < action >
 49       <!--  将请假的状态改变为“主管否决” -->
 50       < delegation  class ="kellerdu.jbpm.action.ChiefDisapprove" />
 51      </ action >
 52     </ transition >
 53    </ state >
 54    < state  name ="BossApprove" >
 55     < assignment  swimlane ="boss" />
 56     < transition  name ="approve"  to ="Decided" >
 57      < action >
 58       <!--  将请假的状态改变为“老板批准” -->
 59       < delegation  class ="kellerdu.jbpm.action.BossApprove" />
 60      </ action >
 61     </ transition >
 62     < transition  name ="disapprove"  to ="Decided" >
 63      < action >
 64       <!--  将请假的状态改变为“老板否决” -->
 65       < delegation  class ="kellerdu.jbpm.action.BossDisapprove" />
 66      </ action >
 67     </ transition >
 68    </ state >
 69    < decision  name ="NeedBossApprove" >
 70     <!--  请假天数大于10天的要老板批准   -->
 71     < delegation  class ="kellerdu.jbpm.delegation.NeedBossApproveDecision" />
 72     < transition  name ="need"  to ="BossApprove" />
 73     < transition  name ="notNeed"  to ="Decided" />
 74    </ decision >
 75    < join  name ="Decided" >
 76     < description > 有一个先到达即进行父Token </ description >
 77     < delegation  class ="kellerdu.jbpm.delegation.DecidedJoin" />
 78     < transition  to ="DoSomething" />
 79    </ join >
 80    < decision  name ="DoSomething" >
 81     < description >
 82      根据请求的状态决定。
 83      (1)“主管或者老板批准”-‘approve’:修改员工休假的总天数,设定发给用户E-Mail的信息。
 84      (2)“主管或者老板否决”-“disapprove”:设定发给用户E-Mail的信息。
 85      (3)“撤销”-"cancel"-设定发给用户E-Mail的信息。如果主管批准,要发给主管消息说明已经撤销。
 86       </ description >
 87     < delegation  class ="kellerdu.jbpm.delegation.DoSomethingDecision" />
 88     < transition  name ="disapprove"  to ="Finished" >
 89      < action >
 90       < delegation  class ="kellerdu.jbpm.action.Disapprove" />
 91      </ action >
 92     </ transition >
 93     < transition  name ="approve"  to ="Finished" >
 94      < action >
 95       < delegation  class ="kellerdu.jbpm.action.Approve" />
 96      </ action >
 97     </ transition >
 98     < transition  name ="cancel"  to ="Finished" >
 99      < action >
100       < delegation  class ="kellerdu.jbpm.action.Cancel" />
101      </ action >
102     </ transition >
103    </ decision >
104    < end-state  name ="Finished" />
105    < action  event-type ="process-end" >
106     <!--  发送E-Mail消息给申请者,记录请假日志  -->
107     < delegation  class ="kellerdu.jbpm.action.ProcessEndAction" />
108    </ action >
109  </ process-definition >
Action指明的是当前状态要执行的一些额外的操作,如记录log、发邮件等。

(1)Swimline的delegation要做的就是判别当前Actor的身份。

 1  package  kellerdu.jbpm.delegation;
 2 
 3  import  org.jbpm.delegation. * ;
 4  import  kellerdu.jbpm.LogsFactory;
 5  import  org.apache.commons.logging.Log;
 6 
 7  public   class  BossSwimlane  implements  AssignmentHandler {
 8       public  BossSwimlane() {
 9      }
10 
11       /**
12       * 当前的状态有哪个actor来具体负责处理,选择是老板的actor来处理。
13       *
14       * 如果王林是老板,那么他请假可以用他的名称来开始一个请假流程,当他检查他需要批示的
15       * 请假时,使用actorId=boss来找出所有的批示。这时selectActor返回的值就是一个常量“boss”
16       *
17       *
18       *  @param  assignmentContext AssignmentContext
19       *  @return  String
20       * @todo Implement this org.jbpm.delegation.AssignmentHandler method
21        */
22       public  String selectActor(AssignmentContext assignmentContext) {
23          Log log  =  LogsFactory.getLogInstance( this .getClass());
24          log.info( " 任务分配给老板 " );
25           return   " boss " ;
26      }
27  }
28 
 1  package  kellerdu.jbpm.delegation;
 2 
 3  import  org.jbpm.delegation. * ;
 4  import  kellerdu.jbpm.LogsFactory;
 5  import  org.apache.commons.logging.Log;
 6 
 7  public   class  ChiefSwimlane  implements  AssignmentHandler {
 8       public  ChiefSwimlane() {
 9      }
10       /**
11       * selectActor
12       *  @see  BossSwimlane
13       *
14       *  @param  assignmentContext AssignmentContext
15       *  @return  String
16       * @todo Implement this org.jbpm.delegation.AssignmentHandler method
17        */
18       public  String selectActor(AssignmentContext assignmentContext) {
19         Log log  =  LogsFactory.getLogInstance( this .getClass());
20          log.info( " 任务分配给上级主管 " );
21          return   " chief " ;
22      }
23  }
(二)Decision
 1  package  kellerdu.jbpm.delegation;
 2 
 3  import  org.jbpm.delegation. * ;
 4  import  kellerdu.jbpm.LogsFactory;
 5  import  org.apache.commons.logging.Log;
 6  import  kellerdu.jbpm.Constants;
 7 
 8  public   class  ChiefDecision  implements  DecisionHandler {
 9       public  ChiefDecision() {
10      }
11 
12       /**
13       * 判断是否需要主管批准,决定下一个要进行的transition
14       *
15       *  @param  executionContext ExecutionContext
16       *  @return  String
17       * @todo Implement this org.jbpm.delegation.DecisionHandler method
18        */
19       public  String decide(ExecutionContext executionContext) {
20          Log log = LogsFactory.getLogInstance( this .getClass());
21          String ac = (String)executionContext.getVariable(Constants.USER_NAME);
22           if (ac != null && (ac.equals( " dali " ) || ac.equals( " wang " ))){
23              log.info(ac + " 需要老板批准! " );
24               return   " BossApprove " ;
25          } else {
26              log.info(ac + " 需要先经主管批准 " );
27               return   " ChiefApprove " ;
28          }
29      }
30  }
(三)fork
 1  package  kellerdu.jbpm.delegation;
 2 
 3  import  org.jbpm. * ;
 4  import  org.jbpm.delegation. * ;
 5  import  org.jbpm.model.execution. * ;
 6  import  java.util. * ;
 7 
 8  public   class  DecidedJoin  implements  JoinHandler {
 9       public  DecidedJoin() {
10      }
11 
12       /**
13       * fork,只要一个分支到达,即可进行下一步操作,同时取消其它同时进行的分支。
14       * 这里就是用户如果取消,请假就取消。如果用户请假批准,则用户不能取消。
15       *
16       *  @param  forkContext ForkContext
17       *  @throws  ExecutionException
18       * @todo Implement this org.jbpm.delegation.ForkHandler method
19        */
20       public   void  join(JoinContext joinContext)  throws  ExecutionException {
21          Iterator it = joinContext.getConcurrentTokens().values().iterator();
22          Token arrivingToken  =  joinContext.getToken();
23           while (it.hasNext()){
24              Token to = (Token)it.next();
25               if (to.getId().equals(arrivingToken.getId())){
26                   // 取消其它执行的Token
27                  joinContext.getExecutionService().cancelToken(to.getId());
28              }
29          }
30            //  reactivate the parent token.
31            joinContext.reactivateToken( arrivingToken.getParent() );
32      }
33  }

(一)  开始一个请假流程
 
 1         // user是请假人的actorId
 2         ExecutionService es = JbpmServiceFactory.getInstance().openExecutionService(user);
 3          HashMap vs = new  HashMap();
 4          // 一些参数
 5          vs.put(Constants.REQUEST_STATUS,String.valueOf( 0 ));
 6          vs.put(Constants.REQUEST_RETURN_INFO, " No info! " );
 7          vs.put(Constants.USER_NAME,EncodeTransfer.toISO(user));
 8          vs.put(Constants.REQUEST_DAYS,String.valueOf(rea.getDays()));
 9           try  {
10              // 开启请假流程
11              es.startProcessInstance(Constants.WORK_NAME, vs);
12              log.info( " [ " + user + " ] " + " 申请假期开始!请假 " + rea.getDays() + " 天! " );
13               return  am.findForward( " main " );
14          }  catch  (ExecutionException ex) {
15              ex.printStackTrace();
16              log.error( " 请假进程无法开始! " );
17               return  am.findForward( " error " );
18          } finally {
19              es.close();
20          }

(二)当前执行任务
 对于部门经理或者老板,找到要处理的请假。
 1       String actorId  =  (String) req.getSession().getAttribute(Constants.USER);
 2               if (actorId.equals( " wang " )){
 3                  actorId = " boss " ;
 4              } else   if (actorId.equals( " bigli " )){
 5                  actorId = " chief " ;
 6              }
 7               //  get the execution service
 8              ExecutionService executionService  =  JbpmServiceFactory.getInstance().
 9                                                  openExecutionService(actorId);
10 
11               //  get the tasklist from jbpm for user
12              List tasks  =   new  ArrayList();
13               //  add the jbpm tasks
14              tasks.addAll(executionService.getTaskList(actorId));
15               //  put the tasklist into the form
16              mf.setTasks(tasks);
17               //  get the tasklist from jbpm for user
18              List definitions  =   new  ArrayList();
19               //  add the jbpm definitions
20              definitions.addAll(executionService.getLatestDefinitions());
21               //  put the tasklist into the form
22              mf.setRequests(definitions);
23               //  close the execution service
24              executionService.close();
25              req.getSession().setAttribute( " mainForm " ,mf);
26              log.debug( " 任务:  "   +  tasks);
27              log.debug( " 当前可以执行的请求:  "   +  definitions);
28 
(三)处理请假
 1           String actorId  =  (String) reqrest.getSession().getAttribute(Constants.
 2                      USER);
 3              Long tokenId = new  Long(req.getParameter( " tokenId " ));
 4               //  get the execution service
 5              ExecutionService executionService  =  JbpmServiceFactory.getInstance().
 6                                                  openExecutionService(actorId);
 7              Map hm = executionService.getVariables(tokenId); // 变量
 8              String act = req.getParameter( " action " ); // 进行转换的transition
 9              executionService.endOfState(tokenId,hm,act);
10              executionService.close();