轉(zhuǎn)自小小冰 http://blog.csdn.net/kellerdu/archive/2004/11/08/172247.aspx
-----------------------------------------------------------------------
------- ------- ------- --
示例:
在某一公司中,部門員工要休假的話需要部門主管的批準(zhǔn)。如果休假天數(shù)大于10天的話,在部門主管的同意后,還必須上級主管批準(zhǔn)。如果是部門主管要休假只要上級主管批準(zhǔn)即可。在休假被批準(zhǔn)之前,申請人可以撤銷休假申請。
每 個(gè)員工還有多少天休假必須管理起來,在員工提交休假申請時(shí)要檢查申請?zhí)鞌?shù)是否超過可用天數(shù)。申請批準(zhǔn)后,要在可用天數(shù)里減去申請?zhí)鞌?shù)。每次休假申請結(jié)束之 后,不管通過未通過或是否取消,都必須記錄下來。主管在批復(fù)申請之后,系統(tǒng)要將批復(fù)結(jié)果Email給申請人。對于大于10天的申請,如果部門主管已批準(zhǔn)同 意而上級主管還未批準(zhǔn),這時(shí)申請人撤銷申請后,系統(tǒng)應(yīng)發(fā)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?????<!--?將請假的狀態(tài)改變?yōu)椤叭∠?/span>-->
?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?????<!--?將請假的狀態(tài)改變?yōu)椤爸鞴芘鷾?zhǔn)”-->
?44?????<delegation?class="kellerdu.jbpm.action.ChiefApprove"/>
?45????</action>
?46???</transition>
?47???<transition?name="disapprove"?to="Decided">
?48????<action>
?49?????<!--?將請假的狀態(tài)改變?yōu)椤爸鞴芊駴Q”-->
?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?????<!--?將請假的狀態(tài)改變?yōu)椤袄习迮鷾?zhǔn)”-->
?59?????<delegation?class="kellerdu.jbpm.action.BossApprove"/>
?60????</action>
?61???</transition>
?62???<transition?name="disapprove"?to="Decided">
?63????<action>
?64?????<!--?將請假的狀態(tài)改變?yōu)椤袄习宸駴Q”-->
?65?????<delegation?class="kellerdu.jbpm.action.BossDisapprove"/>
?66????</action>
?67???</transition>
?68??</state>
?69??<decision?name="NeedBossApprove">
?70???<!--?請假天數(shù)大于10天的要老板批準(zhǔn)??-->
?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>有一個(gè)先到達(dá)即進(jìn)行父Token</description>
?77???<delegation?class="kellerdu.jbpm.delegation.DecidedJoin"/>
?78???<transition?to="DoSomething"/>
?79??</join>
?80??<decision?name="DoSomething">
?81???<description>
?82?????根據(jù)請求的狀態(tài)決定。
?83?????(1)“主管或者老板批準(zhǔn)”-‘a(chǎn)pprove’:修改員工休假的總天數(shù),設(shè)定發(fā)給用戶E-Mail的信息。
?84?????(2)“主管或者老板否決”-“disapprove”:設(shè)定發(fā)給用戶E-Mail的信息。
?85?????(3)“撤銷”-"cancel"-設(shè)定發(fā)給用戶E-Mail的信息。如果主管批準(zhǔn),要發(fā)給主管消息說明已經(jīng)撤銷。
?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???<!--?發(fā)送E-Mail消息給申請者,記錄請假日志?-->
107???<delegation?class="kellerdu.jbpm.action.ProcessEndAction"/>
108??</action>
109?</process-definition>
Action指明的是當(dāng)前狀態(tài)要執(zhí)行的一些額外的操作,如記錄log、發(fā)郵件等。

(1)Swimline的delegation要做的就是判別當(dāng)前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??????*?當(dāng)前的狀態(tài)有哪個(gè)actor來具體負(fù)責(zé)處理,選擇是老板的actor來處理。
13??????*
14??????*?如果王林是老板,那么他請假可以用他的名稱來開始一個(gè)請假流程,當(dāng)他檢查他需要批示的
15??????*?請假時(shí),使用actorId=boss來找出所有的批示。這時(shí)selectActor返回的值就是一個(gè)常量“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("任務(wù)分配給老板");
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("任務(wù)分配給上級主管");
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??????*?判斷是否需要主管批準(zhǔn),決定下一個(gè)要進(jìn)行的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+"需要老板批準(zhǔn)!");
24?????????????return?"BossApprove";
25?????????}else{
26?????????????log.info(ac+"需要先經(jīng)主管批準(zhǔn)");
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,只要一個(gè)分支到達(dá),即可進(jìn)行下一步操作,同時(shí)取消其它同時(shí)進(jìn)行的分支。
14??????*?這里就是用戶如果取消,請假就取消。如果用戶請假批準(zhǔn),則用戶不能取消。
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?????????????????//取消其它執(zhí)行的Token
27?????????????????joinContext.getExecutionService().cancelToken(to.getId());
28?????????????}
29?????????}
30??????????//?reactivate?the?parent?token.
31???????????joinContext.reactivateToken(?arrivingToken.getParent()?);
32?????}
33?}

(一)? 開始一個(gè)請假流程
?
?1???????//user是請假人的actorId
?2????????ExecutionService?es=JbpmServiceFactory.getInstance().openExecutionService(user);
?3?????????HashMap?vs=new?HashMap();
?4????????//一些參數(shù)
?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("請假進(jìn)程無法開始!");
17?????????????return?am.findForward("error");
18?????????}finally{
19?????????????es.close();
20?????????}

(二)當(dāng)前執(zhí)行任務(wù)
?對于部門經(jīng)理或者老板,找到要處理的請假。
?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("任務(wù):?"?+?tasks);
27?????????????log.debug("當(dāng)前可以執(zhí)行的請求:?"?+?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");//進(jìn)行轉(zhuǎn)換的transition
?9?????????????executionService.endOfState(tokenId,hm,act);
10?????????????executionService.close();