`

jbpm_工作流框架笔记

    博客分类:
  • jbpm
 
阅读更多

1. 工作流基础

1.1. 工作流相关概念

工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。

通俗的说,流程就是多个人在一起合作完成某件事情的步骤,把步骤变成计算机能理解的形式就是工作流

 

 

工作流管理系统(WfMSWorkflow Management System)的主要功能是通过计算机技术的支持去定义、执行和管理工作流,协调工作流执行过程中工作之间以及群体成员之间的信息交互。工作流需要依靠工作流管理系统来实现。工作流管理系统是定义、创建、执行工作流的系统,应能提供以下三个方面的功能支持:

1. 定义工作流:包括具体的活动、规则等

2. 运行控制功能:在运行环境中管理工作流过程,对工作流过程中的活动进行调度

3. 运行交互功能:指在工作流运行中,WfMS与用户(活动的参与者)及外部应用程序工具交互的功能。

 

一、 定义工作流

二、 执行工作流

 

采用工作流管理系统的优点

1. 提高系统的柔性,适应业务流程的变化 

2. 实现更好的业务过程控制,提高顾客服务质量

3. 降低系统开发和维护成本

 

工作流框架有:JbpmOSWorkflowActiveBPELYAWL等

 

OA(办公自动化)主要技术之一就是工作流。

1.2. 开源工作流jBPM4.4介绍

jBPM java Business Process Management,是基于java的业务流程管理系统。jBPM是市面上相当流行的一款开源工作流引擎,引擎底层基于Active Diagram模型。jBPM4.4使用了hibernate3.3.1版),因此可以很好的支持主流数据库。jBPM4.4共有18张表。

jBPM官方主页http://www.jboss.org/jbpm

2. 准备jBPM4.4环境

2.1. jBPM4.4所需环境

jBPM requires a JDK (standard java) version 5 or higher. http://java.sun.com/javase/downloads/index.jsp 

To execute the ant scripts, you'll need apache ant version 1.7.0 or higher: http://ant.apache.org/bindownload.cgi

2.2. 下载相关资源

1, jBPM下载地址:http://sourceforge.net/projects/jbpm/files/

2, Eclipse下载地址( Eclipse IDE for Java EE Developers (163 MB)Version3.5 ):http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/galileo

2.3. 安装流程设计器(GPDEclipse插件)

GPDGraphical Process Designer)是一个Eclipse插件。

安装方法说明(jBPM4.4User Guide, 2.11.2. Install the GPD plugin into eclipse):

 Help --> Install New Software... 

 Click Add... 

 In dialog Add Site dialog, click Archive... 

 Navigate to install/src/gpd/jbpm-gpd-site.zip and click 'Open' 

 Clicking OK in the Add Site dialog will bring you back to the dialog 'Install' 

 Select the jPDL 4 GPD Update Site that has appeared 

 Click Next... and then Finish 

 Approve the license 

 Restart eclipse when that is asked

 

 

 

查看是否成功安装了插件:WindowàPreference中是否有Jboss jBPM项。

2.4. 在Eclipse中添加jPDL4.4 Schema校验

流程定义文件的xsd文件的路径为:JBPM_HOME/src/jpdl-4.4.xsd

添加到Eclipse中的方法为(jBPM4.4 User Guide, 2.11.5. Adding jPDL 4 schema to the catalog):

 Click Window --> Preferences 

 Select XML --> XML Catalog 

 Click 'Add...' 

 The 'Add XML Catalog Entry' dialog opens 

 Click the button with the map-icon next to location and select 'File System...' 

 In the dialog that opens, select file jpdl-4.4.xsd in the src directory of the jBPM installation root. 

 Click 'Open' and close all the dialogs

 

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

2.5.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包)。

2.5.2. 添加并定制配置文件

1. 配置文件可以从JBPM_HOME/examples/src/中拷贝:
jbpm.cfg.xml
logging.properties
jbpm.hibernate.cfg.xml

2. 修改logging.properties中的日志输出级别WARNING: java.util.logging.ConsoleHandler.level=WARNING

3. 修改jbpm.hibernate.cfg.xml中的数据库连接信息。如果使用MySql,使用的方言一定要是org.hibernate.dialect.MySQL5InnoDBDialect。

4. 数据库连接编码一定要是UTF-8。否则可能会在部署含有中文字符的流程定义时会抛异常,说sql语法错误。

 

 

说明:如果要改变jbpm.hibernate.cfg.xml的文件名称,需要做:

1、从JBPM_HOME/src/中拷贝jbpm.tx.hibernate.cfg.xml放到工程的src/下,然后进行修改。

2、修改jbpm.tx.hibernate.cfg.xml中的hibernate主配置文件的路径配置(指定的是相对于classpath的相对路径)。

 

2.5.3. 初始化数据库

1, 方法一:执行sql脚本文件${JBPM4.4_HOME}/install/src/db/create/jbpm.*.create.sql

2, 方法二:使用Hibernate的自动建表,在jbpm.hibernate.cfg.xml中配置:hibernate.hbm2ddl.auto=update

3. 核心概念与相关API(Service API)

3.1. 概念:Process definition, process instance ,  execution

3.1.1. Process definition

ProcessDefinition,流程定义:

一个流程的步骤说明。如一个请假流程、报销流程、借款流程等,是一个规则。

例:

 

3.1.2. Process instance

ProcessInstance,流程实例:

代表流程定义的一次执行。如张三昨天按请假流程请了一次假。一个流程实例包括了所有运行阶段, 其中最典型的属性就是跟踪当前节点的指针。

 

3.1.3. Execution

Execution,执行:

一般情况下,一个流程实例是一个执行树的根节点。 

使用树状结构的原因在于, 这一概念只有一条执行路径, 使用起来更简单。 业务API不需要了解流程实例和执行之间功能的区别。 因此, API里只有一个执行类型来引用流程实例和执行。

 

 

假设汇款和存档可以同时执行,那么主流程实例就包含了2个用来跟踪状态的子节点:

 

 

4.1. ProcessEngineService API

4.1.1. ConfigurationProcessEngine

Interacting with jBPM occurs through services. The service interfaces can be obtained from the ProcessEngine which is build from a Configuration. A ProcessEngine is thread safe and can be stored in a static member field.

 

使用默认的配置文件(jbpm.cfg.xml生成Configuration并构建ProcessEngine

ProcessEngine processEngine = new Configuration()

.buildProcessEngine();

或是使用如下代码获取使用默认配置文件的、单例的ProcessEngine对象:

ProcessEngine processEngine = Configuration.getProcessEngine();

或是使用指定的配置文件(要放到classPath):

ProcessEngine processEngine = new Configuration()

      .setResource("my-own-configuration-file.xml")

      .buildProcessEngine();

 

4.1.2. jBPM Service API

jBPM所有的操作都是通过Service完成的,以下是获取Service的方式:

RepositoryService repositoryService = processEngine

.getRepositoryService();

ExecutionService executionService = processEngine

.getExecutionService();

TaskService taskService = processEngine

.getTaskService();

HistoryService historyService = processEngine

.getHistoryService();

ManagementService managementService = processEngine

.getManagementService();

 

各个Service的作用:

RepositoryService

管理流程定义

ExecutionService

管理执行的,包括启动、推进、删除Execution等操作

TaskService

管理任务的

HistoryService

历史管理(执行完的数据管理,主要是查询

IdentityService

jBPM的用户、组管理

ManagementService

 

4.1.3. API风格

方法调用链

 

每一个方法都是流程有关的一个业务操作,默认是一个独立的事务。

4.1.4. 查询的有关API(风格)

功能说明

相应的查询API

查询“流程定义”

ProcessDefinitionQuery processDefinitionQuery = 

processEngine.getRepositoryService()

.createProcessDefinitionQuery();

查询“执行对象”

(流程实例)

ProcessInstanceQuery processInstanceQuery = 

processEngine.getExecutionService() //

.createProcessInstanceQuery();

查询“任务”

TaskQuery taskQuery = //

processEngine.getTaskService()//

.createTaskQuery();

查询“执行历史”

(流程实例历史)

HistoryProcessInstanceQuery historyProcessInstanceQuery = 

processEngine.getHistoryService()

.createHistoryProcessInstanceQuery();

查询“任务历史”

HistoryTaskQuery historyTaskQuery = 

processEngine.getHistoryService()

.createHistoryTaskQuery();

 

以上列出的Query对象有:

1. ProcessDefinitionQuery

2. ProcessInstanceQuery

3. TaskQuery

4. HistoryProcessInstanceQuery

5. HistoryTaskQuery

 

这些Query对象的使用方法都是一致的,如下所示:

1, 添加过滤条件:调用其中的有关方法指定条件即可。如:

a) processDefinitionQuery.processDefinitionKey("请假")是指定查询key请假的流程定义;

b) taskQuery.assignee("张三")是指定办理人为张三的任务。

2, 添加排序条件:

a) 调用 xxQuery.orderAsc(property),表示按某属性升序排列

b) 调用 xxQuery.orderDesc(property),表示按某属性降序排列

c) 可指定多个排序条件,就是代表第1顺序,第2顺序…等。

d) 属性名在各自的Query对象(接口)中有常量定义,如:

i. ProcessDefinitionQuery.PROPERTY_ID

ii. ProcessDefinitionQuery.PROPERTY_KEY

iii. TaskQuery.PROPERTY_NAME

iv. TaskQuery.PROPERTY_ASSIGNEE

3, 指定分页有关信息:

a) 调用方法xxQuery.page(firstResultmaxResults);

b) 这是指定firstmax的值(就是Hibernate中的Query.setFirstResult()Query.setMaxResults()

c) 如果没有调用这个方法,代表要查询出符合条件的所有记录。

4, 查询得到结果:

a) 调用方法xxQuery.list(); 表示查询列表

b) 调用方法 xxQuery.uniqueResult(); 表示查询唯一的结果

c) 调用方法xxQuery.count(); 表示查询符合条件的记录数量

 

 

 

5. 管理流程定义

没有更新功能

5.1. 部署流程定义

注意区分Deployment与ProcessDefinition

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

String deploymentId = processEngine.getRepositoryService()

.createDeployment()

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

.addResourceFromClasspath("process/test.png")

.deploy();

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

String deploymentId = processEngine.getRepositoryService()

.createDeployment()

.addResourcesFromZipInputStream(zipInputStream)

.deploy();

5.1.3. 说明

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

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

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

4, 以上方法可以在一起调用。

 

5.2. 删除流程定义

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

repositoryService.deleteDeployment(deploymentId);

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

repositoryService.deleteDeploymentCascade(deploymentId);

5.3. 查询流程定义

5.3.1. 相关查询API说明:ProcessDefinitionQuery

RepositoryService.createProcessDefinitionQuery()

 

5.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()); //

}

5.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());

}

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

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

String deploymentId = "90001";

String resourceName = "test.png"; 

InputStream in = processEngine.getRepositoryService()

.getResourceAsStream(deploymentId, resourceName);

5.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());

 

6. 执行流程实例

6.1. 启动流程实例

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

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

ProcessInstance pi = processEngine.getExecutionService()

.startProcessInstanceByKey(processDefinitionKey);

6.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);

6.2. 向后执行一步(Signal

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

processEngine.getExecutionService().signalExecutionById(executionId);

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

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

variables.put("审批结果""同意");

 

processEngine.getExecutionService()

.signalExecutionById(executionId, variables);

 

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

String outcome"to end1";

processEngine.getExecutionService()

.signalExecutionById(executionId, outcome);

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

String outcome"to end1";

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

variables.put("审批结果""同意");

processEngine.getExecutionService()

.signalExecutionById(executionId, outcome, variables);

 

6.3. 查询任务

6.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

}

6.3.2. 查询组任务列表

方式1 taskService.findGroupTasks(userId);

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

.createTaskQuery()//

.candidate(userId)//

.list();

6.4. 完成任务

6.4.1. 正常完成任务(也可以同时设置一些流程变量)

String taskId = "420001";

processEngine.getTaskService().completeTask(taskId);

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

 

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

 

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

String taskId = "420001";

 

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

TaskImpl taskImpl = (TaskImpl) processEngine

.getTaskService().getTask(taskId);

taskImpl.setSignalling(false); 

// 2,办理完任务

processEngine.getTaskService().completeTask(taskId);

6.5. 拾取任务

1, TaskService.takeTask(taskId, userId),拾取组任务到个人任务列表中,如果任务有assignee,则会抛异常。

2, processEngine.getTaskService().assignTask(taskId, userId),转交任务给其他人,(如果任务有assignee,则执行这个方法代表重新分配。也可以把assignee设为null表示组任务没有人办理了)

6.6. 设置与获取流程变量

6.6.1. 设置流程变量

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

ExecutionService.setVariable(executionId, name, value);

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

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

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

 

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

6.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. 

6.7. 直接结束流程实例(自己手工结束)

String processInstanceId = "test.10001";

processEngine.getExecutionService()

.endProcessInstance(processInstanceId, ProcessInstance.STATE_ENDED);

7. jBPM4.4的流程定义语言(设计流程)

7.1. process(流程)

.jpdl.xml的根元素,可以指定的属性有:

属性名

作用说明

name

流程定义的名称,用于显示。

key

流程定义的key,用于查询。

如未指定,则默认为name的值。

version

版本,如果指定,则不能与已有的流程定义的版本重复;如未指定,则此key的流程定义的第1个为版本1,以后的是版本递增(每次加1

   

 

7.2. transition(连线、转移)

1, 一个活动中可以指定一个或多个TransitionStart中只能有一个,End中没有)。

a) 开始活动中只能有一个Transition

b) 结束活动中没有Transition

c) 其他活动中有1条或多条Transition

2, 如果只有一个,则可以不指定名称(名称是null);如果有多个,则要分别指定唯一的名称。

7.3. 流转控制活动

7.3.1. start(开始活动)

代表流程的开始边界,一个流程有且只能有一个Start活动。开始活动只能指定一个Transition。在流程实例启动后,会自动的使用这个唯一的Transition离开开始活动,到一下个活动。

7.3.2. endend-errorend-cancel(结束活动)

代表流程的结束边界,可以有多个,也可以没有。如果有多个,则到达任一个结束活动,整个流程就都结束了;如果没有,则到达最后那个没有Transition的活动,流程就结束了。

7.3.3. state(状态活动)

功能:等待。

7.3.4. task(任务活动)

分配任务:

1, actor=#{String型的变量}

2, AssignmentHandler,需要在<task>元素中写<assignment-handler class="AssignmentHandlerImpl"/>子元素。

a) 指定的类要实现AssignmentHandler接口

b) 在其中可以使用Assignable.setAssignee(String),分配个人任务。

 

7.3.5. decision(判断活动)

1,使用expression,如:expr="#{'to state2'}"

2,使用Handler,要实现DecisionHandler接口

3,如果同时配置了expressionHandler,则expression有效,忽略Handler

 

7.3.6. forkjoin(分支/聚合活动)

这是多个分支并行(同时)执行的,并且所有的分支Execution都到Join活动后才离向后执行。

7.4. 自定义活动(Custom

1,在<custom>元素中指定class属性为指定的类。

2,这个类要实现ExternalActivityBehaviour接口,其中有两个方法:

1execute(ActivityExecution),节点的功能代码

2signal(ActivityExecution, String, Map),在当前节点等待时,外部发信号时的行为

3,在execute()方法中,可以调用以下方法对流程进行控制

1ActivityExecution.waitForSignal(),在当前节点等待。

2ActivityExecution.takeDefaultTransition(),使用默认的Transition离开,当前节点中定义的第一个为默认的。

3ActivityExecution.take(String transitionName),使用指定的Transition离开

4ActivityExecution.end(),结束流程实例

4,也可以实现ActivityBehaviour接口,只有一个方法execute(ActivityExecution),这样就不能等待,否则signal时会有类转换异常。

 

7.5. 事件

1, 在根元素中,或在节点元素中,使用<on event="">元素指定事件,其中event属性代表事件的类型。

2, 在<on>中用子元素<event-listener class="EventListenerImpl" />,指定处理的类,要求指定的类要实现EventListener接口

3,  事件类型:

a) <on>元素放在根元素(<process>)中,可以指定eventstartend,表示流程的开始与结束。

b) <on>元素放在节点元素中,可以指定eventstartend,表示节点的进入与离开

c) 在Start节点中只有end事件,在End节点中只有start事件。

d) 在<transition>元素中直接写<event-listener class="">,就是配置事件。(因为在这里只有一个事件,所以不用写on与类型)

e) 在<task>元素中还可以配置assign事件,是在分配任务时触发的。

 

8. jBPM4.4应用

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

8.1.1. 在jbpm.cfg.xml

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

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

8.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" />

8.1.3. 测试

@Test // 测试ProcessEngine

public void testProcessEngine() {

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

Assert.assertNotNull(processEngine);

}

 

8.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了!

8.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 中增加:

i. getSession() { return HibernateUtils.getSessionFactory().getCurrentSession(); }

ii. getProcessEngine(){ return org.jbpm.api.Configuration.getProcessEngine(); }

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

 

8.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,就没有问题了。

 

8.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

分享到:
评论

相关推荐

    【人工智能产业链分析】2018-2024年中国各地区AI产业集中度与财务状况及产业话语权研究

    中国全国AI人工智能产业链关系2018-2024集中度指标按地区分销售财务情况产业话语权指标等 数据来源:基于国内各部委公布数据及各地统计数据整理,或相关省、市数据 数据范围:全国、或各省份地市的统计数据 数据期间:(参见其文件名的标识表达了数据年度、或月度日度期间) 主要指标: 包含的数据文件有: 中国全国AI人工智能产业链产业基本情况2020-2024.zip 中国全国AI人工智能产业链产业上市公司按地区分销售情况统计表2020-2024.zip 中国全国AI人工智能产业链产业上市公司财务情况统计表2020-2024.zip 中国全国AI人工智能产业链产业上市公司销售情况统计表2020-2024.zip 中国全国AI人工智能产业链产业政策信息表2020-2024.zip 中国全国AI人工智能产业链关系表2024.zip 中国全国AI人工智能产业链集中度指标表2020-2024.zip 中国全国AI人工智能产业链名单2024.zip 中国全国AI人工智能产业链企业基本信息表2018-202501.zip 中国全国AI人工智能产业链企业名单2024.zip 中国全国AI人工智能产业链上市公司产业话语权指标表2020-2024.zip (近百MB数据的网盘链接)

    DOS游戏 - RPG - 侠客英雄传3

    注意事项: 1、运行游戏方法 :双击 “侠客英雄传3.bat” 运行。 2、更换光碟提示: 使用 CTRL+F4 组合键后 按空格即可跳过。

    电力电子领域两相交错并联Buck/Boost变换器的Matlab/Simulink仿真及控制策略分析

    内容概要:本文详细介绍了两相交错并联Buck/Boost变换器的建模与仿真,重点探讨了三种不同的控制方式及其性能表现。首先,文章描述了模型的基本架构,包括两个桥臂共用直流母线,MOSFET采用理想的双向开关,电流传感器安装在电感支路上。接着,分别讨论了开环控制、电压单环控制和电压电流双闭环控制的具体实现方法和优缺点。开环模式适用于观察硬件参数的影响,电压单环控制虽然稳定但在负载突变时响应较慢,而双闭环控制能够显著提高系统的动态响应和电流均流效果。此外,文章还分享了一些实用的仿真技巧,如正确设置死区时间和仿真步长,确保仿真的准确性和效率。 适合人群:电力电子工程师、科研人员、高校师生等对DC-DC变换器设计和仿真感兴趣的读者。 使用场景及目标:①研究两相交错并联Buck/Boost变换器的工作原理和控制策略;②优化变换器的设计参数,提高系统的稳定性和效率;③掌握Matlab/Simulink进行复杂电力电子系统仿真的方法和技术。 其他说明:文中提供了详细的代码片段和仿真波形,帮助读者更好地理解和应用相关理论和技术。

    ffmpeg7.0 + sdl3.0 播放音频

    ffmpeg7.0 + sdl3.0 播放音频

    基于龙贝格观测器的PMSM无传感器控制技术解析与应用

    内容概要:本文深入探讨了基于龙贝格观测器的永磁同步电机(PMSM)无传感器控制技术。首先介绍了龙贝格观测器相较于传统滑模观测器(SMO)的优势,特别是在减少系统抖振方面表现突出。接着详细解释了龙贝格观测器的工作原理,包括状态预测、误差补偿以及角度解算三大核心步骤,并提供了具体的代码实现。文中还讨论了实际工程应用中的挑战,如参数选择、噪声处理等问题,并给出了相应的解决方案。此外,文章通过实验数据展示了龙贝格观测器在不同工况下的性能优势,尤其是在高速和低速情况下的稳定性和响应速度。 适合人群:从事电机控制系统研究与开发的技术人员,尤其是关注无传感器控制领域的工程师。 使用场景及目标:适用于希望提升PMSM无传感器控制系统的稳定性、精确度的研发团队。主要目标是在保持高性能的同时降低系统复杂度,提高产品竞争力。 其他说明:文中不仅分享了理论知识和技术细节,还提供了大量实用的经验技巧,帮助读者更好地理解和应用龙贝格观测器进行实际项目开发。

    PMSM伺服系统转动惯量与阻尼系数在线辨识方法及仿真研究

    内容概要:本文深入探讨了永磁同步电机(PMSM)伺服系统的转动惯量和阻尼系数的在线辨识方法。文中介绍了两种主要的辨识方程:一种用于空载工况,另一种用于负载工况。通过详细的数学推导和Python、C、MATLAB代码示例,展示了如何在不同工况下精准辨识这些参数。此外,还讨论了1.5拍延时补偿、全电压前馈补偿和相电压重构等关键技术,以提高辨识精度和系统稳定性。仿真结果显示,在空载和负载突变情况下,辨识误差分别低于0.8%和2.3%。 适合人群:从事电机控制、自动化控制领域的研究人员和技术人员,尤其是对PMSM伺服系统感兴趣的工程师。 使用场景及目标:适用于需要在线辨识PMSM伺服系统转动惯量和阻尼系数的应用场合,如工业机器人、数控机床等。目标是在不影响正常生产的情况下,实时监测和调整电机参数,提升系统性能。 其他说明:本文不仅提供了理论推导和算法实现,还给出了具体的代码示例和仿真结果,便于读者理解和应用。同时,文中提到的技术可以作为其他类似算法验证的良好参考。

    (源码)基于Arduino的精确计时与PWM控制系统.zip

    # 基于Arduino的精确计时与PWM控制系统 ## 项目简介 本项目基于Arduino的TimerOne库,该库是Arduino平台上用于精确计时和PWM控制的开源库。主要面向Arduino板上的ATmega系列微控制器,可实现设置定时器、产生PWM信号、定时中断等功能,用于精确控制时间和电机速度。 ## 项目的主要特性和功能 1. 初始化定时器,设置初始参数。 2. 根据用户指定微秒数设置定时器周期。 3. 设定PWM输出的占空比,控制PWM输出大小。 4. 启动和停止PWM输出。 5. 设定和停止中断服务例行程序。 6. 重新启动和重置定时器。 7. 停止定时器计数。 8. 读取当前定时器的计数值并转换为微秒数。 ## 安装使用步骤 ### 安装 用户已下载项目源码文件后,可通过Arduino IDE的库管理器搜索并安装TimerOne库。 ### 使用 在代码中引入#include <TimerOne.h>,即可使用上述功能。

    weixin242基于微信小程序的外卖点餐系统设计与实现ssm(文档+源码)_kaic

    weixin242基于微信小程序的外卖点餐系统设计与实现ssm(文档+源码)_kaic

    (源码)基于Arduino的Wemos Mqtt Alarm Panel项目.zip

    # 基于Arduino的Wemos Mqtt Alarm Panel项目 ## 项目简介 本项目是一个基于Arduino平台的开源智能报警面板项目,命名为“Wemos Mqtt Alarm Panel”。该项目允许用户通过简单的MQTT操作来触发和控制报警系统。主要面向需要低成本、易于部署的智能家居或小型商业场所报警系统。项目仍在开发阶段,但已经具备基本功能并可供使用。 ## 项目的主要特性和功能 1. 低成本硬件需求主要使用Wemos D1 Mini或其他兼容的微控制器,以及Lolin 2.4英寸TFT显示屏。整体硬件成本较低,易于获取和部署。 2. 基于MQTT通信协议允许报警系统与MQTT服务器进行通信,实现远程控制和状态报告功能。 3. 界面友好采用直观的图形界面,支持触摸操作,方便用户进行交互。 4. 校准功能提供校准界面,确保触摸操作的准确性。 5. 可扩展性支持自定义报警事件和动作,允许用户根据需求进行个性化设置。 ## 安装使用步骤

    MATLAB实现SSA-ESN多输出回归:代码解析与应用实例

    内容概要:本文详细介绍了一个基于MATLAB的SSA-ESN(奇异谱分析-回声状态网络)多输出回归代码。该代码适用于处理复杂的非线性回归问题,具有多输出支持、友好的数据格式、丰富的可视化效果以及全面的评价指标等特点。文中不仅提供了详细的代码解析,还给出了具体的操作步骤和注意事项,帮助初学者快速理解和应用这一先进的回归方法。主要内容分为数据预处理、模型训练与预测、结果分析与可视化三个部分,涵盖了从数据准备到最终结果呈现的完整流程。 适合人群:对机器学习感兴趣特别是想学习和应用SSA-ESN进行多输出回归的新手程序员和研究人员。 使用场景及目标:①用于解决多输出的非线性回归问题;②提供一个完整的项目案例,帮助用户理解SSA-ESN的工作机制及其优势;③通过实际操作加深对机器学习理论的理解。 其他说明:代码已调试完毕,可以直接运行,附有详细的中文注释,便于学习和修改。此外,文中还提到了一些常见的错误及解决方案,如数据格式不匹配等问题。

    基于Matlab的模拟射击自动报靶系统:图像处理与计算机视觉技术实现高效报靶

    内容概要:本文详细介绍了一个基于Matlab的模拟射击自动报靶系统的实现方法。该系统利用图像处理技术和计算机视觉技术,通过一系列步骤如图像滤波、图像减影、二值化、噪声滤除、目标矫正、弹孔识别和环值判定,实现了对射击靶纸的自动化处理。此外,文中还介绍了如何使用Matlab的GUIDE工具创建友好的GUI界面,使系统更易于操作。系统不仅提高了报靶的速度和准确性,还在军事训练和民用射击活动中展现出广阔的应用前景。 适合人群:对图像处理、计算机视觉感兴趣的研发人员和技术爱好者,尤其是有一定Matlab基础的用户。 使用场景及目标:适用于射击训练和比赛中,用于快速准确地报靶,提高训练效率和比赛公平性。目标是通过自动化手段减少人工干预,确保报靶结果的客观性和实时性。 其他说明:文中提供了详细的代码示例和优化技巧,帮助读者更好地理解和实现该系统。此外,作者还分享了一些常见问题的解决方案,如光照突变、靶纸反光等问题的应对措施。

    【Docker Compose】高级编排实战指南:涵盖Web全栈、AI/ML、IoT、监控、CI/CD等多领域应用部署摘要 本文

    内容概要:本文深入探讨了 Docker Compose 的高级应用,旨在帮助用户从基础用户成长为能够驾驭复杂系统编排的专家。文章首先介绍了 Docker Compose 的核心高级特性,如 profiles、extends、depends_on、healthcheck、自定义网络、卷管理和环境变量管理。接着,通过 30 多个实战模板,覆盖了 Web 全栈、AI/ML、IoT、监控、CI/CD 等多个领域的复杂场景,展示了如何利用这些特性构建高效、可靠的应用环境。每个模板不仅提供了详细的代码示例,还附有解释要点,帮助读者理解其工作原理和应用场景。 适用人群:具备一定 Docker 基础,希望提升 Docker Compose 使用技能的开发者和运维人员,特别是那些需要管理复杂多服务应用的 DevOps 工程师。 使用场景及目标: 1. **Web 开发**:构建 LEMP、MERN 等全栈应用,简化开发和部署流程。 2. **数据处理**:实现 ETL 流程,结合消息队列和数据库进行高效数据处理。 3. **微服务架构**:使用 API 网关简化微服务入口管理,提升服务发现和路由配置的灵活性。 4. **监控与日志**:搭建 PLG 或 ELK 日志系统,实现日志的收集、存储和可视化。 5. **物联网**:构建 MQTT Broker 和时序数据库,支持 IoT 设备的数据接收和处理。 6. **机器学习**:部署 TensorFlow Serving 或 TorchServe,提供模型服务接口。 7. **CI/CD**:快速搭建 GitLab/Gitea 平台,支持代码托管和持续集成。 8. **安全测试**:使用 OWASP ZAP 对 Web 应用进行自动化或手动的安全扫描。 9. **教育与学习**:部署 Moodle,在线学习管理系统,支持课程创建和

    基于COMSOL的注浆技术仿真:浆液扩散特性与优化方案

    内容概要:本文详细探讨了利用COMSOL软件对注浆技术进行仿真的方法和技术细节。主要内容包括浆液扩散的数学建模、仿真模型的构建(如几何模型、边界条件、初始条件和控制方程)、关键参数(注浆压力、孔间距、地质条件)对浆液扩散的影响分析,以及实际工程应用案例。文中通过具体实例展示了如何通过仿真优化注浆施工参数,提高注浆效率并降低成本。此外,还讨论了倾斜裂隙、孔隙率和渗透率等因素对浆液扩散的具体影响及其应对措施。 适合人群:从事地下工程施工的技术人员、科研人员及高校相关专业师生。 使用场景及目标:①用于优化注浆施工方案,提高注浆效果;②为地下工程建设提供技术支持;③帮助研究人员深入理解浆液扩散机制。 其他说明:文章不仅提供了理论分析,还包括大量具体的代码示例和实践经验分享,有助于读者更好地理解和应用COMSOL仿真技术。

    【信息安全领域】实战项目汇总:涵盖网络渗透测试、Web应用安全加固、企业安全策略制定等多方面内容

    内容概要:本文列举了多个信息安全领域的实战项目示例,涵盖网络渗透测试、Web应用安全加固、企业安全策略制定与实施、恶意软件分析、数据泄露应急响应、物联网设备安全检测、区块链安全审计和云安全防护八大方面。每个项目均明确了具体的目标与步骤,如网络渗透测试通过模拟攻击发现并修复系统漏洞;Web应用安全加固则从代码审查、输入验证、身份验证、数据加密等方面确保应用安全;企业安全策略制定旨在构建全面的信息安全体系;恶意软件分析深入探究其功能与传播机制;数据泄露应急响应项目则聚焦于快速遏制影响、调查原因、恢复系统;物联网设备安全检测保障设备的安全性;区块链安全审计确保系统稳定可靠;云安全防护构建云环境下的安全体系。; 适合人群:信息安全从业人员、网络安全工程师、企业IT管理人员、安全研究人员。; 使用场景及目标:适用于希望深入了解信息安全各细分领域实战操作的专业人士,目标是掌握不同类型安全项目的实施流程与技术要点,提升实际工作中应对安全挑战的能力。; 其他说明:文中提供的项目示例不仅有助于理论学习,更为实际工作提供了具体的指导和参考,帮助相关人员在不同场景下有效开展信息安全工作,确保信息系统的安全性、稳定性和可靠性。

    基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码(毕业设计&课程设计&项目开发)

    基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用 基于matlab实现的博弈方法的电动汽车充电调度策略研究+源码,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用

    基于Matlab的违规限号车牌识别管理系统:从粗定位到精准识别

    内容概要:本文详细介绍了基于Matlab的违规限号车牌识别管理系统的开发过程和技术细节。系统主要分为多个步骤,包括车牌粗定位、灰度化、倾斜矫正、二值化、形态学处理、反色处理、精准定位、字符分割与识别、限号判断、语音播报和违规车牌信息导出。通过这些步骤,系统能够高效地识别并处理违规限号车辆,提升交通管理水平。 适用人群:适用于具有一定编程基础的技术人员,特别是对计算机视觉和数字图像处理感兴趣的开发者。 使用场景及目标:本系统主要用于城市交通管理部门,帮助执法人员快速识别和处理违反限号规定的车辆,提高交通管理的智能化水平。具体应用场景包括但不限于道路监控、停车场管理和临时检查点等。 其他说明:文中提供了大量Matlab代码示例,详细解释了各个步骤的具体实现方法。此外,作者还分享了许多实际开发过程中遇到的问题及其解决方案,有助于读者更好地理解和应用这些技术。

    2000-2017年各省国有经济煤气生产和供应业固定资产投资数据

    2000-2017年各省国有经济煤气生产和供应业固定资产投资数据 1、时间:2000-2017年 2、来源:国家统计j、能源nj 3、指标:行政区划代码、城市、年份、国有经济煤气生产和供应业固定资产投资 4、范围:31省

    HDRI大全三维环境切图

    HDRI大全三维环境切图

    ADAS系统核心技术解析:ACC、FCW、AEB、LKA的设计与实现

    内容概要:本文详细介绍了ADAS(高级驾驶辅助系统)中四个主要功能模块的设计与实现,分别是自适应巡航控制系统(ACC)、前向碰撞预警系统(FCW)、自动紧急制动系统(AEB)和车道保持辅助系统(LKA)。文章不仅展示了各个系统的具体算法实现,如ACC中的PID控制、FCW中的TTC计算、AEB中的状态机设计和LKA中的PD控制器,还分享了许多实际开发中的经验和挑战,如参数调校、传感器融合、时间同步等问题。此外,文中还提到了一些有趣的细节,如在暴雨天气下LKA的表现优化,以及AEB系统在测试过程中遇到的各种corner case。 适合人群:汽车电子工程师、自动驾驶研究人员、嵌入式软件开发者。 使用场景及目标:帮助读者深入了解ADAS系统的工作原理和技术细节,掌握关键算法的实现方法,提高在实际项目中的开发和调试能力。 其他说明:文章通过生动的语言和具体的代码示例,使复杂的理论变得通俗易懂,有助于初学者快速入门并深入理解ADAS系统的开发流程。

    (源码)基于PHP的历史年表聚合网站.zip

    # 基于PHP的历史年表聚合网站 ## 项目简介 本项目是一个历史年表的聚合网站,采用PHP编程语言开发。网站包含了众多功能函数,可处理系统信息、错误异常、数字、字符串、时间等,还具备数据库管理、搜索、用户管理等功能,同时拥有日志记录和安全防护模块。 ## 项目的主要特性和功能 1. 系统信息处理能获取系统名称、版本、描述等信息,还可管理令牌。 2. 错误处理具备生成错误消息、错误退出等功能。 3. 数据处理涵盖数字、字符串、时间的处理,如数字转汉字、字符串编码等。 4. 标签管理定义了多种与历史相关的标签信息,包括朝代、事件、人物等。 5. 数据库操作提供数据库管理、SQL查询语句生成、搜索、用户管理等功能。 6. 用户界面生成可生成和更新与时间、标签相关的用户界面元素。 7. 日志记录包含日志保存、格式化、核心记录等功能。 8. 安全防护拥有Web应用防火墙模块,增强网站安全性。 ## 安装使用步骤

Global site tag (gtag.js) - Google Analytics