The important thing in life is to have a great aim , and the determination

          常用鏈接

          統計

          IT技術鏈接

          保險相關

          友情鏈接

          基金知識

          生活相關

          最新評論

          對Jbpm數據庫應用的簡單分析和在Mysql上實現的demo

          Jbpm 數據庫應用的簡單分析和在 Mysql 上實現的 demo

          ?

          吳大愚

          dywu_xa@sina.com

          2006-10-17

          ?

          ?

          適用 jbpm3.1 版本

          ?

          HelloWorldDbTest 的分析

          Eclipse 中到如 jbpm-starters-kit-3.1\jbpm 工程后,在 src\examples\org\jbpm\db 底下有一個 HelloWorldDbTest.java 的實例。我從這個實例分析開始,構建自己的 jbpm 工程在 Mysql 下的應用。

          首先我們來先分析一下 HelloWorldDbTest 實例。

          基本流程

          HelloWorldDbTest 類是一個 JUnit 的測試類。里面只有一個測試函數 testSimplePersistence 。這個函數里面調用了三個操作,分別是:

          l ???????? 將流程( processDefinition )的部署到數據庫中;

          l ???????? 從數據庫中加載流程,并實例化一個流程實例( processInstance ),然后運行一半再將流程實例存回數據庫;

          l ???????? 從數據庫中加載流程實例,然后運行完畢這個實例。

          JbpmConfigration

          在類 HelloWorldDbTest 中有靜態代碼段,內容是構造一個 JbpmConfigration 的實例。 JbpmConfigration Jbpm3.1 中和 Jbpm3 中差別很大, JbpmAPI 手冊描寫如下:

          configuration of one jBPM instance. During process execution, jBPM might need to use some services. A JbpmConfiguration contains the knowledge on how to create those services.

          A JbpmConfiguration is a thread safe object and serves as a factory for JbpmContexts, which means one JbpmConfiguration can be used to create JbpmContexts for all threads. The single JbpmConfiguration can be maintained in a static member or in the JNDI tree if that is available.

          JbpmConfigration 主要有兩種加載方法,一種是從配置文件中加載,一般使用 jbpm.cfg.xml jbpm-starters-kit-3.1 中放在 jbpm-starters-kit-3.1\jbpm\src\config.files 目錄下。要使用 jbpm.cfg.xml 進行配置的話,就必須把這個文件放在 classpath 中。因為 jbpm-starters-kit-3.1\jbpm 工程已經把此目錄放在工程的 classpath 中,所以如果在代碼中 JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance(); 這樣書寫的話就是使用 jbpm.cfg.xml 中的配置來構造 JbpmConfigration 。另外一種就是本例中使用的對 xml 解析的方法。

          使用數據庫

          在加載的 JbpmConfiguration 的加載內容中有如下部分:

          "? <string name='resource.hibernate.cfg.xml' " +

          ????? "????????? value='hibernate.cfg.xml' />" +

          這里面的 hibernate.cfg.xml 也在 jbpm-starters-kit-3.1\jbpm\src\config.files 目錄下,是對 Jbpm 使用的 Hibernate 的配置文檔。通過這個文檔, Jbpm 就可以通過 Hibernate 的工具,在不同的數據庫中,把說使用到的表全部構建出來,而不需要再人工去操作 sql 語句在數據庫中操作,這也就是為什么這個實例中沒有需要我們自己在數據庫中建表建庫的原因。

          通過 HelloWorldDbTest 類的注釋和用戶手冊中的文檔可以知道,在這個實例中使用的數據庫是一個內存數據庫,在目錄下的 Hibernate.cfg.xml 中有如下內容:

          ??? <!-- jdbc connection properties -->

          ??? < 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 >

          ?

          懂得 Hibernate 的朋友就能看出來,在 jbpm 工程中,使用的數據庫是 hsqldb

          在加載 HelloWorldDbTest 類的時候,就會發現,在 console 有大量的輸出。其中包括:

          12:27:38,201 [main] INFO? Configuration : Reading mappings from resource: org/jbpm/graph/def/Transition.hbm.xml

          12:27:38,231 [main] INFO? HbmBinder : Mapping class: org.jbpm.graph.def.Transition -> JBPM_TRANSITION “很多類似的輸出。這些輸出就是 Hiernate 在加載描述文件時候產生的說明信息。

          輸出信息中后面還包括對數據庫的連接,設置等等說明信息。

          ?

          JbpmConfiguration.createSchema()

          這個方法可以實現自動在數據庫中生成表結構的。在這個實例中,在 Junit ? setup() 操作中調用了這個函數,在進行測試實例前對數據庫進行創建。

          JbpmContext

          運行 HelloWorldDbTest 中的測試實例。

          首先是定義一個流程,然后就實例化一個 JbpmContext

          JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          JbpmContext 類是 Jbpm3.1 版本引進的一個新類,以前是沒有的。

          jbpm 的說明中有對 JbpmContext 類的如下說明:

          JbpmContext is used to surround persistent operations to processes.

          Obtain JbpmContext's via JbpmConfiguration.createJbpmContext() and put it in a try-finally block like this:

          ?JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();

          ?try {

          ?? TaskInstance taskInstance = ...

          ??

          ?? ...do your process operations...

          ??

          ?? // in case you update a process object that was not fetched

          ?? // with a ...ForUpdate method, you have to save it.

          ?? jbpmContext.save(processInstance);

          ?finally {

          ?? jbpmContext.close();

          ?}

          ?

          A JbpmContext separates jBPM from a sprecific environment. For each service that jBPM uses, there is an interface specified in the jBPM codebase. jBPM also includes implementations that implement these services by using services in a specific environment. e.g. a hibernate session, a JMS asynchronous messaging system, ...

          A JbpmContext can demarcate a transaction. When a PersistenceService is fetched from the JbpmContext, the default implementation for the persistence service will create a hibernate session and start a transaction. So that transactions can be configured in the hibernate configuration.

          A JbpmContext allows the user to overwrite (or make complete) the configuration by injecting objects programmatically. like e.g. a hibernate session factory or a hibernate session or any other resource that can be fetched or created from the configuration.

          Last but not least, JbpmContext provides convenient access to the most common operations such as getTaskList(String), newProcessInstance(String)loadTaskInstanceForUpdate(long) and save(ProcessInstance).

          All the ...ForUpdate(...) methods will automatically save the loaded objects at jbpmContext.close();

          將上面這些英文讀懂,基本上就能對JbpmContext有個大致的了解。最主要的就是實現Jbpm對數據庫操作的所有接口的封裝。

          流程部署

          deployProcessDefinition 中的 jbpmContext. deployProcessDefinition (processDefinition); 操作,向數據庫中部署一個流程。如果跟蹤 deployProcessDefinition 的話,會發現 jbpmContext 還是調用的 GraphSession 的流程部署方法。后面我們再講到 GraphSession 類。

          在后面使用 Mysql 實現的例子中,我們就可以通過工具在 mysql 中看到這樣一個部署流程的操作對數據庫有如何影響。同樣也可以查看流程實例化保存在數據庫中的情況。

          GraphSession

          Jbpm are the graph related database operations 的類。可以通過 GraphSession graphSession = jbpmContext.getGraphSession(); 來得到這個類的實例,并且 JbpmContext 很多方法都是封裝該類的方法。

          該類中包括了幾乎所有的數據庫操作的,例如部署流程,加載流程,部署流程實例,加載變量,等等。

          ?

          HelloWorldDbTest 類本身就已經有非常完整的注釋, 有關分析也就寫到這里。

          ?

          Jbpm Mysql 上的 demo 工程

          創建 Jbpm Project

          首先在 Eclipse 里面創建一個 Jbpm Process Project 的新項目。比如命名為 myDemo Eclipse Jbpm 插件會自動創建一些文件,比如在 processes 目錄下有一個 simple 的流程。在 src/java 下面有一個 MessageActionHandler 的類。在 src/config.files 目錄下四個配置有文件。在 test/java 下面有一個 SimpleProcessTest JUnit 類實例。可以先運行這個測試,應該是正確沒有問題的。

          配置 Mysql 數據庫

          打開 MySql 數據庫,假設 MySql 數據庫的用戶名為 root ,密碼 1234 。首先創建 jbpm_db 數據庫。然后修改 src/config.files 底下的 Hibernate.cfg.xml 文件。將連接數據庫的部分換成 Mysql 的內容。如下:

          ??????? <!-- jdbc connection properties -->

          ??? < 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_db </ property >

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

          ??? < property name = "hibernate.connection.password" > 1234 </ property > ?????????????

          添加代碼和流程

          我們先創建一個自己的流程。在 processes 目錄下面創建一個叫做 pro1 的流程。然后添加最簡單的, start-state ,end 和一個 state 節點。

          Jbpm3 工程中的 jbpm.cfg.xml 中的內容添加到 src/config.files 目錄下的 jbpm.cfg.xml 中。

          test/java 目錄下面添加一個新的 Junit 類。命名為 SimpleDBTest

          代碼如下:

          package com.sample;

          ?

          import java.io.FileInputStream;

          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;

          ?

          public class SimpleDBTest extends TestCase {

          ?????? static JbpmConfiguration cfg = JbpmConfiguration.getInstance();????

          ?????? public void setUp() {

          ?????? ?? cfg.createSchema();

          ?????? }????

          ?????? public void testDeployProcessDefinition() throws Exception {

          ????????????? assertNotNull("JbpmConfiguration should not be null", cfg);

          ???????????????????????????

          ????????????? FileInputStream fis = new FileInputStream("processes/pro1/processdefinition.xml");

          ????????????? ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(fis);

          ????????????? assertNotNull("Definition should not be null", processDefinition);

          ?????? ??

          ????????????? JbpmContext jbpmContext = cfg.createJbpmContext() ;

          ?????????????

          ????????????? try {

          ?????? ??????? // Deploy the process definition in the database

          ?????? ??????? jbpmContext.deployProcessDefinition(processDefinition);

          ?????? ????? } finally {

          ?????? ???? ???jbpmContext.close();

          ?????? ????? }

          ?????? }

          }

          執行這個操作,會發現報錯,報不能找到 Hibernate 的錯誤。原來在 Eclipse 建立的 Jbpm 的工程中,雖然添加了 Jbpm 的包,但沒有添加 Hibernate 的包。因此在工程的 Java Build Path Libraries 底下添加 Hibernate 的包(具體添加那些,請參考 Jbpm 的用戶手冊)。

          部署流程

          執行 SimpleDBTest .testDeployProcessDefinition() 操作。如果沒有錯誤的話,這次就可以將流程 pro1 部署進入 Mysql 數據庫。

          jbpm_db 數據庫中會看到產生了 33 個表。查看 jbpm_processdefinition 表,會發現有一個名字為 pro1 ID 1 version 1 的條目。

          同樣可以查看 jbpm_node 表。

          再次部署

          修改流程 pro1 的定義,在 state1 節點添加一個 Action ,在 node-enter 事件中。完整的 xml 文件見該文檔最后部分。然后再次運行 SimpleDBTest .testDeployProcessDefinition() 操作。查看 jbpm_processdefinition ,會發現有了一個 pro1 version 2 版本的流程。這里有了一個 Jbpm 流程版本的概念,可以參考用戶手冊。

          還可查看 jbpm_event jbpm_action 表。

          實例化流程

          添加代碼:

          ?????? public void testLoadProcessAndInstance() throws Exception {

          ????????????? JbpmContext jbpmContext = cfg.createJbpmContext() ;???????????

          ????????????? try {

          ????????????? ????? GraphSession graphSession = jbpmContext.getGraphSession();??????????? ?????

          ????????????? ????? ProcessDefinition processDefinition =

          ????????????? ????????? graphSession.findLatestProcessDefinition("pro1");???????? ???

          ????????????? ????? ProcessInstance processInstance =

          ????????????? ????????? new ProcessInstance(processDefinition);

          ????????????? ????? Token token = processInstance.getRootToken();

          ????????????? ????? assertEquals("start", token.getNode().getName());

          ????????????? ????? // Let's start the process execution

          ????????????? ????? token.signal();

          ????????????? ????? assertEquals("state1", token.getNode().getName());

          ????????????? ?????

          ?????? ?????? ????? jbpmContext.save(processInstance);

          ?

          ????????????? ??? } finally {

          ????????????? ????? // Tear down the pojo persistence context.

          ????????????? ????? jbpmContext.close();

          ????????????? ??? }

          ?????? }

          這段代碼把 pro1 流程的最新版本加載進來,然后實例化。并開始執行,到 state1 節點停下來(此時 Action 已經執行過了)。然后把這個實例也存入數據庫。

          這時候查看 jbpm_processInstance 表, jbpm_token 表。

          完成實例的運行

          添加代碼

          public void testLoadInstanceAndDoActionAndEnd() throws Exception {

          ????????????? JbpmContext jbpmContext = cfg.createJbpmContext() ;???????????

          ????????????? ? try {

          ????????????? ????? GraphSession graphSession = jbpmContext.getGraphSession();

          ????????????? ???

          ????????????? ????? ProcessDefinition processDefinition =

          ????????????? ????????? graphSession.findLatestProcessDefinition("pro1");

          ????????????? ????? List processInstances =

          ????????????? ????????? graphSession.findProcessInstances(processDefinition.getId());???????????? ?????

          ??????

          ????????????? ????? ProcessInstance processInstance =

          ????????????? ??????? ??(ProcessInstance) processInstances.get(0);??????????? ?????

          ????????????? ????? this.assertEquals("message",(String)(processInstance.getContextInstance().getVariable("message")));

          ????????????? ????? processInstance.signal();

          ????????????? ????? assertTrue(processInstance.hasEnded());

          ????????????? ????? jbpmContext.save(processInstance);

          ????????????? ??? } finally {

          ????????????? ????? jbpmContext.close();

          ????????????? ??? }

          ?????? }

          這段代碼將剛才的流程實例從數據庫中加載進來,然后執行完畢。

          查看表 jbpm_processinstance 表,會發現上次 end 字段還是 null ,現在已經是填寫了剛才執行的事件了,表示這個流程實例已經執行完畢。

          流程 Pro1 的完整 xml 文檔

          <? xml version = "1.0" encoding = "UTF-8" ?>

          ?

          < process-definition

          ? xmlns = "urn:jbpm.org:jpdl-3.1"? name = "pro1" >

          ?? < start-state name = "start" >

          ????? < transition name = "" to = "state1" ></ transition >

          ?? </ start-state >

          ?? < state name = "state1" >

          ????? < event type = "node-enter" >

          ???????? < action name = "action1" class = "com.sample.action.MessageActionHandler" >

          ??????????? < message > message </ message >

          ??????????? < message2 > message2 </ message2 >

          ???????? </ action >

          ????? </ event >

          ????? < transition name = "" to = "end" ></ transition >

          ?? </ state >

          ?? < end-state name = "end" ></ end-state >

          </ process-definition >

          總結

          posted on 2006-12-04 17:12 鴻雁 閱讀(264) 評論(0)  編輯  收藏

          主站蜘蛛池模板: 安溪县| 绍兴县| 延吉市| 津市市| 武强县| 长岭县| 江安县| 永德县| 博爱县| 天等县| 元氏县| 深泽县| 怀来县| 景德镇市| 平原县| 观塘区| 河间市| 广平县| 门源| 长海县| 淅川县| 青神县| 普格县| 扶绥县| 大悟县| 宜章县| 大余县| 拜城县| 长顺县| 虹口区| 镇原县| 英山县| 容城县| 苏州市| 景洪市| 探索| 平阴县| 岳阳市| 滦南县| 四平市| 云和县|