jBPMjPDL学习笔记流程设计与控制Word文件下载.docx
《jBPMjPDL学习笔记流程设计与控制Word文件下载.docx》由会员分享,可在线阅读,更多相关《jBPMjPDL学习笔记流程设计与控制Word文件下载.docx(37页珍藏版)》请在冰豆网上搜索。
/action>
/transition>
/start-state>
task-nodename="
taskname="
Task_AssignToInitiator"
assignmentclass="
com.firstflow.task.NewApplicationAssignmentHandler"
/assignment>
/task>
transitionto="
部门经理审批"
提交申请"
Action_SubmitApply"
com.firstflow.action.SubmitApplyActionHandler"
/task-node>
Task_ManagerApprove"
com.firstflow.task.DepartmentManagerApproveAssignmentHandler"
金额判定"
部门经理审批通过"
Task_ManagerApproved"
com.firstflow.action.ManagerApprovedActionHandler"
结束"
部门经理驳回"
Action_ManagerDisapprove"
com.firstflow.action.ManagerDisapproveActionHandler"
nodename="
财务拨款"
Action_AccountantProcess"
com.firstflow.action.AccountantProcessActoinHandler"
邮件通知"
Action_Mail"
com.firstflow.action.SendMailActionHandler"
/node>
decisionname="
handlerclass="
com.firstflow.decision.MoneyCheckDecisionHandler"
/handler>
总经理审批"
5000元总经理审批"
5000元财务拨款"
/decision>
Task_PresidentApprove"
com.firstflow.task.PresidentApproveAssignmentHandler"
总经理审批通过"
Action_PresidentApproved"
com.firstflow.action.PresidentApprovedActionHandler"
总经理驳回"
Action_PresidentDisapproved"
com.firstflow.action.PresidentDisapprovedActionHandler"
end-statename="
/end-state>
/process-definition>
在样例流程中,除了开始和结束结点外,我们定义了三种类型的结点:
任务结点<
task-node>
任务结点是一个需要人工参与的结点类型。
当流程进入结点时,会生成相应的任务实例(TaskInstatnce),并通过委派接口AssignmentHandler或jBPM表达式将任务委派给一个或多个特定的角色或参与者。
结点自身进入等待状态,直到任务被参与者完成或者跳过,流程继续。
判定结点<
decision>
判定结点的设计目标是根据上下文环境和程序逻辑,判定流程转向。
通过指定一个实现DecisionHandlder接口的Java委派类或jBPM表达式,来返回转向(transition)的字符窜类型的名称(可以是中文哦),来达到决定流程方向的功能。
普通结点<
node>
普通结点也可以定义相应的处理任务,通过定义相应的ActioinHandler类。
同任务结点不同的是,普通结点定义的任务是由流程自动执行的,无须人工干预。
三种结点都可定义结点事件(event):
node-enter,该事件在流程进入结点时触发
node-leave,该事件在流程离开节点是触发
可以在事件上挂接ActioinHandler接口的实现类来完成一些特定的功能。
三种节点都可以定义异步处理方式(async属性):
异步处理意味着每个结点的事务处理是通过消息机制分离的,不再同一线程中统一调用执行。
而是由消息监听线程从消息队列中取得消息体来运行相应得程序。
此外我们定义了结点间的转向(transition),用来记录和处理状态的变迁。
每个转向中,可以委派一个或多个的ActioinHandler接口实现类,负责处理节点变迁时的上下文状态变更及回调用户定义的处理程序。
流程的程序接口说明
动作处理接口(ActioinHandler)
接口方法:
voidexecute(ExecutionContextexecutionContext)throwsException
该接口是jPDL中最常用的一个回调接口。
从它的接口方法可以发现,它仅仅暴露了流程执行上下文变量ExecutionContext。
用户程序通过ExecutionContext来了解流程的执行状态,并通过改变ExecutionContext中的属性值来影响流程的执行。
ActioinHandler接口可以在所有能包含事件(event)、动作(action)元素的地方被回调。
判定处理接口(DecisionHandlder)
Stringdecide(ExecutionContextexecutionContext)throwsException
判定接口仅适用于判定节点(decision)中。
从它的接口方法可以看出,方法要返回一个字符串型的结果,这个结果必须和判定节点拥有的转向(transition)集合中的一条转向名称相匹配。
在DecisionHandlder的接口方法中一样能访问到ExecutionContext变量,这为判定提供了执行上下文的根据。
当然,如果有必要,用户也可以在该接口中改变ExecutionContext中的变量值。
委派处理接口(AssignmentHandler)
voidassign(Assignableassignable,ExecutionContextexecutionContext)throwsException;
委派处理接口被用户任务元素(task)的委派(assignment)子元素中,它的职责很明确,就是将任务分配给指定的人员或角色。
在AssignmentHandler接口的方法中,Assignable变量通常指任务实例(TaskInstance)。
通过将ExecutionContext和TaskInstance两个变量都暴露给接口方法,用户就可以根据流程上下文情况,来决定要将指定的任务分配个谁。
流程的部署
用户使用jPDL的流程设计器定义业务流程,当然,你也可以直接用文档编辑器直接编辑processdefinition.xml定义文件。
定义文档是可以直接被ProcessDefinition类载入使用的,但在正式运行的系统中,流程定义信息更多是使用关系型数据库来存储。
从流程定义文件将数据导入流程数据库的过程,我们称之为流程部署。
jPDL的流程部署文件包含processdefinition.xml的定义部分和Java处理器的代码部分,这些文件可以被一起打包成.jpdl的zip格式包而后上传服务器端。
这个过程可以在流程设计器界面的“deployment”标签页中操作:
这里我们着重要讲述的是接受部署文件上载的服务器端配置。
在jBPM3.2的包中带着一个jPDL的管理控制台web应用,默认名字为jbpm-console。
该应用带有接受流程定义包部署的程序,但不是最小化的。
实际上完成流程部署功能的,只是jbpm-jpdl.jar核心包中的一个servlet类:
org.jbpm.web.ProcessUploadServlet.完成这个Servlet的成功部署,需要以下工作:
1.配置web.xml,将servlet配置成启动时加载,如下:
web-app>
servlet>
servlet-name>
GDPDeployerServlet<
/servlet-name>
servlet-class>
org.jbpm.web.ProcessUploadServlet<
/servlet-class>
load-on-startup>
1<
/load-on-startup>
/servlet>
servlet-mapping>
url-pattern>
/upload/*<
/url-pattern>
/servlet-mapping>
/web-app>
2.建立流程定义存储数据库表:
Demo中,我们使用的数据库是MySQL的,在E:
\Java\tools\jbpm-jpdl-3.2.2\db\目录下有个jbpm.jpdl.mysql.sql数据库脚本文件。
但我们不能直接导入该文件,会提示有错误,应为该文件的SQL语句末尾少了分号,在批量执行时,MySQL报错。
需要在每一行SQL的末尾添加一个分号,这样就可以用source命令导入了。
3.配置Hibernate.cfg.xml
由于jBPM的数据库持久化是依靠Hibernate进行的,因此需要配置Hibernate.cfg.xml使其适应我们的MySQL环境
!
--hibernatedialect-->
propertyname="
hibernate.dialect"
org.hibernate.dialect.MySQLInnoDBDialect<
/property>
hibernate.connection.driver_class"
com.mysql.jdbc.Driver<
hibernate.connection.url"
jdbc:
mysql:
//localhost:
3306/linly<
hibernate.connection.username"
linly<
hibernate.connection.password"
coffee<
hibernate.cache.provider_class"
org.hibernate.cache.HashtableCacheProvider<
4.Import需要的jar包
这里的jar包包括三部分:
jbpm的核心包;
Hibernate及其支撑包;
MySQL的JDBC驱动包。
到此,我们的配置工作完成,这是实现jBPM流程部署服务端的最小化应用配置。
流程控制及API使用
样例程序中的Handler接口实现
下面,根据上述的接口分类,列出样例程序中的类名及相应的功能说明,具体可参考源代码。
这里要提到一个很重要的区别,就是作用于Node上的ActoinHandler和作用于Transition上的ActoinHandler是有不同的。
区别在于,Node上的ActoinHandler在结束业务逻辑处理后,必须调用executionContext.leaveNode();
或executionContext.leaveNode(transition)来保证流程向下执行;
而作用于Transition上的则不需要。
流程测试剖析
本章节,我们将给大家剖析两个流程测试类。
一个是简单的基于内存模型的流程测试FirstFlowProcessTest;
一个是更贴近实用的,基于MySQL数据库操作的标准测试案例。
通过对这两个测试例程的分析,来直观的学习如何通过JavaAPI操作jPDL。
简单流程测试案例
测试案例类:
FirstFlowProcessTest.java
Java代码
1.public
class
FirstFlowProcessTest
extends
TestCase
{
2.
ProcessDefinition
pdf
;
3.
ProcessInstance
pi;
4.
5.
public
void
test4000YuanApplication()
throws
Exception
6.
deployProcessDefinition();
7.
createProcessInstance("
linly"
);
8.
submitApplication(4000);
9.
approveByManager(true);
10.
checkTasks();
11.
}
12.
13.
test6000YuanApplication()
14.
15.
16.
submitApplication(6000);
17.
18.
approveByPresident(true);
19.
20.
21.
22.
test7000YuanApplication()
23.
24.
25.
submitApplication(7000);
26.
27.
approveByPresident(false);
28.
29.
30.
31.
/**
32.
*
部署流程定义
33.
@throws
Exception
34.
*/
35.
protected
deployProcessDefinition()
Exception{
36.
System.out.println("
==FirstFlowProcessTest.deployProcessDefinition()=="
37.
=
ProcessDefinition.parseXmlResource("
firstflow/processdefinition.xml"
38.
assertNotNull("
Definition
should
not
be
null"
pdf);
39.
}
40.
41.
生成流程实例
42.
43.
createProcessInstance(String
user){
44.
==FirstFlowProcessTest.createProcessInstance()=="
45.
46.
//生成实例
47.
pi
pdf.createProcessInstance();
48.
processInstance
pi);
49.
//设置流程发起人
50.
pi.getContextInstance().createVariable("
initiator"
user);
51.
//触发流程转向
52.
pi.signal();
53.
54.
55.
填写提交申请单
56.
@param
money
57.
58.
submitApplication(int
money){
59.
==FirstFlowProcessTest.submitApplication()=="
60.
TaskInstance
ti
(TaskInstance)pi.getTaskMgmtInstance().getTaskInstances().iterator()
.next()
61.
ti.actor
"
+
ti.getActorId());
62.
ContextInstance
ci
ti.getContextInstance();
63.
ci.setVariable("
money"
new
Integer(money));
64.
ti.end();
65.
66.
67.
部门经理审批
68.
pass
69.
70.
@SuppressWarnings("
unchecked"
)
71.
approveByManager(boolean
pass){
72.
==FirstFlowProcessTest.approveByManager()=="
73.
Iterator<
TaskInstance>
it
pi.getTaskMgmtInstance().getTaskInstances().iterator();
74.
for(
it.hasNext();
){
75.
it.next();