fbpx

工作流程引擎介紹 - JBoss JBPM (JAVA Business Process Management)

JBPM 介紹

JBPM 是一項由 Java 所實作的企業流程引擎,由大名鼎鼎的 JBoss 所領導與發展。其中的 JBPM Engine 是 License 採用 LGPL 授權。那麼 BPM 提供了哪些功能呢?其實 BPM 可以想像成我們一般常會使用的流程圖,JBPM 提供了將這些流程進行設計、規劃、管理、執行等等功能。那麼如何告訴 JBPM 我們所定義的流程呢?其實是透過 JBPM Process Definition Language (JPDL) 這一項語言來完成,JPDL 使用 XML 為基礎,JBPM 除了提供 BPM Engine 之外也提供了 Graphical Process Designer (GPD) 來輔助我們定義與建立流程,你總不希望設計流程還要寫 XML 吧!? GPD 提供了 Eclipse 的套件,使用者可以透過 Eclipse 直接編輯流程。

那麼這些流程會儲存在哪裡呢?官方已經整合了 Hibernate 並且也有提供了一項嵌入式的 Database 稱為 hsqldb ,此外 Spring 也能夠與 jBPM 進行整合,將 jBPM 的設定交由 Spring 來管理。jBPM 目前最新的版本為 4.3,以下我們就使用最新的版本進行測試。

JBPM 安裝方式

JBPM 4.3 + Jetty + Spring + Hibernate + Postgresql 終極整合

JBPM 4.3 與先前 JBPM 3.x 的版本差異較大最主要在新版中支援了 BPMN 2.0。在官方提供的整合文件中有錯誤,造成整合問題一直無法成功。希望這些問題在下一個版本會獲得解決之道。

JBPM 設定介紹

JBPM 最重要的就是取得 ProcessEngine,在 Spring 中視透過 SpringHelper 這一支 Class 來進行配置,預設情況 JBPM 在 Spring 這設定中會讀取 Classpath 中的 jbpm.cfg.xml 設定檔。jbpm.cfg.xml 設定檔內容如下,仔細看看相較於以前的版本是不是很精簡呢。

jbpm.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<jbpm-configuration>
    <import resource="jbpm.default.cfg.xml" />
    <import resource="jbpm.tx.spring.cfg.xml" />
    <import resource="jbpm.jpdl.cfg.xml" />
    <import resource="jbpm.bpmn.cfg.xml" />
    <import resource="jbpm.identity.cfg.xml" />
    <import resource="jbpm.businesscalendar.cfg.xml" />
    <import resource="jbpm.console.cfg.xml" />
    <import resource="jbpm.jobexecutor.cfg.xml" />
</jbpm-configuration>

以下是 Spring 的設定,ApplicationContext.xml 檔案內容如下:

<bean id="springHelper" />
<bean id="transactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
    <property name="dataSource" ref="dataSource" />
</bean>
<bean id="processEngine" factory-bean="springHelper" factory-method="createProcessEngine" />

有了上述的設定,你還是會跑不起來,因為 Spring3 整合 JBPM 4.3 含有許多問題,以下是我實作上遭遇的問題與解決方式。

  • Spring 3 整合 JBPM 4.3 內建 Bug 1 - Service 配置死循環

在 Spring ApplicationContext 中不可透過以下方法配置 RepositoryService, ExecutionService, 如此會照成死循環導致 Spring 初始化失敗,這應該是 JBPM 的 BUG,以下為引述:

If you are using jBPM-4.3 in Spring, you cannot use add 'repositoryService' or 'executionService' in the application context.
It will cause a cycle reference in SpringContext.
Because jBPM-4.3 will append the SpringContext on the top of EnvironmentStack.

When you invoked the 'factory-method="getRepositoryService"', it will look up RepositoryService in the EnvironmentStack, but the first environment is SpringContext.
So it will go back to application context and find out a bean named 'repositoryService' declared in the application context, but this bean is not yet created.
Spring will continue invoke the factory-method to create this bean and go back to jBPM4, then there is a endless cycle.

If you want to use jBPM-4.3 in Spring, you should remove repsitoryService and executionService from processEngine.

所以 Spring 不可加入以下設定

<bean id="executionService" factory-bean="processEngine" factory-method="getExecutionService" />
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />

  • Spring 3 整合 JBPM 4.3 內建 Bug 2 - java.lang.NumberFormatException: For input string

