当业务流程被设计好之后,会有许多相关的文件散落在工程中,这些文件包括:
- 定义流程的 JPDL 文件。
- 根据图形化流程定义同步生成的流程图片文件(PNG 格式)。
- 业务流程中用于人机交互的表单页面文件。
- 事件监听器等用户自定义代码的Java类文件。
- 其他流程资源文件,例如小图标、css样式表、脚本文件、属性文件等。
jbpm4 支持将流程定义及其相关资源打包一个 JAR(Java归档)格式的文件,然后再部署到服务器上(其实就是JBPM 数据库中),这样流程定义就可以被执行了。这个归档文件叫做 “业务流程归档文件”。
1 使用 Ant 部署流程
jbpm4 提供了一个基于 Ant 任务的 API 来部署业务流程归档文件——org.jbpm.pvm.internal.ant.JbpmDeployTask。
JbpmDeployTask 不仅可以部署单个业务流程归档文件,也可以部署一组业务流程归档文件到服务器。通过读取 jbpm.cfg.xml 中的 jdbc 数据连接信息将业务流程归档文件部署到数据库中。因此,在使用
JbpmDeployTask 部署流程定义之前,先确保部署的数据库正在运行。
创建和部署业务流程归档的例子位于 jbpm4 发布包中的 examples 目录下的 build.xml 中,任务名称是 create.and.deploy.examples。它是通过如下步骤来实现流程部署的:
- 声明一个 path 任务来指定包含 JbpmDeployTask 的 jbpm.jar 及其所有的依赖库:
注意:使用数据库的 JDBC 驱动 jar 包必须被包含在这个 path 中(${jbpm.home}/lib)。有的数据库(比如 MySQL)的驱动已经默认包含,但有的(比如 Oracle)还没有。
- 创建一个业务流程归档文件。
这里创建了一个名为 examples.bar 的业务流程归档文件,里面引用了刚才创建的 path 任务:
...
工作流引擎会扫描业务流程归档中所有以 .jpdl.xml 结尾的文件,所有这些文件的内容都会被当做 JPDL 流程定义来解析,然后被用来发起流程实例,业务流程归档中所有其他资源也会在部署过程中持久化到数据库中。
所有这些资源被统一编号保存在数据库表 jbpm4_lob 中,因此可以很方便地通过 jbpm4 提供的 RepositoryService.getResourceAsStream API 来访问这些资源。
- 部署。
需要先在 Ant 中将 JbpmDeployTask 声明为一个 jbpm-deploy 的自定义任务:
然后调用这个自定义的 Ant 任务:
通过 JbpmDeployTask 预留的 file 参数,指定需要部署的流程归档文件。
JbpmDeployTask 类为我们预留了 3 个接口参数:
private String jbpmCfg;
private File file;
private List fileSets = new ArrayList();
jbpm-deploy 任务支持这些属性:
属性 | 类型 | 默认值 | 是否必填 | 描述 |
---|---|---|---|---|
file | 文件 | 无 | 可选 | 指定需要被部署的业务流程定义文件。以 .xml 结尾的文件会被作为流程定义文件直接部署;以 "*ar" 结尾的文件,比如 .bar或 .jar文件,则会作为业务流程归档文件部署。 |
cfg | 文件 | jbpm.cfg.xml | 可选 | 指定 jbpm 配置文件,默认寻找 classpath 根目录下的 jbpm.cfg.xml。如果需要自定义,这个路径应位于 jbpm-deploy 任务定义的 classpath 范围内。 |
jbpm-deploy 任务支持这个元素:
元素 | 关联关系 | 描述 |
---|---|---|
fileset | 0..* | 指定需要被部署的业务流程定义文件集合。以 .xml 结尾的文件会被作为流程定义文件直接部署;以 "*ar" 结尾的文件,比如 .bar或 .jar文件,则会作为业务流程归档文件部署。 |
首先配置好 JBPM 运行环境,即在 classpath 根目录下的jbpm.hibernate.cfg.xml 中设置好数据库连接,并确保数据库服务正常。
改造之前的 build.xml 文件,即可通过 Ant 脚本部署流程。
这里假设要部署一个 deniro.jar 的流程文件,它的 Ant 脚本如下:
2 使用 Java 类部署流程
从 jBPM4.2 开始, jBPM4 使用了流程专用类加载器来加载被部署到数据库中的流程 Java 类,所以效率更高。
我们也可以通过以下两种方法来部署流程:
- 把流程的 Java 类部署到应用服务器类库中,例如放在 Tomcat 服务器的 lib 目录中包。这种方式加载类的优先级最高。
- 把流程 Java 类部署到 Web 应用或企业应用相应目录中,例如WEB-INF、classes 目录或 WEB-INF/lib 目录。Tomcat 在运行时会找到流程所需的 Java 类并调用。这种方式加载类的优先级为次高。
不过这种部署方式在实践中很少使用。
3 使用工作流引擎的服务来部署流程
编写 Java 代码直接调用 JBPM 工作流引擎提供的部署服务 API 来完成流程定义部署。我们使用基于 JUnit 的单元测试架构来演示部署过程:
package net.deniro.jbpm.test;
import org.jbpm.test.JbpmTestCase;
public class Test extends JbpmTestCase{
/**
* 流程定义的部署 ID
*/
String deploymentId;
/**
* 初始化方法中执行流程部署工作
*/
@Override
protected void setUp() throws Exception{
super.setUp();
//从 classpath 中部署流程定义
deploymentId=repositoryService.createDeployment().addResourceFromClasspath("net/deniro/jbpm/test/process.jpdl.xml").deploy();
//可以多次调用 addResourceFromClasspath 方法,把多个资源都部署到数据库中
}
/**
*
*/
@Override
protected void tearDown() throws Exception{
//物理清除 deploymentId 对应的流程定义及其所有相关资源
repositoryService.deleteDeploymentCascade(deploymentId);
super.tearDown();
}
public void test(){
//单元测试代码
}
}
以上单元测试中的流程引擎服务的初始化工作由 JbpmTestCase.setUp 方法来完成的,它为此定义了以下 6 个流程引擎服务:
//资源库服务
protected RepositoryService repositoryService;
//执行服务
protected ExecutionService executionService;
//管理服务
protected ManagementService managementService;
//任务服务
protected TaskService taskService;
//历史服务
protected HistoryService historyService;
//身份认证服务
protected IdentityService identityService;
JbpmTestCase在 setUp 方法中初始化这些服务:
super.setUp();
processEngine = buildProcessEngine();
repositoryService = processEngine.getRepositoryService();
executionService = processEngine.getExecutionService();
historyService = processEngine.getHistoryService();
managementService = processEngine.getManagementService();
taskService = processEngine.getTaskService();
identityService = processEngine.getIdentityService();
在某些客户端实现中,开发者可以参考上述代码获得这些流程引擎提供的服务。