jBPM开发入门(3)

来源:互联网 发布:java performance中文 编辑:程序博客网 时间:2024/05/18 01:50

5 安装jBPMEclipse开发插件

有个辅助工具开发起来方便一点,只不过现在jBPM的开发工具插件功能还不算太强,也就一个“项目创建向导”的功能,让你:

(1)不用再去配置classpath库的引用了

(2)直接得到了一个jBPM的项目初始结构

其实吧,开发jBPM也不需要什么插件工具,在熟练了以后,库引用了项目初始结构都可以手工创建。

插件不用再去下载了,jbpm-starters-kit-3.1.1包里就有,目录地址如下:D:/jbpm-starters-kit-3.1.1/jbpm-designer/jbpm-gpd-feature/eclipse,插件的安装方式是链接式还是直接复制式,任选吧。不懂的就去看看《Eclipse从入门精通》这本书,在前面章节都有讲到。另外,注明一下Eclipse的版本我是用3.2,插件和Eclispe版本相关的,要注意了。

如果安装成功,则Eclipse首选项里多了一个JBoss jBPM,另外我们也需要到这个jBPM的首选项里做一些配置工作――指定jBPM的安装路径(如下图所示)。这个配置主要是为了找到jbpm下的各种jar包,好让Eclipse设置项目的库引用。本文指向路径是d:/jbpm-starters-kit-3.1.1/jbpm.3

20060823_image001.jpg 

6 jBPMHello World

6.1 新建jBPM项目

主菜单“文件->新建->项目”,在弹出的对话框里,有“Process Project”项,如下图所示:

 20060823_image002.jpg


选上好,单击“下一步”,起个名“
myjbpm”,然后就可以单击“完成”了。然后就生成了如下图所示的一个项目结构:
20060823_image003.jpg 

这个项目和通常
Eclipse的项目结构有点不同,不过这是一个现在非常流行的项目结构,src/java存放源文件,test/java存放相应的JUnit单元测试代码。如果你用Maven来编译构建项目,对这种目录结构一定不陌生。

 

项目创建起了,介绍一下里面的文件吧:

l           MessageActionHandler,自动生成的一个ActionHandler。不想要可以删掉。

l           ehcache.xml  cache的配置文件,里面有很详解的英文说明。没有必要可以不用改它。

l           hibernate.cfg.xml jBPM是用Hibernate进行工作流的数据存储的,这个就是Hibernate的配置文件。后面我们将讲到如何配置这个文件。

l           jbpm.cfg.xml jbpm本身的配置文件。现在是空的,它用的是缺省配置,你想知道有哪些配置就去看这个文件D:/jbpm-starters-kit-3.1.1/jbpm.3/src/java.jbpm/org/jbpm/default.jbpm.cfg.xml

l           log4j.properties 这个是日志APIlog4j的配置文件,用过log4j的都知道。

l           SimpleProcessTest.java 这个是对最重要的流程配置文件的processdefinition.xml单元测试代码。这里表扬一点,jBPM的优良设计使得它的可测试性非常之高,喜欢写t单元测试的人有福了。

l           gpd.xml 用于生成流程图的定义文件。都是一些方框的坐标和长宽

l           processdefinition.xml 这个是对最重要的流程配置文件,以后写流程要经常和它打交道。

l           processimage.jpg 一个流程图


从项目结构来看,我们没有看到
JSP网页程序,也没有看到GUI客户端程序,这些代码都是要我们以后开发中来写的。但本文不准备用JSPGUISwingSWT)来做示例,而是用JUnit代码来做使用jBPM客户端来演示。因为jBPM实际上是一个后台框架,至于前台是JSP还是Swing还是无界面的java.class都是无关紧要的。在教程里用无界面的java.class来做客户端则更方便一些,如果进一步采用JUnit,则这样的java.class同时还具备了单元测试的功能。以后就是用JSP写了WEB页面,我们还是可以用这些JUnit程序来做单元测试,避免了频繁的鼠标点按WEB页面这样的力气活。所以在jBPM自带的英文教程里都是一个JUnit程序,不仔佃看还真摸不着头脑。


6.2 修改hibernate.cfg.xml

hibernate.cfg.xml的默认设置是用HSQL,这是一个内存数据库,这种内存数据库用来代替项目实际所用的数据库来做单元测试挺不错的。不过我们这里是要试试用MySQLOracle,那就改一下设置吧。

注:配置值可参考D:/jbpm-starters-kit-3.1.1/jbpm-db对应子目录下的hibernate.properties文件。

