Terry.Li-彬

虚其心,可解天下之问;专其心,可治天下之学;静其心,可悟天下之理;恒其心,可成天下之业。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  143 随笔 :: 344 文章 :: 130 评论 :: 0 Trackbacks
 

一个JBPM工作流管理示例

一个JBPM工作流管理示例

示例:
在某一公司中,部门员工要休假的话需要部门主管的批准。如果休假天数大于10天的话,在部门主管的同意后,还必须上级主管批准。如果是部门主管要休假只要上级主管批准即可。在休假被批准之前,申请人可以撤销休假申请。
每个员工还有多少天休假必须管理起来,在员工提交休假申请时要检查申请天数是否超过可用天数。申请批准后,要在可用天数里减去申请天数。每次休假申请结束之后,不管通过未通过或是否取消,都必须记录下来。主管在批复申请之后,系统要将批复结果Email给申请人。对于大于10天的申请,如果部门主管已批准同意而上级主管还未批准,这时申请人撤销申请后,系统应发Email通知部门主管申请已撤销。 
  processdefinition.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSPY v2004 rel. 3 U (http://www.xmlspy.com) by keller (zju) -->
<!DOCTYPE process-definition PUBLIC
    "-//jBpm/jBpm Mapping DTD 2.0//EN"
    "http://jbpm.org/dtd/processdefinition-2.0.dtd">
<process-definition  name="RequestLeave">
 <swimlane name="requester">
  <description>
申请者</description>
 </swimlane>
 <swimlane name="chief">
  <description>部门主管</description>
  <delegation class="kellerdu.jbpm.delegation.ChiefSwimlane"/>
 </swimlane>
 <swimlane name="boss">
  <description>上级主管</description>
  <delegation class="kellerdu.jbpm.delegation.BossSwimlane"/>
 </swimlane>
 <start-state name="request" swimlane="requester">
  <transition to="BeginRequest"/>
 </start-state>
 <fork name="BeginRequest">
  <transition to="RequesterCancel"/>
  <transition to="IsChief"/>
 </fork>
 <decision name="IsChief">
  <delegation class="kellerdu.jbpm.delegation.ChiefDecision"/>
  <transition name="BossApprove"  to="BossApprove"/>
  <transition name="ChiefApprove"  to="ChiefApprove"/>
 </decision>
 <state name="RequesterCancel">
  <assignment swimlane="requester"/>
  <transition name="cancel" to="Decided">
   <action>
    <!-- 将请假的状态改变为“取消”-->
    <delegation class="kellerdu.jbpm.action.RequestCancel"/>
   </action>
  </transition>
 </state>
 <state name="ChiefApprove">
  <assignment swimlane="chief"/>
  <transition name="approve" to="NeedBossApprove">
   <action>
    <!-- 将请假的状态改变为“主管批准”-->
    <delegation class="kellerdu.jbpm.action.ChiefApprove"/>
   </action>
  </transition>
  <transition name="disapprove" to="Decided">
   <action>
    <!-- 将请假的状态改变为“主管否决”-->
    <delegation class="kellerdu.jbpm.action.ChiefDisapprove"/>
   </action>
  </transition>
 </state>
 <state name="BossApprove">
  <assignment swimlane="boss"/>
  <transition name="approve" to="Decided">
   <action>
    <!-- 将请假的状态改变为“老板批准”-->
    <delegation class="kellerdu.jbpm.action.BossApprove"/>
   </action>
  </transition>
  <transition name="disapprove" to="Decided">
   <action>
    <!-- 将请假的状态改变为“老板否决”-->
    <delegation class="kellerdu.jbpm.action.BossDisapprove"/>
   </action>
  </transition>
 </state>
 <decision name="NeedBossApprove">
  <!-- 请假天数大于10天的要老板批准  -->
  <delegation class="kellerdu.jbpm.delegation.NeedBossApproveDecision"/>
  <transition name="need" to="BossApprove"/>
  <transition name="notNeed" to="Decided"/>
 </decision>
 <join name="Decided">
  <description>有一个先到达即进行父Token</description>
  <delegation class="kellerdu.jbpm.delegation.DecidedJoin"/>
  <transition to="DoSomething"/>
 </join>
 <decision name="DoSomething">
  <description>
    根据请求的状态决定。
    (1)“主管或者老板批准”-‘approve’:修改员工休假的总天数,设定发给用户E-Mail的信息。
    (2)“主管或者老板否决”-“disapprove”:设定发给用户E-Mail的信息。
    (3)“撤销”-"cancel"-设定发给用户E-Mail的信息。如果主管批准,要发给主管消息说明已经撤销。
    </description>
  <delegation class="kellerdu.jbpm.delegation.DoSomethingDecision"/>
  <transition name="disapprove" to="Finished">
   <action>
    <delegation class="kellerdu.jbpm.action.Disapprove"/>
   </action>
  </transition>
  <transition name="approve" to="Finished">
   <action>
    <delegation class="kellerdu.jbpm.action.Approve"/>
   </action>
  </transition>
  <transition name="cancel" to="Finished">
   <action>
    <delegation class="kellerdu.jbpm.action.Cancel"/>
   </action>
  </transition>
 </decision>
 <end-state name="Finished"/>
 <action event-type="process-end">
  <!-- 发送E-Mail消息给申请者,记录请假日志 -->
  <delegation class="kellerdu.jbpm.action.ProcessEndAction"/>
 </action>
</process-definition>

Action指明的是当前状态要执行的一些额外的操作,如记录log、发邮件等。
(1)Swimline的delegation要做的就是判别当前Actor的身份。
package kellerdu.jbpm.delegation;

import org.jbpm.delegation.*;
import kellerdu.jbpm.LogsFactory;
import org.apache.commons.logging.Log;

public class BossSwimlane implements AssignmentHandler {
    public BossSwimlane() {
    }

    /**
     *
当前的状态有哪个actor来具体负责处理,选择是老板的actor来处理。
     *
     * 如果王林是老板,那么他请假可以用他的名称来开始一个请假流程,当他检查他需要批示的
     * 请假时,使用actorId=boss来找出所有的批示。这时selectActor返回的值就是一个常量“boss”
     *
     *
     * @param assignmentContext AssignmentContext
     * @return String
     * @todo Implement this org.jbpm.delegation.AssignmentHandler method
     */
    public String selectActor(AssignmentContext assignmentContext) {
        Log log = LogsFactory.getLogInstance(this.getClass());
        log.info("任务分配给老板");
        return "boss";
    }
}
========================================
ackage kellerdu.jbpm.delegation;

import org.jbpm.delegation.*;
import kellerdu.jbpm.LogsFactory;
import org.apache.commons.logging.Log;

public class ChiefSwimlane implements AssignmentHandler {
    public ChiefSwimlane() {
    }

    /**
     * selectActor
     * @see BossSwimlane
     *
     * @param assignmentContext AssignmentContext
     * @return String
     * @todo Implement this org.jbpm.delegation.AssignmentHandler method
     */
    public String selectActor(AssignmentContext assignmentContext) {
       Log log = LogsFactory.getLogInstance(this.getClass());
        log.info("
任务分配给上级主管");
       return "chief";
    }
}

(二)Decision
package kellerdu.jbpm.delegation;

import org.jbpm.delegation.*;
import kellerdu.jbpm.LogsFactory;
import org.apache.commons.logging.Log;
import kellerdu.jbpm.Constants;

public class ChiefDecision implements DecisionHandler {
    public ChiefDecision() {
    }

    /**
     *
判断是否需要主管批准,决定下一个要进行的transition
     *
     * @param executionContext ExecutionContext
     * @return String
     * @todo Implement this org.jbpm.delegation.DecisionHandler method
     */
    public String decide(ExecutionContext executionContext) {
        Log log=LogsFactory.getLogInstance(this.getClass());
        String ac=(String)executionContext.getVariable(Constants.USER_NAME);
        if(ac!=null&&(ac.equals("dali")||ac.equals("wang"))){
            log.info(ac+"需要老板批准!");
            return "BossApprove";
        }else{
            log.info(ac+"需要先经主管批准");
            return "ChiefApprove";
        }
    }
}
=======================
(三)fork
package kellerdu.jbpm.delegation;

import org.jbpm.*;
import org.jbpm.delegation.*;
import org.jbpm.model.execution.*;
import java.util.*;

public class DecidedJoin implements JoinHandler {
    public DecidedJoin() {
    }

    /**
     * fork
,只要一个分支到达,即可进行下一步操作,同时取消其它同时进行的分支。
     * 这里就是用户如果取消,请假就取消。如果用户请假批准,则用户不能取消。
     *
     * @param forkContext ForkContext
     * @throws ExecutionException
     * @todo Implement this org.jbpm.delegation.ForkHandler method
     */
    public void join(JoinContext joinContext) throws ExecutionException {
        Iterator it=joinContext.getConcurrentTokens().values().iterator();
        Token arrivingToken = joinContext.getToken();
        while(it.hasNext()){
            Token to=(Token)it.next();
            if(to.getId().equals(arrivingToken.getId())){
                //取消其它执行的Token
                joinContext.getExecutionService().cancelToken(to.getId());
            }
        }
         // reactivate the parent token.
          joinContext.reactivateToken( arrivingToken.getParent() );
    }
}

(一) 开始一个请假流程
       //user是请假人的actorId
       ExecutionService es=JbpmServiceFactory.getInstance().openExecutionService(user);
        HashMap vs=new HashMap();
       //一些参数
        vs.put(Constants.REQUEST_STATUS,String.valueOf(0));
        vs.put(Constants.REQUEST_RETURN_INFO,"No info!");
        vs.put(Constants.USER_NAME,EncodeTransfer.toISO(user));
        vs.put(Constants.REQUEST_DAYS,String.valueOf(rea.getDays()));
        try {
           //开启请假流程
            es.startProcessInstance(Constants.WORK_NAME, vs);
            log.info("["+user+"]"+"申请假期开始!请假"+rea.getDays()+"天!");
            return am.findForward("main");
        } catch (ExecutionException ex) {
            ex.printStackTrace();
            log.error("请假进程无法开始!");
            return am.findForward("error");
        }finally{
            es.close();
        }
(二)当前执行任务
    对于部门经理或者老板,找到要处理的请假。
       String actorId = (String) req.getSession().getAttribute(Constants.USER);
            if(actorId.equals("wang")){
                actorId="boss";
            }else if(actorId.equals("bigli")){
                actorId="chief";
            }
            // get the execution service
            ExecutionService executionService = JbpmServiceFactory.getInstance().
                                                openExecutionService(actorId);

            // get the tasklist from jbpm for user
            List tasks = new ArrayList();
            // add the jbpm tasks
            tasks.addAll(executionService.getTaskList(actorId));
            // put the tasklist into the form
            mf.setTasks(tasks);
            // get the tasklist from jbpm for user
            List definitions = new ArrayList();
            // add the jbpm definitions
            definitions.addAll(executionService.getLatestDefinitions());
            // put the tasklist into the form
            mf.setRequests(definitions);
            // close the execution service
            executionService.close();
            req.getSession().setAttribute("mainForm",mf);
            log.debug("
任务: " + tasks);
            log.debug("当前可以执行的请求: " + definitions);
(三)处理请假
           String actorId = (String) reqrest.getSession().getAttribute(Constants.
                    USER);
            Long tokenId=new Long(req.getParameter("tokenId"));
            // get the execution service
            ExecutionService executionService = JbpmServiceFactory.getInstance().
                                                openExecutionService(actorId);
            Map hm=executionService.getVariables(tokenId);//变量
            String act=req.getParameter("action");//进行转换的transition
            executionService.endOfState(tokenId,hm,act);
            executionService.close();

v
posted on 2007-09-06 18:13 礼物 阅读(675) 评论(0)  编辑  收藏 所属分类: Jbpm