转自小小冰 http://blog.csdn.net/kellerdu/archive/2004/11/08/172247.aspx
----------------------------------------------------------------------- ------- ------- ------- --
示例:
在某一公司中,部门员工要休假的话需要部门主管的批准。如果休假天数大于10天的话,在部门主管的同意后,还必须上级主管批准。如果是部门主管要休假只要上级主管批准即可。在休假被批准之前,申请人可以撤销休假申请。
每 个员工还有多少天休假必须管理起来,在员工提交休假申请时要检查申请天数是否超过可用天数。申请批准后,要在可用天数里减去申请天数。每次休假申请结束之 后,不管通过未通过或是否取消,都必须记录下来。主管在批复申请之后,系统要将批复结果Email给申请人。对于大于10天的申请,如果部门主管已批准同 意而上级主管还未批准,这时申请人撤销申请后,系统应发Email通知部门主管申请已撤销。
processdefinition.xml如下:
(一) 开始一个请假流程
(二)当前执行任务
对于部门经理或者老板,找到要处理的请假。
----------------------------------------------------------------------- ------- ------- ------- --
示例:
在某一公司中,部门员工要休假的话需要部门主管的批准。如果休假天数大于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、发邮件等。
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 >
(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
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
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 }
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
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 }
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 }
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 }
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
(三)处理请假
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();
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();