1MySQL的更改如下:

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jbpm</property>

<property name="hibernate.connection.username">root</property>

<property name="hibernate.connection.password">123456</property>


2Oracle的更改如下:

<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>

<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

<property name="hibernate.connection.url">jdbc:oracle:thin:@192.168.123.10:1521:wxxrDB</property>

<property name="hibernate.connection.username">chengang</property>

<property name="hibernate.connection.password">chengang</property>

 

如果你装了Oracle的客户端,并且D:/oracle/ora92/network/ADMIN/tnsnames.ora里做了如下的设置

WXXRDB_192.168.123.10 =

  (DESCRIPTION =

    (ADDRESS_LIST =

      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.123.10)(PORT = 1521))

    )

    (CONNECT_DATA =

      (SID = wxxrDB)

      (SERVER = DEDICATED)

    )

  )


Oraclehibernate.connection.url项也可以设为:jdbc:oracle:oci:@WXXRDB_192.168.123.10

6.3 完善库引用

虽然jBPM在创建项目之初给我们设置好了库引用,如下图

20060823_image004.jpg
 

但后面运行时还是报一些NoClassDefFoundError异常,如没有对hibernate3.jar的引用导致下面的错误

java.lang.NoClassDefFoundError: org/hibernate/Session

    at org.jbpm.persistence.db.DbPersistenceServiceFactory.openService(DbPersistenceServiceFactory.java:55)

    at org.jbpm.svc.Services.getService(Services.java:136)

    .......

 

所以我们要为本文的实例完善库引用。主要是把MySQLOracleJDBC库、以及Hibernatehibernate3.jar加入到项目的库引用中。

(1)       找到缺少的jar

l           mysqljdbc包,在D:/jbpm-starters-kit-3.1.1/jbpm-db/mysql/lib目录里

