说说在 jBPM 中如何部署流程

当业务流程被设计好之后,会有许多相关的文件散落在工程中,这些文件包括:
* 定义流程的 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。它是通过如下步骤来实现流程部署的:

  1. 声明一个 path 任务来指定包含 JbpmDeployTask 的 jbpm.jar 及其所有的依赖库:
  <target name="jbpm.libs.path">
    <path id="jbpm.libs.incl.dependencies">
      <pathelement location="${jbpm.home}/examples/target/classes" />
      <pathelement location="${jbpm.home}/jbpm.jar" />
      <fileset dir="${jbpm.home}/lib" includes="*.jar" />
    </path>
  </target>

注意:使用数据库的 JDBC 驱动 jar 包必须被包含在这个 path 中(${jbpm.home}/lib)。有的数据库(比如 MySQL)的驱动已经默认包含,但有的(比如 Oracle)还没有。

  1. 创建一个业务流程归档文件。

这里创建了一个名为 examples.bar 的业务流程归档文件,里面引用了刚才创建的 path 任务:

<target name="create.and.deploy.examples" depends="jbpm.libs.path, examples.jar">
    <mkdir dir="${jbpm.home}/examples/target" />
    <copy file="${jbpm.home}/install/src/cfg/hibernate/jdbc/${database}.hibernate.cfg.xml"
          tofile="${jbpm.home}/examples/target/classes/jbpm.hibernate.cfg.xml"
          overwrite="true">
      <filterset filtersfile="${jbpm.home}/install/jdbc/${database}.properties" />
    </copy>
    <jar destfile="${jbpm.home}/examples/target/examples.bar">
      <fileset dir="${jbpm.home}/examples/src">
        <exclude name="jbpm.cfg.xml" />
        <exclude name="jbpm.hibernate.cfg.xml" />
        <exclude name="jbpm.mail.properties" />
        <exclude name="jbpm.mail.templates.xml" />
        <exclude name="logging.properties" />
        <exclude name="org/jbpm/examples/task/swimlane/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/candidates/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/concurrency/graphbased/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/timer/repeat/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/script/text/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/decision/handler/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/mail/template/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/script/expression/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/assignee/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/mail/inline/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/mail/template/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/eventlistener/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/timer/event/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/assignmenthandler/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/java/JavaInstantiateTest.java" />
        <exclude name="org/jbpm/examples/decision/conditions/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/decision/expression/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/java/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/notification process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/reminder process.jpdl.xml" />
        <exclude name="org/jbpm/examples/rulesdecision/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/notification/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/task/reminder/process.jpdl.xml" />
        <exclude name="org/jbpm/examples/bpmn/event/terminateend/terminate_end_event.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/gateway/exclusive/exclusive_gateway.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/gateway/exclusive/exclusive_gateway_default_seq_flow.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/gateway/parallel/parallel_gateway.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/task/service/service_task_java.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/task/usertask/user_task_human_performer_variable.bpmn.xml" />
        <exclude name="org/jbpm/examples/bpmn/task/script/script_task.bpmn.xml" />
      </fileset>
    </jar>
  ...
  </target>

工作流引擎会扫描业务流程归档中所有以 .jpdl.xml 结尾的文件,所有这些文件的内容都会被当做 JPDL 流程定义来解析,然后被用来发起流程实例,业务流程归档中所有其他资源也会在部署过程中持久化到数据库中。

所有这些资源被统一编号保存在数据库表 jbpm4_lob 中,因此可以很方便地通过 jbpm4 提供的 RepositoryService.getResourceAsStream API 来访问这些资源。

  1. 部署。

需要先在 Ant 中将 JbpmDeployTask 声明为一个 jbpm-deploy 的自定义任务:

  <taskdef name="jbpm-deploy"
             classname="org.jbpm.pvm.internal.ant.JbpmDeployTask"
             classpathref="jbpm.libs.incl.dependencies" />

然后调用这个自定义的 Ant 任务:

 <jbpm-deploy file="${jbpm.home}/examples/target/examples.bar" />

通过 JbpmDeployTask 预留的 file 参数,指定需要部署的流程归档文件。

JbpmDeployTask 类为我们预留了 3 个接口参数:

private String jbpmCfg;
private File file;
private List<FileSet> fileSets = new ArrayList<FileSet>();

jbpm-deploy 任务支持这些属性:

属性类型默认值是否必填描述
file文件可选指定需要被部署的业务流程定义文件。以 .xml 结尾的文件会被作为流程定义文件直接部署;以 “*ar” 结尾的文件,比如 .bar或 .jar文件,则会作为业务流程归档文件部署。
cfg文件jbpm.cfg.xml可选指定 jbpm 配置文件,默认寻找 classpath 根目录下的 jbpm.cfg.xml。如果需要自定义,这个路径应位于 jbpm-deploy 任务定义的 classpath 范围内。

jbpm-deploy 任务支持这个元素:

元素关联关系描述
fileset0..*指定需要被部署的业务流程定义文件集合。以 .xml 结尾的文件会被作为流程定义文件直接部署;以 “*ar” 结尾的文件,比如 .bar或 .jar文件,则会作为业务流程归档文件部署。

首先配置好 JBPM 运行环境,即在 classpath 根目录下的jbpm.hibernate.cfg.xml 中设置好数据库连接,并确保数据库服务正常。

改造之前的 build.xml 文件,即可通过 Ant 脚本部署流程。

这里假设要部署一个 deniro.jar 的流程文件,它的 Ant 脚本如下:

<project name="jbpm.deployment">

    <!--使用 jbpm.home 表示 JBPM4 的安装目录-->
    <property name="jbpm.home" value="F:\ideaProjects\jbpm-4.4" />

    <!--这个 Ant 任务专门用来定义 JBPM 的运行库、依赖库以及配置文件的 classpath 路径-->
    <target name="jbpm.libs.path">
        <path id="jbpm.libs.incl.dependencies">
            <pathelement location="${jbpm.home}/examples/bin" />
            <fileset dir="${jbpm.home}">
                <include name="jbpm.jar"/>
            </fileset>
            <fileset dir="${jbpm.home}/lib" includes="*.jar" />
        </path>
    </target>
    <target name="deniro.jar" depends="jbpm.libs.path">
        <mkdir dir="${jbpm.home}/examples/target/classes" />
        <javac srcdir="${jbpm.home}/examples/src"
               destdir="${jbpm.home}/examples/target/classes"
               source="1.5"
               classpathref="jbpm.libs.incl.dependencies" />
        <copy todir="${jbpm.home}/examples/target/classes">
            <fileset dir="${jbpm.home}/examples/src">
                <exclude name="**/*.java" />
            </fileset>
        </copy>
        <jar destfile="${jbpm.home}/deniro.jar">
            <fileset dir="${jbpm.home}/examples/target/classes">
                <include name="**/*.class" />
            </fileset>
        </jar>
    </target>
    <!--使用 JBPM4工作流引擎提供的 Ant API——JbpmDeployTask 来执行部署-->
    <target name="deploy" depends="jbpm.libs.path,deniro.jar">
        <taskdef name="jbpm-deploy" classname="org.jbpm.pvm.internal.ant.JbpmDeployTask"
                 classpathref="jbpm.libs.incl.dependencies"/>
        <!--指定流程定义打包文件-->
        <jbpm-deploy file="${jbpm.home}/deniro.jar"/>
    </target>
</project>

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

在某些客户端实现中,开发者可以参考上述代码获得这些流程引擎提供的服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值