- 浏览: 126550 次
- 来自: ...
最近访客 更多访客>>
文章分类
最新评论
-
dwangel:
给messageSource设置属性
<property ...
Spring i18n的better practice(相对于appfuse) -
dwangel:
spring 的message tag有一个属性text,可以 ...
Spring i18n的better practice(相对于appfuse) -
sn201:
awk高级篇
有问题啊!有问题!有问题!有问题!有问题!
i ...
awk文本处理总结(入门,中级,高级) -
happy_javaboy:
...
Log4j日志管理系统简单使用说明
本文介绍怎样把jBPM组件添加到Web应用程序中。所需要用到的资源,可以在jbpm-starters-kit-3.1.2中找到。
一、首先安装jBPM数据库。jBPM是一个停止状态的组件,需要数据库表持久化保存:1)业务程序定义和业务程序实例及相关的工作流数据。保障工作流引擎的执行。2)异步系统使用数据库表来模拟消息系统的功能。需要把消息到数据库表中,由消息系统的命令执行器异步查询和执行。不像专业的消息系统那样是远程的。它仅仅使用数据库模拟消息系统。
1,打开MySQL的命令执行工具Query Browser。
2,当前选定应用程序的数据库,如wcms。
3,导入脚本文件:mysql.drop.create.sql
4,执行该脚本。会在当前数据库中增加jBPM的数据库表。
二、导入jBPM所需的.jar文件
1,jbpmlib目录中包含了jBPM所需的全部jar包。包括MySQL的jdbc包。
2,把它整个复制到应用程序的lib目录下。
3,应用程序的构建器路径的“库”中,把这些jar都加进来。
这些classpath下的jar包,都会被该Web应用程序的类载入器载入。
三、创建config.files和processes目录,并加入classpath的源代码路径
(一)config.files目录的功能
这个目录存放jBPM的各类配置文件。放在这里(就是classpath顶层)的配置文件会取代jBPM的jar包中各处的配置文件。
这里,由于需要使用mysql,而不是内置的hsql内存数据库。所以我们提供了一个修改过的配置文件:hibernate.cfg.xml。这里提供了Hibernate3的配置。
hibernate.cfg.xml配置文件的部分内容
<hibernate-configuration>
<session-factory>
<session-factory>
<!-- jdbc connection properties
原来的HSQL配置被注释掉,使用MySQL数据库的配置
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:mem:.;sql.enforce_strict_size=true</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/wcms</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:mem:.;sql.enforce_strict_size=true</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/wcms</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
(二)processes目录的功能
这个目录存放process流程定义。如:manageNews\内有3个文件。
在jBPM应用程序导入.par或.xml文件时,使用相对路径(如:withubCMS/processdefinition.xml)来定位业务程序定义资源文件。
怎样把它们放到classpath下,需要根据不同的环境进行不同的处理。
一、一般Java程序
1,创建config.files和processes目录。
2,配置构建器路径,将这2个目录设为到classpath的源代码路径。
这样,运行时,会把它们中的内容复制到classpath目录下。
二、Eclipse下的Web程序
我们使用Eclipse自带的功能发布Web程序。
1,创建config.files和processes目录。
2,配置构建器路径,将这2个目录设为到classpath的源代码路径。
3,配置classpath,也就是“缺省输出文件夹”,为:
内容管理(应用程序根路径名)/webapps/WEB-INF/classes
4,这样,在Eclipse编译时(默认是保存即编译),把这2个文件夹中的内容复制到classpath下。
5,然后,使用Eclipse自带的功能,发布该Web应用程序。
Eclipse会把/webapps/文件夹下的所有内容复制到Web服务器下,并且把webapps改名为该Web应用程序的Eclipse项目名字。
这样,我们的配置,对于classpath来说也是正确的!Web应用程序可以顺利地运行。
三、Ant发布的Web程序
可以和上面一样。把这些classpath的源文件,编译,然后把内部的内容复制到classpath下。
Web项目运行时的classpath是classes和lib。当然也需要把jar包都复制到lib下。
最后,在内容管理\webapps\WEB-INF\jbpm\下放置那2个目录。并把它们设为classpath的源路径。
目标classpath路径是内容管理\webapps\WEB-INF\classes。
四、测试jBPM和数据库
建立test源文件夹。提供一个junit测试类:org.jbpm.test.db.HelloWorldDbTest。
这个类使用字符串定义了一个简单的业务程序,然后在数据库上完整的执行它。
执行该单元测试。在应用程序的数据库中的2个表:
SELECT * FROM jbpm_processdefinition j;
SELECT * FROM jbpm_processinstance j;
应该有数据。
至此,jBPM组件就成功地加入到Web应用程序中了!
附录:HelloWorldDbTest.java源代码
package org.jbpm.test.db;
import java.util.List;
import junit.framework.TestCase;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.GraphSession;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.JbpmContext;
import org.jbpm.db.GraphSession;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class HelloWorldDbTest extends TestCase {
static JbpmConfiguration jbpmConfiguration = null;
static JbpmConfiguration jbpmConfiguration = null;
static {
// An example configuration file such as this can be found in
// 'src/config.files'. Typically the configuration information is in the
// resource file 'jbpm.cfg.xml', but here we pass in the configuration
// information as an XML string.
// First we create a JbpmConfiguration statically. One JbpmConfiguration
// can be used for all threads in the system, that is why we can safely
// make it static.
/**
*单例对象。
*JbpmConfiguration能够被系统中所有线程所使用。
*jbpm.cfg.xml这个命名方式和Hibernate配置文件的命名方式一致。
*
*/
// An example configuration file such as this can be found in
// 'src/config.files'. Typically the configuration information is in the
// resource file 'jbpm.cfg.xml', but here we pass in the configuration
// information as an XML string.
// First we create a JbpmConfiguration statically. One JbpmConfiguration
// can be used for all threads in the system, that is why we can safely
// make it static.
/**
*单例对象。
*JbpmConfiguration能够被系统中所有线程所使用。
*jbpm.cfg.xml这个命名方式和Hibernate配置文件的命名方式一致。
*
*/
jbpmConfiguration = JbpmConfiguration.parseXmlString(
"<jbpm-configuration>" +
// A jbpm-context mechanism separates the jbpm core
// engine from the services that jbpm uses from
// the environment.
/*jbpm-context机制在环境中把jbpm核心引擎和jbpm使用的服务分开。
* 持久化服务是jbpm核心引擎使用的一个服务。
*
* */
" <jbpm-context>" +
" <service name='persistence' " +
" factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />" +
" </jbpm-context>" +
// Also all the resource files that are used by jbpm are
// referenced from the jbpm.cfg.xml
/*
*string,配置了所有jbpm使用的资源文件的路径。
* */
" <string name='resource.hibernate.cfg.xml' " +
" value='hibernate.cfg.xml' />" +
" <string name='resource.business.calendar' " +
" value='org/jbpm/calendar/jbpm.business.calendar.properties' />" +
" <string name='resource.default.modules' " +
" value='org/jbpm/graph/def/jbpm.default.modules.properties' />" +
" <string name='resource.converter' " +
" value='org/jbpm/db/hibernate/jbpm.converter.properties' />" +
" <string name='resource.action.types' " +
" value='org/jbpm/graph/action/action.types.xml' />" +
" <string name='resource.node.types' " +
" value='org/jbpm/graph/node/node.types.xml' />" +
" <string name='resource.varmapping' " +
" value='org/jbpm/context/exe/jbpm.varmapping.xml' />" +
"</jbpm-configuration>"
);
}
public void setUp() {
//创建数据库表
//jbpmConfiguration.createSchema();
}
public void tearDown() {
//删除数据库表
//jbpmConfiguration.dropSchema();
}
"<jbpm-configuration>" +
// A jbpm-context mechanism separates the jbpm core
// engine from the services that jbpm uses from
// the environment.
/*jbpm-context机制在环境中把jbpm核心引擎和jbpm使用的服务分开。
* 持久化服务是jbpm核心引擎使用的一个服务。
*
* */
" <jbpm-context>" +
" <service name='persistence' " +
" factory='org.jbpm.persistence.db.DbPersistenceServiceFactory' />" +
" </jbpm-context>" +
// Also all the resource files that are used by jbpm are
// referenced from the jbpm.cfg.xml
/*
*string,配置了所有jbpm使用的资源文件的路径。
* */
" <string name='resource.hibernate.cfg.xml' " +
" value='hibernate.cfg.xml' />" +
" <string name='resource.business.calendar' " +
" value='org/jbpm/calendar/jbpm.business.calendar.properties' />" +
" <string name='resource.default.modules' " +
" value='org/jbpm/graph/def/jbpm.default.modules.properties' />" +
" <string name='resource.converter' " +
" value='org/jbpm/db/hibernate/jbpm.converter.properties' />" +
" <string name='resource.action.types' " +
" value='org/jbpm/graph/action/action.types.xml' />" +
" <string name='resource.node.types' " +
" value='org/jbpm/graph/node/node.types.xml' />" +
" <string name='resource.varmapping' " +
" value='org/jbpm/context/exe/jbpm.varmapping.xml' />" +
"</jbpm-configuration>"
);
}
public void setUp() {
//创建数据库表
//jbpmConfiguration.createSchema();
}
public void tearDown() {
//删除数据库表
//jbpmConfiguration.dropSchema();
}
public void testSimplePersistence() {
// Between the 3 method calls below, all data is passed via the
// database. Here, in this unit test, these 3 methods are executed
// right after each other because we want to test a complete process
// scenario情节. But in reality, these methods represent different
// requests to a server.
// Since we start with a clean, empty in-memory database, we have to
// deploy the process first. In reality, this is done once by the
// process developer.
/**
* 这个方法把业务处理定义通过Hibernate保存到数据库中。
*/
deployProcessDefinition();
// Between the 3 method calls below, all data is passed via the
// database. Here, in this unit test, these 3 methods are executed
// right after each other because we want to test a complete process
// scenario情节. But in reality, these methods represent different
// requests to a server.
// Since we start with a clean, empty in-memory database, we have to
// deploy the process first. In reality, this is done once by the
// process developer.
/**
* 这个方法把业务处理定义通过Hibernate保存到数据库中。
*/
deployProcessDefinition();
// Suppose we want to start a process instance (=process execution)
// when a user submits a form in a web application...
/*假设当一个用户提交一个表单时,我们要开始一个业务处理的实例/执行。
* 这可以在Action中执行处理。
*/
processInstanceIsCreatedWhenUserSubmitsWebappForm();
// when a user submits a form in a web application...
/*假设当一个用户提交一个表单时,我们要开始一个业务处理的实例/执行。
* 这可以在Action中执行处理。
*/
processInstanceIsCreatedWhenUserSubmitsWebappForm();
// Then, later, upon the arrival of an asynchronous message the
// execution must continue.
/*
* 然后,直到异步消息来到,才继续执行业务处理实例的余下的工作流程。
* */
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
}
// execution must continue.
/*
* 然后,直到异步消息来到,才继续执行业务处理实例的余下的工作流程。
* */
theProcessInstanceContinuesWhenAnAsyncMessageIsReceived();
}
public void deployProcessDefinition() {
// This test shows a process definition and one execution
// of the process definition. The process definition has
// 3 nodes: an unnamed start-state, a state 's' and an
// end-state named 'end'.
/*
* 这个方法把业务处理定义通过Hibernate保存到数据库中。
*
* */
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
"<process-definition name='hello world'>" +
" <start-state name='start'>" +
" <transition to='s' />" +
" </start-state>" +
" <state name='s'>" +
" <transition to='end' />" +
" </state>" +
" <end-state name='end' />" +
"</process-definition>"
);
// This test shows a process definition and one execution
// of the process definition. The process definition has
// 3 nodes: an unnamed start-state, a state 's' and an
// end-state named 'end'.
/*
* 这个方法把业务处理定义通过Hibernate保存到数据库中。
*
* */
ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
"<process-definition name='hello world'>" +
" <start-state name='start'>" +
" <transition to='s' />" +
" </start-state>" +
" <state name='s'>" +
" <transition to='end' />" +
" </state>" +
" <end-state name='end' />" +
"</process-definition>"
);
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// Deploy the process definition in the database
jbpmContext.deployProcessDefinition(processDefinition);
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// Deploy the process definition in the database
jbpmContext.deployProcessDefinition(processDefinition);
} finally {
// Tear down the pojo persistence context.
// This includes flush the SQL for inserting the process definition
// to the database.
/*
* 关闭jbpm上下文。删除pojo持久化上下文。
* 这包括刷新SQL来真正的把业务处理定义插入到数据库中。
* */
jbpmContext.close();
}
}
// Tear down the pojo persistence context.
// This includes flush the SQL for inserting the process definition
// to the database.
/*
* 关闭jbpm上下文。删除pojo持久化上下文。
* 这包括刷新SQL来真正的把业务处理定义插入到数据库中。
* */
jbpmContext.close();
}
}
public void processInstanceIsCreatedWhenUserSubmitsWebappForm() {
// The code in this method could be inside a struts-action
// or a JSF managed bean.
// The code in this method could be inside a struts-action
// or a JSF managed bean.
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
/*
* 图表会话,是图表定义/业务处理定义 相关的数据库层面的会话。应该也是一个Hibernate会话。
* 可以从JBpm上下文这个数据库----业务处理定义、实例等 得到 业务处理定义会话。
*
* */
GraphSession graphSession = jbpmContext.getGraphSession();
//从数据库中根据业务处理定义的名字得到一个业务处理定义。
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// With the processDefinition that we retrieved from the database, we
// can create an execution of the process definition just like in the
// hello world example (which was without persistence).
/*
* 创建业务处理定义的一个实例。
*
* */
ProcessInstance processInstance =
new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
assertEquals("start", token.getNode().getName());
// Let's start the process execution
token.signal();
// Now the process is in the state 's'.
assertEquals("s", token.getNode().getName());
// Now the processInstance is saved in the database. So the
// current state of the execution of the process is stored in the
// database.
/*
* 执行一步工作流程后,使用jbpmContext保存这个业务处理实例进数据库。
* 所以现在就把业务处理实例的执行状态也保存进了数据库。
* 因为,业务处理定义的实例 这个类也是一个Model类,用于管理一个业务处理定义的执行的所有信息,
* 是一个多例模式的Model。
*
* */
jbpmContext.save(processInstance);
// The method below will get the process instance back out
// of the database and resume execution by providing another
// external signal.
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
/*
* 图表会话,是图表定义/业务处理定义 相关的数据库层面的会话。应该也是一个Hibernate会话。
* 可以从JBpm上下文这个数据库----业务处理定义、实例等 得到 业务处理定义会话。
*
* */
GraphSession graphSession = jbpmContext.getGraphSession();
//从数据库中根据业务处理定义的名字得到一个业务处理定义。
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// With the processDefinition that we retrieved from the database, we
// can create an execution of the process definition just like in the
// hello world example (which was without persistence).
/*
* 创建业务处理定义的一个实例。
*
* */
ProcessInstance processInstance =
new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
assertEquals("start", token.getNode().getName());
// Let's start the process execution
token.signal();
// Now the process is in the state 's'.
assertEquals("s", token.getNode().getName());
// Now the processInstance is saved in the database. So the
// current state of the execution of the process is stored in the
// database.
/*
* 执行一步工作流程后,使用jbpmContext保存这个业务处理实例进数据库。
* 所以现在就把业务处理实例的执行状态也保存进了数据库。
* 因为,业务处理定义的实例 这个类也是一个Model类,用于管理一个业务处理定义的执行的所有信息,
* 是一个多例模式的Model。
*
* */
jbpmContext.save(processInstance);
// The method below will get the process instance back out
// of the database and resume execution by providing another
// external signal.
} finally {
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
public void theProcessInstanceContinuesWhenAnAsyncMessageIsReceived() {
// The code in this method could be the content of a message driven bean.
//这个方法可能在消息驱动Bean这个远程业务代理类中。
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// The code in this method could be the content of a message driven bean.
//这个方法可能在消息驱动Bean这个远程业务代理类中。
// Lookup the pojo persistence context-builder that is configured above
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
GraphSession graphSession = jbpmContext.getGraphSession();
// First, we need to get the process instance back out of the database.
// There are several options to know what process instance we are dealing
// with here. The easiest in this simple test case is just to look for
// the full list of process instances. That should give us only one
// result. So let's look up the process definition.
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// First, we need to get the process instance back out of the database.
// There are several options to know what process instance we are dealing
// with here. The easiest in this simple test case is just to look for
// the full list of process instances. That should give us only one
// result. So let's look up the process definition.
ProcessDefinition processDefinition =
graphSession.findLatestProcessDefinition("hello world");
// Now, we search for all process instances of this process definition.
/*
* 根据业务处理定义的id得到数据库中所有的业务处理实例。这表明,数据库中应该存在2张表
* 它们是 一对多 的关系。
*
* */
List processInstances =
graphSession.findProcessInstances(processDefinition.getId());
// Because we know that in the context of this unit test, there is
// only one execution. In real life, the processInstanceId can be
// extracted from the content of the message that arrived or from
// the user making a choice.
ProcessInstance processInstance =
(ProcessInstance) processInstances.get(0);
// Now we can continue the execution. Note that the processInstance
// delegates signals to the main path of execution (=the root token).
processInstance.signal();
/*
* 根据业务处理定义的id得到数据库中所有的业务处理实例。这表明,数据库中应该存在2张表
* 它们是 一对多 的关系。
*
* */
List processInstances =
graphSession.findProcessInstances(processDefinition.getId());
// Because we know that in the context of this unit test, there is
// only one execution. In real life, the processInstanceId can be
// extracted from the content of the message that arrived or from
// the user making a choice.
ProcessInstance processInstance =
(ProcessInstance) processInstances.get(0);
// Now we can continue the execution. Note that the processInstance
// delegates signals to the main path of execution (=the root token).
processInstance.signal();
// After this signal, we know the process execution should have
// arrived in the end-state.
assertTrue(processInstance.hasEnded());
// Now we can update the state of the execution in the database
jbpmContext.save(processInstance);
// arrived in the end-state.
assertTrue(processInstance.hasEnded());
// Now we can update the state of the execution in the database
jbpmContext.save(processInstance);
} finally {
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
}
// Tear down the pojo persistence context.
jbpmContext.close();
}
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1346877
相关推荐
介绍了如何将定义好的流程嵌入到 Java 应用程序中。 ##### 5.8 其他特性 除了基本的流程定义外,jBPM 还提供了许多高级特性,如数据处理、约束条件和动作脚本等。 - **数据**:处理流程中的数据变量。 - **约束**...
jBPM作为一款成熟且灵活的工作流管理工具,为企业级应用程序提供了强大的业务流程自动化能力。通过深入学习其原理和实践操作,开发者能够有效地设计和实施复杂的工作流程,提高业务效率和响应速度。然而,成功应用...
- **灵活的集成选项**:能够与现有的应用程序和服务进行集成。 - **插件式扩展**:通过插件机制可以轻松扩展jBPM的功能。 - **社区支持**:拥有活跃的开发者社区和丰富的文档资源。 #### 四、核心组件 - **流程...
第二篇主要涉及基于jBPM4这个强大的应用程序框架打造属于自己独特业务的“企业流程管理平台”,包括jBPM4扩展研发先决条件、深入jPDL和jBPM Service API、升级jBPM3到jBPM4、流程虚拟机原理、jBPM4的设计思想、随需...
这意味着开发者可以将这些组件直接集成到现有的Java项目中,无需像安装独立应用程序那样进行复杂的安装过程。 - **数据库存储**:为了持久化流程定义和运行时数据,jBPM支持多种数据库,包括但不限于HSQLDB(内存...
WFMC定义的工作流包括五个关键部分:工作流过程活动、转移信息、参与者声明、外部应用程序声明和相关数据,并制定了XPDL标准语法。然而,jBPM使用自定义的jPdl,不完全符合WFMC规范。 **二、jBPM流程处理步骤** 1....
- 提供丰富的API接口,便于与其他应用程序和服务进行集成。 - 支持RESTful API,方便远程访问和操作。 - **监控与审计**: - 提供详细的流程执行日志和审计记录,便于追踪流程的执行情况。 - 支持实时监控流程...
作为一个灵活的平台,jBPM支持多种流程建模语言,包括BPMN2,这使得开发者能够构建复杂的应用程序,并通过图形化工具直观地设计业务流程。 #### 二、概述 jBPM不仅是一个工作流引擎,还是一个全面的业务流程管理...
它具有高度的灵活性和可扩展性,可以集成到任何Java应用程序中。 - **发展历程**:最初是一个独立项目,后来加入了JBoss组织,成为JBoss中间件的一部分。 - **应用场景**:适用于各种业务流程的自动化处理,如审批...
- **部署应用**:将构建好的应用程序部署到服务器上,可以是Tomcat、Jetty或其他任何兼容Servlet 3.0的容器。 #### 五、Activiti的开发流程 1. **设计流程模型**:使用BPMN2.0工具(如Activiti Modeler)设计流程...
Spring框架是整个SSH架构的核心,提供依赖注入和面向切面编程的支持,极大地简化了Java应用程序的开发。版本Spring 1.2的添加,除了常规的类库导入外,还需特别注意Spring的Web Librabries。Spring的配置文件`...
Activiti还提供了一个Web应用程序,可以通过配置activiti-rest.war中的activiti.cfg.xml和activiti-context.xml来管理流程定义的部署和资源。ProcessEngineConfiguration类用于创建流程引擎配置,开发者可以通过调用...