1. jBPM的简单介绍
jBPM是JBOSS下的一个开源java工作流项目,该项目提供eclipse插件,基于Hibernate实现数据持久化存储。
参考
2. jBPM和myeclipse的冲突
当eclipse安装了myeclipse和jBPM时候,可能有冲突,具体表现在jBPM的流程设计器不能在eclipse中使用。
3. Hibernate连接mysql数据库的一般参数
下面的配置参数,根据需要可以修改:
jbpmtest是mysql中的schema的名字;
GBK是字符集,可以根据需要修改;
username=root,mysql数据库的用户名是root;
password=mysql,mysql数据库的用户密码是mysql;
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://localhost/jbpmtest?useUnicode=true&characterEncoding=GBK
hibernate.connection.username=root
hibernate.connection.password=mysql
hibernate.show_sql=true
hibernate.c3p0.min_size=1
hibernate.c3p0.max_size=3
4. Hibernate连接Oracle数据库的一般参数
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url= jdbc:oracle:thin:@localhost:1521:orcl hibernate.connection.username=jbpm
hibernate.connection.password=jbpm
5. 为jBPM创建数据库表等内容
5.1. 为mysql创建数据库以及数据内容
JbpmSessionFactory.buildJbpmSessionFactory().getJbpmSchema().dropSchema();
JbpmSessionFactory.buildJbpmSessionFactory().getJbpmSchema().createSchema();
这2个语针对mysq有效.
5.2. 为oralce创建数据库以及数据内容
JbpmSessionFactory.buildJbpmSessionFactory().getJbpmSchema().dropSchema();
JbpmSessionFactory.buildJbpmSessionFactory().getJbpmSchema().createSchema();
上面的语句对oralce无效。
模型目录jBPM\jbpm_database\jBPM_oralce10g.pdm 是jBPM的Oralce模型,包含对应的Sequence的信息.
需要在数据库中创建 Sequence name=hibernate_sequence
5.3. 流程信息保存到数据库
JbpmSessionFactory factory = JbpmSessionFactory.buildJbpmSessionFactory();
JbpmSession session = factory.openJbpmSession();
GraphSession graphSession = session.getGraphSession();
session.beginTransaction();
/// new ProcessDefinition 实例
ProcessDefinition myProcessDefinition = null;
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("myvar","xxx");
///
graphSession.saveProcessDefinition(myProcessDefinition);
session.commitTransaction();
session.close();
jBPM和Hibernate,MySQL的使用中会遇到字符集的问题.
需要注意几个地方。
5.4. 在Mysql安装过程指定字符集
在Mysql安装过程中指定相应的默认字符集是GBK
5.5. Hibernate.properties文件中的字符集设置
hibernate.connection.url=jdbc:mysql://localhost/jbpmtest?useUnicode=true&characterEncoding=GBK
5.6. hibernate.cfg.xml 文件中的字符集设置
<property name="hibernate.connection.url">jdbc:mysql://192.168.1.2/jbpmtest
5.7. MySQL的配置文件的修改:
my.ini中 default-character-set=GBK
注意有2处需要修改
6. 为流程定义变量
分成3种流程变量
全局变量(全局流程变量)
全局临时变量(全局流程临时变量)
局部变量(流程某个接点内有效的变量)
@see org.jbpm.context.exe.ContextInstance
目前还没有使用过局部变量(流程某个接点内有效的变量)
流程变量的定义
6.1. 流程变量的类型
· java.lang.String
· java.lang.Boolean
· java.lang.Character
· java.lang.Float
· java.lang.Double
· java.lang.Long
· java.lang.Byte
· java.lang.Short
· java.lang.Integer
· java.util.Date
· byte[]
· java.io.Serializable
· classes that are persistable with hibernate
所有基本类型的包裹类型,以及实现了Serializable的类型都可以作为流程参数变量使用,注意参数类不能是一个类的内部类或者属性类(除非包含参数类的类实现了Serializable接口)
参考 org.jbpm.context.exe.VariableInstance
6.2. 流程变量的使用
l 变量的定义和获取
void ContextInstance.setVariable(String variableName, Object value);
void ContextInstance.setVariable(String variableName, Object value, Token token);
Object ContextInstance.getVariable(String variableName);
Object ContextInstance.getVariable(String variableName, Token token);
l Variables can be deleted with
ContextInstance.deleteVariable(String variableName);
ContextInstance.deleteVariable(String variableName, Token token);
6.3. Variable lifetime
一个变量在被定义后,在变量从ContextInstance删除前,都可以被访问。当变量被删除后,去获取该变量将返回为空。
6.4. 自定义类的实例作为流程变量
如果一个类的实例要作为流程变量使用,该类需要实现java.io.Serializable接口,并且定义序列化版本.
//一个可以作为流程变量使用的类
class Wdz implements Serializable{
//为类指定序列化版本号
private static final long serialVersionUID = 1L;
private String name="wdz";
private int age=10;
public String toString(){
return "name="+name+",age="+age;
}
}
上面的例子中,如果把类Wdz作为类WdzParent内部类使用,然后当成流程变量使用,那类WdzParent必须 也实现Serializable接口,否则会有问题.
6.5. Transient variables
流程的历史变量是不能持久化的,作用范围是对整个流程全局有效的。
在ContextInstance类内部,采用的是一个Map来存储TransientVariable的信息
参考代码
org.jbpm.context.exe.ContextInstance 的源代码。
主要的相关方法
public void deleteTransientVariable(java.lang.String name)
public void setTransientVariable(java.lang.String name,
java.lang.Object value)
public java.lang.Object getTransientVariable(java.lang.String name)
6.6. Variables overloading
当一个变量和流实例关联(变量名字=”wdz”,value=”test”),如果在设置一个变量
(变量名字=”wdz”,value= new Integer(10)) ,那最后变量(变量名字=”wdz)的值是Integer(10)。
这称之为overload.
6.7. Variables overriding
如果父流程有变量A(值=”value1”),子流程又定义了变量A值=”value2”,那在子流程范围内,获取变量A的值,那结果是值=”value2”。这是遵循一般语言的局部变量在它的局部范围内override上级变量。
6.8. 流程变量的持久化
它依赖于流程实例的持久化,非TransientVariable随流程实例的持久化一起被保存。
保存在数据表jbpm_variableinstance
参考 org.jbpm.context.exe.VariableInstance
6.9. Customizing variable persistence (可以进一步了解)
User java object <---> converter <---> variable instance
也就是自定义类的持久化需要定义自己的converter和变量实例类
converter和变量实例类需要继承org.jbpm.context.exe.VariableInstance
converter需要实现org.jbpm.context.exe.Converter接口
一
工作流虽然还在不成熟的发展阶段,甚至还没有一个公认的规范标准。但其应用却已经在快速展开,这说明市场对工作流框架的需求是急迫而巨大的。
我们公司的后台短信管理系统涉及短信编发、领导层层审核等操作,这是一个比较典型的工作流系统。过去我们用的工作流引擎是 shark ,然后在使用后发现其过于庞大,后台数据库操作频繁而未进行优化,直接导致的后果就是前台操作缓慢。于是经研究决定,将工作流引擎由 shark 换成 jBPM 。
jBPM 之前是一个开源软件,后加入 JBoss 组织。正好我们公司也是用 JBoss 的。不过 jBPM 并没有绑定在 JBOSS 上, Tomcat 等也可以使用它。
jBPM 的正处在不断发展中,做为开源软件的特点,其设计变化往往很大。所以一些过去的资料可能已经不适用了。于是作者根据自己的使用经验,重新整理出这份文档,以备学习参考。
注:本文使用的 jBPM 版本为 3.1.1
环境准备
所有 JAVA 开发第一个需要安装的,没什么好说的。记得把系统变量 JAVA_HOME 设上。
Ant 是使用 jBPM 必须的一个工具。 jBPM 中的很多操作都要用到 Ant 。
安装方法:
( 1 )先下载: ,选一个如: apache-ant-1.6.5-bin.zip 。
( 2 )解压到 D:\ant (当然其他目录也可以)。
( 3 )设置如下系统变量: ANT_HOME=d:\ant 。
( 4 )把 %ANT_HOME%\bin 加入到系统变量 PATH 中。
Eclipse 不是开发 jBPM 必须的工具,但它是对 jBPM 开发很有帮助的工具,特别是 jBPM 提供了一个 Eclipse 插件用来辅助开发 jBPM 。关于 Eclipse 的安装不赘述了,本文用的版本是: Eclipse3.2
安装 jBPM
jBPM 的下载地址:
l JBoss jBPM 是 jBPM 的软件包
l JBoss jBPM Starters Kit 是一个综合包,它包括了 jBPM 软件包、开发插件、一个配置好了的基于 JBoss 的 jBPM 示例、一些数据库配置文件示例。
l JBoss jBPM Process Designer Plugin 是辅助开发 jBPM 的 Eclipse 插件。
l JBoss jBPM BPEL Extension jBPM 关于 BPEL 的扩展包
本指南选择下载: JBoss jBPM Starters Kit 。下载后解压到 D:\jbpm-starters-kit-3.1 ,目录下含有五个子目录:
l jbpm jBPM 的软件包
l jbpm-bpel 只含有一个网页
l jbpm-db 各种数据库 hibernate 配置文件示例,有些还包含了相应的 jdbc 驱动程序。
l jbpm-designer 辅助开发 jBPM 的 Eclipse 插件,具体在 jbpm-gpd-feature 子目录中
l jbpm-server 一个已经配置好了的基于 JBoss 的 jBPM 示例 .
感觉下工作流
前面我们说了,在 JBoss jBPM Starters Kit 的 jbpm-server 目录是一个已经配置好的了 jBPM 示例,那么让我们来感觉一下 jBPM 做出的东西吧。
双击 jbpm-server 目录下的 start.bat 文件,启动 JBoss 服务。这时会打开一个 DOS 窗口,启动完成后,日志会不断输出,其中最后一句是“ 13:55:39,937 DEBUG [StaticNotifier] going to wait for (CMD_EXECUTOR, java.lang.Object@1df59bd) ”,这表示 jBPM 在开始工作了,它不断进行轮询。
打开网页: 得到如下画面 ![]()
这是一个已经用 jBPM 开发好的用户定单流程,具有下单、审核、估价等流程。它所用的数据库是一个内置的数据库。
以 cookie monster 用户登录,选择“ create new web sale order ”可以创建一个定单。如下图所示,在图左边是填写的定单情况,右边一整个定货流程的示意图,红色框表示流程进行到哪一步了。填写好定单好,选择“ Save and Close Task ”,完成定单提交。 ![]()
选择右上角的“ Login as another user ”以另外一个用户名 ernie 登录。这时可以看到 ernie 用户的任务列表中多了一项。 ![]()
点进去后,显示如下画面。这个示例对中文的支持不好,全都显示成了 unicode 码了。不管这什么多,反正知道是这么回事就行了。在 comment 项填写意见,选 OK 按钮,进入到下一步。如果选择 more info needed 按钮,则打回给 cookie monster 用户修改定单。 ![]()
下面的流程,这里就不再赘述了。在这个很标准的工作流示例中,我们基本可以看到 jBPM 的应用范围还是比较广的。而且从这个示例,我们是看不出有 jBPM 的,也就是说 jBPM 在后台起着作用。
从这个例子,还看不出 jBPM 的优势。不过,如果在一个流程不确定,经常需要变动的项目中, jBPM 的好处将会显然出来。应用 jBPM 后,改变流程只需改变流程描述文件,这将在后面的内容提到。
这是一个已做好的示例,接下来我们将仿造这个实例来开发一个请假流程。
4 数据库初始化
jBPM 需要数据库支持, jBPM 会把自己的一个初始化数据存储到数据库,同时工作流的数据也是存储到数据库中的。 jBPM 使用 Hibernate 来做为自己的存储层,因此只要是 Hibernate 支持的数据库, jBPM 也就支持。
本文先以 MySQL 为例,然后再以 Oracle 为例,来谈谈 jBPM 的数据库初始化操作。
注:在上面的 JBoss 自带的示例中,并没有设置数据库,那是因为 jBPM 默认使用的是内存数据库 hsqldb 。
1 、首先安装 MySQL 。
MySQL 的安装比较简单,网上也有很多文章,本文不再赘述。本指南所用 MySQL 版本为 MySQL 4.1 ( for windows )。再找一个 MySQL 客户端,目的是方便查看数据库中的数据,本文推荐使用 MySQL 网站上免费提供的“ MySQL Query Brower ”,当然你用其他的客户端也行,比如 MySQL-Front 。
2 、建库
MySQL 中创建一个库,库名: jbpm
3 、生成建表的 SQL 语句并建表
将 jbpm-starters-kit-3.1.1 下的子目录 jbpm 改名为 jbpm.3 ,否则在执行下面的 ant 命令时会报如 jbpm.3 目录不存在的错误:
D:\jbpm-starters-kit-3.1.1\jbpm-db\build.xml:361: The following error occurred while executing this line:
D:\jbpm-starters-kit-3.1.1\jbpm-db\build.xml:68: Basedir D:\jbpm-starters-kit-3.1.1\jbpm.3 does not exist
在 DOS 窗下,进入 D:\jbpm-starters-kit-3.1.1\jbpm-db 目录,执行如下命令:
ant mysql.scripts
执行成功后,在 D:\jbpm-starters-kit-3.1.1\jbpm-db\build\mysql\scripts 目录里生成了四个 sql 文件,它们做什么用的一看名字就知道了。在 MySQL 客户端中执行“ mysql.create.sql ”脚本,这样将在 jbpm 库中创建一个个的数据表。
先安装好 Oracle 服务器。我们公司有现存的 Oracle 服务器,也提供给了我一个属于我自己的用户名,一登录就可以任意在我的库之下创建表了。所以这一步就省了,没有的自个先装好吧。
访问 Oracle 推荐用“ PLSQL Developer ”。不过要连接 Oracle 还要在本机上装上 Oracle 自己的客户端程序,里面提供了 JDBC 包和一些配置。要连接服务器还得配置一下,我一般都是不用 GUI 而直接改 tnsnames.ora 文件,在我的电脑里此文件的目录地址是: D:\oracle\ora92\network\ADMIN\tnsnames.ora ,内容如下 ( 两面有两个配置了 ) :
# TNSNAMES.ORA Network Configuration File: E:\oracle\ora92\network\admin\tnsnames.ora
# Generated by Oracle configuration tools.
WXXRDB_192.168.3.2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.3.2)(PORT = 1521))
)
(CONNECT_DATA =
(SID = wxxrDB)
(SERVER = DEDICATED)
)
)
WXXRDB_192.168.4.2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.4.2)(PORT = 1521))
)
(CONNECT_DATA =
(SID = wxxrDB)
(SERVER = DEDICATED)
)
)
前面都是 Oracle 的一些知识,不会的 Google 一下吧。最后配置好后,用 PLSQL Developer 输入你的用户名和密码联接到 Oracle ,就算 OK 了。
参考上面 MySQL 的步骤,基本一样:
(1) 将 jbpm 改名为 jbpm.3 (或者修改jbpm-db目录下的build.properties文件)
(2) 再执行 ant oracle.scripts
(3) 用 jbpm-db\build\oracle\scripts 目录的 oracle.create.sql 脚本,在 Oracle 中生成 jBPM 的所有表。在“ PLSQL Developer ”中可以新建一个 Command Windows 窗口然后输入命令: @D:\jbpm-starters-kit-3.1.1\jbpm-db\build\oracle\scripts\oracle.create.sql
(如果报错,就将报错的地方注释掉)