http://www.blogjava.net/sxyx2008/
JBPM4之基础知识
流程定义引擎:
ProcessEngine processEngine;
获取:
processEngine=Configuration.getProcessEngine();
重要的几个接口:
RepositoryService repositoryService;
ExecutionService executionService;
TaskService taskService;
HistoryService historyService;
ManagementService managementService;
获取:
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
taskService=processEngine.getTaskService();
historyService=processEngine.getHistoryService();
managementService=processEngine.getManagementService();
说明:
RepositoryService主要用来管理和发布流程定义,发布流程定义、删除流程定义、查看那
流程定义。
流程定义发布:
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").
deploy();
注:此方法
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
示从 classpath路径加载一个流程定义文件,并发布,上例中 demo.jpdl.xml
文件位于 src(classpath)路径下,若流程定义文件放置与包中,则需要使用包名+jpdl文件
名。如 com/jbpm/demo.jpdl.xml
查看流程定义:
repositoryService.createDeployment().addResourceFromClasspath("test1.jpdl.xml")
.deploy();
List
list=repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
System.out.println("流程定义 Id:"+processDefinition.getId());
System.out.println("流程部署 Id:"+processDefinition.getDeploymentId());
}
删除流程定义:
String
deploymentId=repositoryService.createDeployment().addResourceFromClasspath("tes
t1.jpdl.xml").deploy();
repositoryService.deleteDeploymentCascade(deploymentId);
deploymentId为流程定义部署 Id
ExecutionService主要用来操作流程实例,启动流程实例、查看流程实例、删除流程实例、
结束流程实例。
http://www.blogjava.net/sxyx2008/
其前提条件是发布了流程定义
启动流程实例:
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").
deploy();
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
使用 executionService.startProcessInstanceByKey("demo");方法来启动一个流程实例。
其中 startProcessInstanceByKey就表示以 key的方式来启动流程实例,key为流程定义文
件中 process节点的 key属性,若未明确给出 key属性,则默认 key属性的值与 name属性
的值相同。
同样也可以使用 executionService.startProcessInstanceById(processDefinitionId)的
方式来启动流程实例。此方法是用流程定义文件中 process节点的 id属性来启动流程实例。
其 Id属性由两部分组成流程定义的 key和流程定义的版本来组成。形如 key-version
例如:
ProcessInstance
processInstance=executionService.startProcessInstanceById("demo-1");
其中 demo-1就为流程定义中的流程 Id,其 key为 demo,版本号为 1
同样使用此方法可用来启动指定版本号的流程实例。
查看流程实例:
List
list=executionService.createProcessInstanceQuery().list();
for (ProcessInstance processInstance : list) {
System.out.println("流程实例 Id:"+processInstance.getId());
System.out.println("流程定义
Id:"+processInstance.getProcessDefinitionId());
}
级联删除流程实例:
executionService.deleteProcessInstanceCascade(processInstance.getId());
结束流程实例:
executionService.endProcessInstance(processInstance.getId(), "结束流程实例");
注意:在使用 executionService.endProcessInstance()对流程实例进行结束操作后,需要
重新查询 processInstance才能得到更新后的流程实例,如果流程已结束,则查询结果为
null
如:
executionService.endProcessInstance(processInstance.getId(), "结束流程实例");
System.out.println(processInstance.isEnded());
此行代码是无意义的,因为此时并未获取到更新后的流程实例,需要重新查询流程实例,所
以此处返回为 false
System.out.println("-----------查询流程实例--------------->");
List
list=executionService.createProcessInstanceQuery().list();
for (ProcessInstance processInstance : list) {
System.out.println("流程实例 Id:"+processInstance.getId());
System.out.println("流程定义
http://www.blogjava.net/sxyx2008/
Id:"+processInstance.getProcessDefinitionId());
}
结果:
false
-----------查询流程实例--------------->
使流程向下执行:
在使用 executionService启动流程实例后,流程会顺着向下执行(即启动流程实例后,流程
会从 start节点向下移动),在 state或 task节点,流程会暂停下来,满足条件后流程会向下
继续执行,直到流程 end节点,结束流程。
在程序中是流程遵循某一条件,沿着某个方向流动的方法为
executionService.signalExecutionById();
该方法有多个重载:
ProcessInstance signalExecutionById(String executionId);
//若在流程定义某一个节点没有分支时(只有一个 transition时),调用此方法,可将流程
继续向下执行 executionId为流程实例 Id
ProcessInstance signalExecutionById(String executionId, String signalName);
//若在流程定义某一个节点有多个分支时(有多个 transition时),调用此方法,可将流程
沿着 transition所指的方向向下执行
executionId为流程实例 Id, signalName为流程定义中 transition节点的 name属性的值
ProcessInstance signalExecutionById(String executionId, String signalName,
Map parameters);
用于将流程沿着 signalName方向(transition的 name属性所指的方向)向下继续执行,在执
行的过程中顺便传递参数 parameters
ProcessInstance signalExecutionById(String executionId, Map
parameters);
用于将流程向下继续执行,在执行的过程中顺便传递参数 parameters
注:当一个节点有多个分支时,若要通过 signalExecutionById()方法将流程向下执行必须
明确指出 signalName即(transition的 name属性所指的方向),否则流程不会向下执行,仍
会停留在当前节点。因为 jbpm不确定流程该流向那个方向。
示例代码:
1. 没有分支的 state流向
流程定义文件:
http://www.blogjava.net/sxyx2008/
测试代码:
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.RepositoryService;
import junit.framework.TestCase;
public class DemoTest extends TestCase{
ProcessEngine processEngine;
RepositoryService repositoryService;
ExecutionService executionService;
@Override
protected void setUp() throws Exception {
processEngine=Configuration.getProcessEngine();
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
//部署流程定义
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xm
l").deploy();
}
public void testProcessInstance(){
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程实例Id:"+processInstance.getId());
System.out.println("流程定义
Id:"+processInstance.getProcessDefinitionId());
//判断当前是否位于start节点
System.out.println("是否位于start节
点:"+processInstance.isActive("start"));
//判断当前是否位于state节点
System.out.println("是否位于state节
点:"+processInstance.isActive("state"));
//判断流程是否结束
System.out.println("判断流程是否结束:"+processInstance.isEnded());
http://www.blogjava.net/sxyx2008/
System.out.println("------------------------>使流程继续向下执行");
//使流程继续向下执行
//ProcessInstance
instanceState=executionService.signalExecutionById(processInstance.getId());
//此处也可以这么写
ProcessInstance
instanceState=executionService.signalExecutionById(processInstance.getId(),"to
end");
//to end为流程定义中用于连接state和end节点之间transition的name属性的值
//判断当前是否位于state节点
System.out.println("是否位于state节
点:"+instanceState.isActive("state"));
//判断流程是否结束
System.out.println("判断流程是否结束:"+instanceState.isEnded());
}
}
执行结果:
流程实例Id:demo1.7
流程定义Id:demo1-1
是否位于start节点:false
是否位于state节点:true
判断流程是否结束:false
------------------------>使流程继续向下执行
是否位于state节点:false
判断流程是否结束:true
2. 含有分支的 state流向
http://www.blogjava.net/sxyx2008/
流程定义文件:
测试代码:
import junit.framework.TestCase;
public class Demo2Test extends TestCase{
ProcessEngine processEngine;
RepositoryService repositoryService;
ExecutionService executionService;
@Override
protected void setUp() throws Exception {
processEngine=Configuration.getProcessEngine();
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
//部署流程定义
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xm
l").deploy();
}
public void testProcessInstance(){
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程实例 Id:"+processInstance.getId());
System.out.println("流程定义
Id:"+processInstance.getProcessDefinitionId());
//判断当前是否位于 start节点
System.out.println("是否位于 start节
点:"+processInstance.isActive("start"));
//判断当前是否位于 state节点
System.out.println("是否位于 state节
http://www.blogjava.net/sxyx2008/
点:"+processInstance.isActive("state"));
//判断流程是否结束
System.out.println("判断流程是否结束:"+processInstance.isEnded());
System.out.println("------------------------>使流程继续向下执行");
//不明确指出流动方向,看流程位于那个节点
ProcessInstance
instance=executionService.signalExecutionById(processInstance.getId());
//判断当前是否位于 state节点
System.out.println("是否位于 state节点:"+instance.isActive("state"));
//判断流程是否结束
System.out.println("判断流程是否结束:"+instance.isEnded());
}
}
执行结果:
流程实例Id:demo.7
流程定义Id:demo-1
是否位于start节点:false
是否位于state节点:true
判断流程是否结束:false
------------------------>使流程继续向下执行
是否位于state节点:true
判断流程是否结束:false
指明流向节点:
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("------------------------>使流程继续向下执行");
System.out.println("------------------------>使流程流向200");
ProcessInstance
processInstance200=executionService.signalExecutionById(processInstance.getId()
, "to 200");
System.out.println("当前流程是否位于200节点
---->"+processInstance200.isActive("200"));
System.out.println("当前流程是否结束
---->"+processInstance200.isEnded());
/*System.out.println("------------------------>使流程流向400");
ProcessInstance
processInstance400=executionService.signalExecutionById(processInstance.getId()
, "to 400");
System.out.println("当前流程是否位于400节点
---->"+processInstance400.isActive("400"));
System.out.println("当前流程是否结束
---->"+processInstance400.isEnded());*/
执行效果:
------------------------>使流程继续向下执行
http://www.blogjava.net/sxyx2008/
------------------------>使流程流向200
当前流程是否位于200节点---->true
当前流程是否结束---->false
上述代码中使用 signalExecutionById()方法时,传入的是流程实例的 Id,也可以使用以下
代码来完成同样的工作:
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
//查询该流程实例的活动节点
System.out.println(processInstance.findActiveActivityNames());
//因为流程实例启动后,它会自动向下执行,直到遇到state或task等节点时暂停下
来,在我们的流程定义文件中紧跟在start后的节点为state,所以流程实例会在state节点暂
停下来
Execution execution=processInstance.findActiveExecutionIn("state");
ProcessInstance
processInstance200=executionService.signalExecutionById(execution.getId(), "to
200");
System.out.println("当前流程是否位于200节点
---->"+processInstance200.isActive("200"));
System.out.println("当前流程是否结束
---->"+processInstance200.isEnded());
//使流程继续向下执行(结束)
System.out.println("-------使流程继续向下执行(结束)------->");
ProcessInstance
instance=executionService.signalExecutionById(processInstance200.getId());
System.out.println("当前流程是否结束---->"+instance.isEnded());
执行结果:
[state]
当前流程是否位于200节点---->true
当前流程是否结束---->false
-------使流程继续向下执行(结束)------->
当前流程是否结束---->true
关于流程实例几个重要的方法:
processInstance.isEnded()判断程实例是否结束结束返回 true,否则返回 false
processInstance.isActive(“A”)判断当前流程是否处于 A节点
谨记executionService.signalExecutionById(String executionId, String signalName)
方法中executionId为流程实例Id,signalName为流程向下执行的transition的name属性的
值,而不是下一个节点的名称。
State、Decision 、Task活动详解:
State表示一个等待状态。当流程实例执行到 state节点时会暂停下来(处于等待状态),流
程的执行会在外部触发器被调用之前一直等待(会暂停)
Decision条件判断节点, 表示在多条路径中选择一条。一个 decision 活动拥有很多个传
出的转移。流程的执行到达一个 decision 活动时,会自动进行计算来决定采用哪个传出的
转移(满足条件时,向下执行,没有符合条件时会停留在 decision活动的上一个活动)
http://www.blogjava.net/sxyx2008/
Task任务组件,主要用来为流程实例分配任务。通常与 form表单相关联.(会暂停下来)
State节点示例
无分支的 state节点
流程定义文件:
测试代码:
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程实例Id:"+processInstance.getId());
System.out.println("流程定义
Id:"+processInstance.getProcessDefinitionId());
//判断当前是否位于start节点
System.out.println("是否位于start节
点:"+processInstance.isActive("start"));//false
//判断当前是否位于state节点
System.out.println("是否位于state节
点:"+processInstance.isActive("state"));//true
//判断流程是否结束
System.out.println("判断流程是否结
束:"+processInstance.isEnded());//false
System.out.println("------------------------>使流程继续向下执行");
//使流程继续向下执行
//ProcessInstance
instanceState=executionService.signalExecutionById(processInstance.getId());
//此处也可以这么写
ProcessInstance
instanceState=executionService.signalExecutionById(processInstance.getId(),"to
http://www.blogjava.net/sxyx2008/
end");
//to end为流程定义中用于连接state和end节点之间transition的name属性的值
//判断当前是否位于state节点
System.out.println("是否位于state节
点:"+instanceState.isActive("state"));//false
//判断流程是否结束
System.out.println("判断流程是否结束:"+instanceState.isEnded());//true
执行结果:
流程实例Id:demo.7
流程定义Id:demo-1
是否位于start节点:false
是否位于state节点:true
判断流程是否结束:false
------------------------>使流程继续向下执行
是否位于state节点:false
判断流程是否结束:true
有分支的 state节点:
注意:在此流程定义中在 state节点后含有 2个分支(2个 transition 即 to 400和 to 200),
那么在使流程实例从 state节点向下执行的时候需要明确给出 transition的方向 name属性
的值,否则流程实例会一直处于 state节点
executionService.signalExecutionById(processInstance.getId(), "to 200");
流程定义文件:
http://www.blogjava.net/sxyx2008/
测试代码:
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("------------------------>使流程继续向下执行");
System.out.println("------------------------>使流程流向200");
ProcessInstance
processInstance200=executionService.signalExecutionById(processInstance.getId()
, "to 200");
System.out.println("当前流程是否位于200节点
---->"+processInstance200.isActive("200"));//true
System.out.println("当前流程是否结束
---->"+processInstance200.isEnded());//false
/*System.out.println("------------------------>使流程流向400");
ProcessInstance
processInstance400=executionService.signalExecutionById(processInstance.getId()
, "to 400");
System.out.println("当前流程是否位于400节点
---->"+processInstance400.isActive("400"));
System.out.println("当前流程是否结束
---->"+processInstance400.isEnded());*/
执行结果:
------------------------>使流程继续向下执行
------------------------>使流程流向200
当前流程是否位于200节点---->true
当前流程是否结束---->false
流向 400的自己测试
由于流程定义中 200和 400均为 state节点,所以流程在流经 200或 400节点后仍会停留在
该节点,以下代码完成流程实例从 start->200->end这一过程
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("demo");
//查询该流程实例的活动节点
System.out.println(processInstance.findActiveActivityNames());
//因为流程实例启动后,它会自动向下执行,直到遇到state或task等节点时暂停下
来,在我们的流程定义文件中紧跟在start后的节点为state,所以流程实例会在state节点暂
停下来
Execution execution=processInstance.findActiveExecutionIn("state");//查
询当前流程实例的当前节点
ProcessInstance
http://www.blogjava.net/sxyx2008/
processInstance200=executionService.signalExecutionById(execution.getId(), "to
200");//此时流程流向200
System.out.println("当前流程是否位于200节点
---->"+processInstance200.isActive("200"));//true
System.out.println("当前流程是否结束
---->"+processInstance200.isEnded());//false
//使流程继续向下执行(结束)
System.out.println("-------使流程继续向下执行(结束)------->");
//由于200节点后没有分支仅有end这一节点,所以200与end之间transition的name
属性的值可以省略,当然加上更好
ProcessInstance
instance=executionService.signalExecutionById(processInstance200.getId());//流
程执行到end,结束流程实例
System.out.println("当前流程是否结束---->"+instance.isEnded());//true
执行结果:
[state]
当前流程是否位于200节点---->true
当前流程是否结束---->false
-------使流程继续向下执行(结束)------->
当前流程是否结束---->true
Decision节点示例
流程图:
流程定义:
在使用 Decision时,一个 Decision活动应配置为以下三种中的一种
decision 会检查每一个传出的转移里的内置条件。流程的执行会采用第一个内置条件为
true 或者没有设置内置条件的转移
第一种:使用 Decision内置条件(返回 true或 false)
即在流程定义中设置每一个 transition的子节点 condition,并为每一个 condition填
充 expr属性
http://www.blogjava.net/sxyx2008/
形如:
详细的流程定义
观察红色标注的部分
测试代码:
Map map=new HashMap();
//coder为流程定义中表达式的名称
map.put("coder", "200");
ProcessInstance
processInstance=executionService.startProcessInstanceByKey("decision",map);
System.out.println("流程是否处于waite节
点?"+processInstance.isActive("waite"));//true
ProcessInstance
processInstanceDecision=executionService.signalExecutionById(processInstance.ge
http://www.blogjava.net/sxyx2008/
tId());
System.out.println("流程是否处于waite节
点?"+processInstanceDecision.isActive("waite"));//false
System.out.println("流程是否处于gowhere节
点?"+processInstanceDecision.isActive("gowhere"));//false
System.out.println("流程是否处于200节
点?"+processInstanceDecision.isActive("200"));//true
System.out.println("流程是否处于404节
点?"+processInstanceDecision.isActive("404"));//false
System.out.println("流程是否处于 500节
点?"+processInstanceDecision.isActive("500"));//false
代码说明:
在一开始定义了一个 Map,在程序中手动为 coder(详见流程定义中的 condition的 expr属性)
赋值 200,当流程实例启动时运行到 decision时会自动计算每一个 transition节点子节点
condition里面的expr属性(详见流程定义中),如果某一内置条件(condition)执行为true,
则就将流程执行到该节点。在使用此种方式时, condition的 expr中设置的下一活动的活
动名称(name),而不是 transition的 name属性.这里紧跟在 decision活动后有三个活动
200、404、500且三个活动名称依次为 200、404、500,所以程序中为 coder赋值 200就表
示将流程执行到 200这个活动.
执行结果:
流程是否处于waite节点?true
流程是否处于waite节点?false
流程是否处于gowhere节点?false
流程是否处于200节点?true
流程是否处于404节点?false
流程是否处于 500节点?false
第二种:为流程定义中 decision活动设置 expr属性, decision 表达式返回类型为字符串的
向外转移的名字,使用此种方式不用再去为每一个 transiti