此外在 JBPM 4.3 與 Spring 3 進行整合的時候後還有一個 Bug,就是執行時會出現 java.lang.NumberFormatException: For input string: "java.vm.version" 錯誤,這個錯誤會在 JBPM 4.4 中獲得解決。官方說明如下:https://jira.jboss.org/browse/JBPM-2859,修正方法為修改 jbpm.jar 裡面的 jbpm.default.cfg.xml 檔案,將

<repository-cache>

替換為以下設定

<object/>

將 jbpm.default.cfg.xml 放在 classpath 底下即可,或是回存到jar檔中。

  • Spring 3 整合 JBPM 4.3 內建 Bug 3 - IllegalStateException: BeanFactory not initialized or already closed - callrefresh' before accessing beans via the ApplicationContext

這個問題必須在 Spring 建立一個 ApplicationListener 來處理 Close Event,實作的 Class 如下:

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.jbpm.api.ProcessEngine;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;

@Component
@SuppressWarnings("unchecked")
public class SpringJbpmJobExecutorShutdownHook implements ApplicationListener {

    static final Logger log = Logger.getLogger(SpringJbpmJobExecutorShutdownHook.class);

    @Resource
    private ProcessEngine processEngine;

    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextClosedEvent ) {
            log.info("Spring ApplicationContext shutting down.  Closing jBPM process engine.");
            processEngine.close();
            log.info("jBPM process engine closed.");
        }
    }

}

此外,在 Hibernate 的設定已然可以採用c3p0的 Connection Pool 進行配置,這裡就不多做介紹了。重點在 ORM 的設定檔記得要匯入(*.hbm.xml),這些檔案可在 JBPM 安裝目錄中的 src 資料夾中找到,請參考以下設定方式:

hibernate.xml (片段)

<bean id="sessionFactory" destroy-method="destroy">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
    <property name="mappingDirectoryLocations">
        <list>
            <value>jbpm.execution.hbm.xml</value>
            <value>jbpm.history.hbm.xml</value>
            <value>jbpm.identity.hbm.xml</value>
            <value>jbpm.repository.hbm.xml</value>
            <value>jbpm.task.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${db.dialect}</prop>
        </props>
    </property>
</bean>
透過上述的方法,您應該已經可以成功的啟動 JBPM,並且從 Spring Application Context 獲得 ProcessEngine,剩下的工作就是如何去熟悉 JBPM 的能力與使用方式。

JBPM 如何運作

JBPM 透過 ProcessDefinition 來定義流程,ProcessDefinition 由一個 XML 所組成,可以放在資料庫或檔案系統中。每一個 ProcessDefinition 必須要有一個名稱(name),除了 name 還能賦與 version 與 key。透過 ExecutionService 可以獲得一個 InstanceProcess,接下來即可對此流程進行控制。以下為測試的 ProcessDefinition XML:

<?xml version="1.0" encoding="UTF-8"?>
<process name="StateChoice" xmlns="http://jbpm.org/4.3/jpdl">

    <start g="133,165,80,40">
        <transition to="wait for response"/>
    </start>

    <state name="wait for response" g="248,169,80,40">
        <transition name="accept" to="submit document" g="-40,-20"/>
        <transition name="reject" to="try again" g="-36,-20"/>
    </state>

    <state name="submit document" g="249,277,80,40"/>

    <state name="try again" g="247,71,80,40"/>

</process>

上述 XML 描述了一個名為 StateChoice 的流程,XML 應該很難理解,流程示意圖如下:

StateChoice

這張圖怎麼來的?其實是透過 JBPM 提供的視覺化編輯器產生的。官方也提供一張示意圖來說明 JBPM 的運作與架構,如下所示:

dhkvvpms_13cxzpjhhw_b

Eclipse 視覺化流程編輯器 PGD, Graphical Process Designer 介紹

安裝方式可參考一下官方文件
http://docs.jboss.com/jbpm/v4/userguide/html_single/#graphicalprocessdesigner

執行畫面如下:

pgd

結論

在企業級的 IT 應用中 BPM 的重要性是不可否認的,至少大型的整合系統(例如SAP, WebSphere, WebLogic)都提供了這樣的功能。JBPM 提供了簡易的流程管理並且結合了 Hibernate 進行資料庫的存取,提供了精簡的 BPM Engine 已經足夠滿足大多數的需求,而缺乏的是 Web Service 元件化的整合介面。以雲端服務的精神來考量,假設能實作分散式儲存與包裝 Web Service 將會是跨入大型應用的首要任務。

參考文獻

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料