l           oraclejdbc包,jbmp中没有包含(可能是没拿到oracle授权),我们可以自已去oracle网站上下载,或者去oracle安装目录D:/oracle/ora92/jdbc/libojdbc14.jar(我们公司用的是Oracle9i

l           Hibernate3.jar在目录D:/jbpm-starters-kit-3.1.1/jbpm.3/lib/hibernate里。

(2)       在项目里创建一个lib目录,将这三个jar复制到lib目录。

(3)       如下图设置三jar包的库引用

20060823_image005.jpg 

6.4 开始HellorWorld

这里是一个很简单的请假流程,请假人提交假单给经理审批,经理审批后结束。要说明的是,这个流程并不严谨,比如经理不通过流程应该到哪?不过这并不防碍拿它来做示例,螃蟹还得一个一个的吃。我们先拿这一杆子捅到底的流程做一个最简单的示例,从整体上对jBPM工作流开发有概念先。然后我们再慢慢丰富。

1、定义流程

流程的定义文件是processdefinition.xml,这个是一个关键文件,jBPM的很大一部份内容都是关于它的。在这里我们把原来自动生成的内容,稍做改动:

<?xml version="1.0" encoding="GBK"?>

 

<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="helloworld">

    <!-- 申请-->

    <start-state name="request">

        <task>

            <controller>

                <variable name="name" />

                <variable name="day" />

                <variable name="note" />

            </controller>

        </task>

        <!-- 流程转向-->

        <transition name="to_confirm" to="confirm">

            <action name="requestAction"

                class="cn.com.chengang.jbpm.RequestAction">

                <reason>我要请假</reason>

            </action>

        </transition>

    </start-state>

    <!-- 审批-->

    <state name="confirm">

        <transition name="to_end" to="end">

            <action name="finishAction"

                class="cn.com.chengang.jbpm.ConfirmAction" />

        </transition>

    </state>

    <!-- 结束-->

    <end-state name="end" />

</process-definition>


说明:

流程的名称改成了helloworld。(呵呵,也就是这里和helloworld有关了)

<controller>标签定义了三个数据:姓名、请假天数、说明。

<transition>标签定了request节点的一个流程转向,这里是转到confirm节点。

<action>标签定义了流程由一个节点转到另一个节点时,所要执行的动作,动作封装在一个ActionHandler类中。比如这里当requestconfirm结点时将执行RequestAction类的execute方法。

FinishAction下面还有一个<reason>(请假理由),它对应于FinshAction的属性String reason 

2、 编写ActionHandler

       在上面processdefinition.xml里我们定义了两个ActionHandlerRequestActionConfirmAction。其代码如下:

packagecn.com.chengang.jbpm;

 

importorg.jbpm.graph.def.ActionHandler;

importorg.jbpm.graph.exe.ExecutionContext;

 

publicclassRequestAction implements ActionHandler {

 

    privatestaticfinallongserialVersionUID= 1L;

 

    privateString reason;

 

    publicString getReason() {

        returnreason;

    }

 

    publicvoidsetReason(String reason) {

        this.reason = reason;

    }

 

    publicvoidexecute(ExecutionContext context) throws Exception {

        context.getContextInstance().setVariable("note", reason);

    }

 

}

 

说明:ExecutionContext是一个贯通流程的容器。它是个大宝箱,里面啥玩意都有,后面将更深入的提到。这里的reasion就是processdefinition.xml中的我要请假

 

 

packagecn.com.chengang.jbpm;

 

importorg.jbpm.graph.def.ActionHandler;

importorg.jbpm.graph.exe.ExecutionContext;

 

publicclassConfirmAction implements ActionHandler {

 

    privatestaticfinallongserialVersionUID= 1L;

 

    publicvoidexecute(ExecutionContext context) throws Exception {

        context.getContextInstance().setVariable("note", "准假");

    }

 

}

 

OK,后台的程序就算写完了(前台客户端的程序还没写),下面开始部署。

6.5 部署processdefinition.xml

我们要把processdefinition.xml的流程定义的数据部署到数据库中,因为jBPM在正式运行的时候不是去读processdefinition.xml文件,而是去读数据库中的流程定义。这里写了一个个JUnit程序来部署processdefinition.xml,当然你用普通的Java Main也可以。

packagecom.sample;

 

importjava.io.FileInputStream;

importjava.io.FileNotFoundException;

importjava.io.InputStream;

importjunit.framework.TestCase;

importorg.jbpm.JbpmConfiguration;

importorg.jbpm.JbpmContext;

importorg.jbpm.graph.def.ProcessDefinition;

 

/**

 * 部署processdefinition.xml

 *

 * @author chengang

 *

 */

publicclassDeployProcessTest extends TestCase {

    /**

     * 在本方法执行完毕后,检查jbpm_processdefinition表会多了一条记录

     *

     * @throws FileNotFoundException

     */

    publicvoidtestDeployProcessDefinition() throws FileNotFoundException {

        // jbpm.cfg.xml取得jbpm的配置

        JbpmConfiguration config = JbpmConfiguration.getInstance();

        // 创建一个jbpm容器

        JbpmContext jbpmContext = config.createJbpmContext();

        // processdefinition.xml生成相对应的流程定义类ProcessDefinition

        InputStream is = new FileInputStream("processes/simple/processdefinition.xml");

        ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(is);

        // 利用容器的方法将流程定义数据部署到数据库上

        jbpmContext.deployProcessDefinition(processDefinition);

        // 关闭jbpmContext

        jbpmContext.close();

    }

 

}

 

运行此程序,在控制台打印了一些日志,通过。如果出错,仔佃阅读出错信息以判断错误原因,并确定你按照前面两节:“修改hibernate.cfg.xml”和“完善库引用”的内容做好了设置。

6.6 从数据库中的查看部署效果

无论是MySQL还是Oracle,查询jbpm_processdefinition表,你会发现多了一条记录,如下图(PLSQL Developer的显示为例)

20060823_image006.jpg
 

依次检查各表我们可以发现有如下变化:

20060823_image007.jpg
20060823_image008.jpg
20060823_image009.jpg
20060823_image010.jpg
20060823_image011.jpg
20060823_image012.jpg
 

并由此简单判断出各表的作用,表中各字段的作用由字段名也能知晓一二。

jbpm_processdefinition

一个流程定义文件对应一条记录,可记录多个流程定义文件,可记录一个流程定义文件的对个版本。

jbpm_action

记录ActionHandler的对象实例(以名称为标识)

jbpm_delegation

记录了ActionHandler全类名,以便于用反射方式来加载

jbpm_envent

它的transition引用了Jbpm_transition表的id,再看其它字段,估计此表是表示流程转向事件的一个实例,或者是一个各表之间的联接表。

jbpm_node

流程结点

jbpm_transition

流程的转向定义

jbpm_variableaccess

流程中携带的变量。ACCESS字段是这些变量的读写权限


 作者简介
陈刚,广西桂林人,著作有《Eclipse从入门到精通》
原创粉丝点击