工做流Jpbm4.4工做流知识点总结(工做流开发宝典)

原文: 工做流Jpbm4.4工做流知识点总结(工做流开发宝典)

Jbpm工做流开发过程当中的一些知识点总结,方便之后开发使用!html

目录:java

1、工做流框架的搭建mysql

2、工做流框架的流程开发spring

  一、管理流程定义sql

    ①部署流程定义数据库

    ②查询流程定义apache

    ③删除流程定义api

    ④获取部署对象中的文件资源内容tomcat

    ⑤ 获取流程图中某活动的坐标session

  二、执行流程实例

    ①启动流程实例

    ②向后执行一步

    ③查询任务

    ④完成任务

    ⑤拾取任务

    ⑥获取流程中的变量

3、Jbpm和spring整合

 

 

第一章 工做流框架的搭建

1.1. 准备jBPM4.4的开发环境

1.1.1. 添加jBPM4.4jar

  1. ${JBPM_HOME}/jbpm.jar(核心包)
  2. JBPM_HOME/lib/*.jar,不添加如下jar包:servlet-api.jar, junit.jar。其中junit.jar必定不要添加,由于是3.8.2版本,与咱们使用的junit4有冲突。
  3. 所使用的数据库对应的驱动的jar包(第2步所添加的jar包中已包含mysqljdbc驱动jar包)。
  4. 配置文件能够从JBPM_HOME/examples/src/中拷贝:
    jbpm.cfg.xml
    logging.properties//要注意版本的问题,接口和实现类要相同版本
    jbpm.hibernate.cfg.xml
  5. 修改logging.properties中的日志输出级别WARNING: java.util.logging.ConsoleHandler.level=WARNING
  6. 修改jbpm.hibernate.cfg.xml中的数据库链接信息。若是使用MySQL,使用的方言必定要是org.hibernate.dialect.MySQL5InnoDBDialect。
  7. 数据库链接编码必定要是UTF-8。不然可能会在部署含有中文字符的流程定义时会抛异常,说sql语法错误。

第二章 工做流框架的流程开发

1.1. 部署流程定义

注意区分Deployment与ProcessDefinition

1.1.1. 示例代码1:流程定义有关文件在classpath

String deploymentId = processEngine.getRepositoryService()

.createDeployment()

.addResourceFromClasspath("process/test.jpdl.xml")

.addResourceFromClasspath("process/test.png")

.deploy();

1.1.2. 示例代码2:一次添加多个流程定义有关文件(要先打成zip包)

String deploymentId = processEngine.getRepositoryService()

.createDeployment()

.addResourcesFromZipInputStream(zipInputStream)

.deploy();

1.1.3. 说明

1, .addResourceFromClasspath(resource); 能够调用屡次以添加多个文件。文件重复添加也不会报错。

2, .addResourceFromInputStream(resourceName, inputStream)添加一个文件(使用InputStream

3, .addResourcesFromZipInputStream(zipInputStream)添加多个文件,里面也能够有文件夹。

4, 以上方法能够在一块儿调用。

 

1.2. 删除流程定义

1.2.1. 示例代码1:删除流程定义,若是有关联的流程实例信息则报错

repositoryService.deleteDeployment(deploymentId);

1.2.2. ?示例代码2:删除流程定义,并删除关联的流程实例与历史信息

repositoryService.deleteDeploymentCascade(deploymentId);

关联:关联的流程实例,就是流程定义中执行过的那些实例【已经放到了历史表中,级联删除的就是同时删除那些执行过了的实例】,

1.3. 查询流程定义

1.3.1. 相关查询API说明:ProcessDefinitionQuery

RepositoryService.createProcessDefinitionQuery()

 

1.3.2. 示例代码1:查询全部流程定义

// 1,构建查询

ProcessDefinitionQuery pdQuery = processEngine.getRepositoryService() 

.createProcessDefinitionQuery()// 

.orderAsc(ProcessDefinitionQuery.PROPERTY_NAME)//

.orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION);

 

// 2,查询出总数量与数据列表

long count = pdQuery.count();

List<ProcessDefinition> list = pdQuery.page(0, 100).list();// 分页:取出前100条记录

 

// 3,显示结果

System.out.println(count);

for (ProcessDefinition pd : list) {

System.out.println("id=" + pd.getId()//

+ ",deploymentId=" + pd.getDeploymentId()//

+ ",name=" + pd.getName()//

+ ",version=" + pd.getVersion()//

+ ",key=" + pd.getKey()); //

}

1.3.3. 示例代码2:查询全部最新版本的流程定义列表

// 1,查询,按version升序排序,则最大版本排在最后

List<ProcessDefinition> all = processEngine.getRepositoryService()//

.createProcessDefinitionQuery()//

.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION)

.list();

// 2,过滤出全部不一样Key的最新版本(由于最大版本在最后面)

Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>(); // mapkey是流程定义的keymapvlaue是流程定义对象

for (ProcessDefinition pd : all) {

map.put(pd.getKey(), pd);

}

Collection<ProcessDefinition> result = map.values();

// 3,显示结果

for (ProcessDefinition pd : result) {

System.out.println("deploymentId=" + pd.getDeploymentId()// 

+ ",\t id=" + pd.getId()// 流程定义的id,格式:{key}-{version}

+ ",\t name=" + pd.getName()

+ ",\t key=" + pd.getKey()

+ ",\t version=" + pd.getVersion());

}

1.4. 获取部署对象中的文件资源内容

// 资源的名称,就是 jbpm4_lob 表中的 NAME_ 列表值

String deploymentId = "90001";

String resourceName = "test.png"; 

InputStream in = processEngine.getRepositoryService()

.getResourceAsStream(deploymentId, resourceName);

1.5. 获取流程图中某活动的坐标

String processDefinitionId = "test-1"; // 流程定义的id

String activityName = "start1"; // 活动的名称

 

ActivityCoordinates c = processEngine.getRepositoryService()

.getActivityCoordinates(processDefinitionId, activityName);

System.out.println("x=" + c.getX() 

+ ",y=" + c.getY() 

+ ",width=" + c.getWidth() 

+ ",height=" + c.getHeight());

 

2. 执行流程实例

2.1. 启动流程实例

说明:流程实例建立后,直接就到开始活动后的第一个活动,不会在开始活动停留。

2.1.1. 示例代码1:使用指定key的最新版本的流程定义启动流程实例

ProcessInstance pi = processEngine.getExecutionService()

.startProcessInstanceByKey(processDefinitionKey);

2.1.2. 示例代码2:使用指定key的最新版本的流程定义启动流程实例,并设置一些流程变量

// 准备流程变量

Map<String, Object> variables = new HashMap<String, Object>();

variables.put("申请人", "张三");

variables.put("报销金额", 1000.00);

 

// 启动流程实例,并设置一些流程变量

ProcessInstance pi = processEngine.getExecutionService()

.startProcessInstanceByKey(processDefinitionKey, variables);

2.2. 向后执行一步(Signal

2.2.1. 示例代码1:向后执行一步,使用惟一的outcome离开活动

processEngine.getExecutionService().signalExecutionById(executionId);

2.2.2. 示例代码2:向后执行一步,使用惟一的outcome离开活动,并设置一些流程变量

Map<String, Object> variables = new HashMap<String, Object>();

variables.put("审批结果", "赞成");

 

processEngine.getExecutionService()

.signalExecutionById(executionId, variables);

 

2.2.3. 示例代码3:向后执行一步,使用指定的outcome离开活动

String outcome= "to end1";

processEngine.getExecutionService()

.signalExecutionById(executionId, outcome);

2.2.4. 示例代码4:向后执行一步,使用指定的outcome离开活动,并设置一些流程变量

String outcome= "to end1";

Map<String, Object> variables = new HashMap<String, Object>();

variables.put("审批结果", "赞成");

 

processEngine.getExecutionService()

.signalExecutionById(executionId, outcome, variables);

 

2.3. 查询任务

2.3.1. 查询我的任务列表

方式1TaskService.findPersonalTasks(userId);

 

方式2List<Task> list = taskService.createTaskQuery()

.assignee(userId)

.list();

 

// 显示任务信息

for (Task task : taskList) {

System.out.println("id=" + task.getId()// 任务的id

+ ",name=" + task.getName()// 任务的名称

+ ",assignee=" + task.getAssignee()// 任务的办理人

+ ",createTime=" + task.getCreateTime() // 任务的建立(生成)的时间

+ ",executionId=" + task.getExecutionId());// 任务所属流程实例的id

}

2.3.2. 查询组任务列表

方式1 taskService.findGroupTasks(userId);

 

方式2 List<Task> list = processEngine.getTaskService()//

.createTaskQuery()//

.candidate(userId)//

.list();

2.4. 完成任务

2.4.1. 正常完成任务(也能够同时设置一些流程变量)

String taskId = "420001";

processEngine.getTaskService().completeTask(taskId);

 

processEngine.getTaskService().completeTask(taskId, outcome);

 

processEngine.getTaskService().completeTask(taskId, outcome, variables);

 

2.4.2. 自行控制任务完成后是否可向后流转

String taskId = "420001";

 

// 1设置为false表明:办理完任务后不向后移动(默认为true

TaskImpl taskImpl = (TaskImpl) processEngine

.getTaskService().getTask(taskId);

taskImpl.setSignalling(false); 

 

// 2,办理完任务

processEngine.getTaskService().completeTask(taskId);

2.5. 拾取任务

1, TaskService.takeTask(taskId, userId),拾取组任务到我的任务列表中,若是任务有assignee,则会抛异常。

2, processEngine.getTaskService().assignTask(taskId, userId),转交任务给其余人,(若是任务有assignee,则执行这个方法表明从新分配。也能够把assignee设为null表示组任务没有人办理了)

2.6. 设置与获取流程变量

2.6.1. 设置流程变量

2.6.1.1. 方式1:根据 executionId 设置或获取流程变量

ExecutionService.setVariable(executionId, name, value);

 

Object obj = executionService.getVariable(executionId, "请假人");

2.6.1.2. 方式2:根据 taskId 设置或获取流程变量

TaskService.setVariables(taskId, variables); // 一次设置多个变量

 

Object obj = executionService.getVariable(executionId, "请假人");

2.6.1.3. 流程变量所支持的值的类型(jBPM User Guide,7.2. Variable types)

7.2. Variable types

jBPM supports following Java types as process variables:

 java.lang.String 

 java.lang.Long 

 java.lang.Double 

 java.util.Date 

 java.lang.Boolean 

 java.lang.Character 

 java.lang.Byte 

 java.lang.Short 

 java.lang.Integer 

 java.lang.Float 

 byte[] (byte array) 

 char[] (char array) 

 hibernate entity with a long id 

 hibernate entity with a string id 

 serializable

For persistence of these variable, the type of the variable is checked in the order of this list. The first match will determine how the variable is stored. 

2.7. 直接结束流程实例(本身手工结束)

String processInstanceId =  "test.10001";

processEngine.getExecutionService()

.endProcessInstance(processInstanceId, ProcessInstance.STATE_ENDED);

 

第三章  jbpm与spring整合

1.1. 与Spring集成(jBPM4.4 Developers Guide, Chapter 17. Spring Integration

1.1.1. 在jbpm.cfg.xml

1,删除配置:<import resource="jbpm.tx.hibernate.cfg.xml" />

2,增长配置:<import resource="jbpm.tx.spring.cfg.xml" />

1.1.2. 在applicationContext.xml中配置

<!-- 配置ProcessEngine(整合jBPM4) -->

<!-- jbpmCfg是相对于classpath的相对路径,默认值为jbpm.cfg.xml -->

<bean id="springHelper" 

class="org.jbpm.pvm.internal.processengine.SpringHelper">

<property name="jbpmCfg" value="jbpm.cfg.xml"></property>

</bean>

<bean id="processEngine" factory-bean="springHelper" 

factory-method="createProcessEngine" />

1.1.3. 测试

@Test // 测试ProcessEngine

public void testProcessEngine() {

ProcessEngine processEngine = (ProcessEngine)ac.getBean("processEngine");

Assert.assertNotNull(processEngine);

}

 

1.1.4. 注意事项

若是作了JBPM4.4Spring整合(使用了jbpm.tx.spring.cfg.xml),则在程序中就必定要使用Spring注入ProcessEngine,千万不能使用Configuration.getProcessEngine()生成ProcessEngine,由于这时内部的代码有如下逻辑:若是整合了Spring但没有ApplicationContext,就默认读取applicationContext.xml建立ApplicationContext实例并从中获取名为”ProcessEngine”的对象。而这时若是把pe = Configuration.getProcessEngine()写成某Spring中管理的bean的初始化代码,就会有无限循环,不停的建立ApplicationContext了!

1.2. 自行控制事务

1, 修改 jbpm.tx.hibernate.cfg.xml

a) 不让jBPM自行管理事务:去掉<standard-transaction-interceptor />

b) 让Jbpm使用SessionFactory.getCurrentSession():修改成 <hibernate-session current="true" />

2, 配置可使用SessionFactory.getCurrentSession(),在jbpm.hibernate.cfg.xml 中配置:<property name="hibernate.current_session_context_class">thread</property>

3, 要使用同一个SessionFactory,且都要使用 SessionFactory.getCurrentSession() 获取 Session

a) 同一个SessionFactorySessionFactory sf = processEngine.get(SessionFactory.class)

b) 在 BaseDaoImpl 中增长:

  1. getSession() { return HibernateUtils.getSessionFactory().getCurrentSession(); }
  2. getProcessEngine(){ return org.jbpm.api.Configuration.getProcessEngine(); }

4, 统一的打开与提交或回滚事务:使用 OpenSessionInViewFilter 控制事务。

 

1.3. 启动Tomcat后,访问JSP时(使用的是MyEclipse自带的Tomcat,是6.0的版本),报错:   Caused by: java.lang.LinkageError: loader constraints violated when linking javax/el/ExpressionFactory class

at org.apache.jsp.WEB_002dINF.jsp.UserAction.loginUI_jsp._jspInit(loginUI_jsp.java:39)

at org.apache.jasper.runtime.HttpJspBase.init(HttpJspBase.java:52)

at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:159)

at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:329)

at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)

at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)

... 40 more

 

说明:缘由是Jbpmjuel.jar, juel-engine.jar, juel-impl.jar包和Tomcat6.0中的el-api.jar包冲突了。

有三个解决办法:

1,方法一:在MyEclipsePreferences -> MyEclipse -> Application Servers -> Tomcat -> .. -> Paths 中配置 Append to classpath,选中 juel.jar, juel-engine.jar, juel-impl.jar 这三个jar包就能够了。

2,方法二:将 juel.jar, juel-engine.jar, juel-impl.jar 这三个包复制到tomcat6下 lib/ 中,并删除原来的el-api.jar

切记还要把工程中 WEB-INF\lib 下的 juel.jar, juel-engine.jar, juel-impl.jar 删除,否则仍是要冲突。

3,方法三:换成tomcat5.5,就没有问题了。

 

1.4. 完成流程实例中的最后一个任务时报错(任务实例结束时),或删除流程定义级联删除流程实例时,报错以下:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`itcastoa_20100909/jbpm4_execution`, CONSTRAINT `FK_EXEC_INSTANCE` FOREIGN KEY (`INSTANCE_`) REFERENCES `jbpm4_execution` (`DBID_`))

 

解决办法:把方言设为 MySQL5InnoDBDialect,不能是 MySQLDialect

相关文章
相关标签/搜索