转自小小冰 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();