《jBPM學習筆記(V3.2環境部署)》
《jBPM學習筆記(框架設計簡介)》
背景
本片文章,我們將從業務流程的設計開始,通過帶領大家完成一個完整工作流的程序設計,來學習jPDL的使用。
業務流程設計
這裏我們實現一個相對簡化的公司借款申請流程。流程圖如下:
在jPDL中,與流程設計相關的文件有三個:processdefinition.xml、gdp.xml、processimage.jpg。其中processdefinition.xml是流程定義的描述文件;gpd.xml是對圖形界面呈現的XML描述;而processimage.jpg則是對圖形界面的快照。下面我們將展示本樣例的流程定義文件。
流程定義描述
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns ="urn:jbpm.org:jpdl-3.2" name="simple">
<start-state name="開始">
<transition name="借款發起" to="填寫借款申請">
<action name="Action_StartProcess" class="com.firstflow.action.StartProcessActionHander"></action>
</transition>
</start-state>
<task-node name="填寫借款申請">
<task name="Task_AssignToInitiator">
<assignment class="com.firstflow.task.NewApplicationAssignmentHandler"></assignment>
</task>
<transition to="部門經理審批" name="提交申請">
<action name="Action_SubmitApply" class="com.firstflow.action.SubmitApplyActionHandler"></action>
</transition>
</task-node>
<task-node name="部門經理審批">
<task name="Task_ManagerApprove">
<assignment class="com.firstflow.task.DepartmentManagerApproveAssignmentHandler"></assignment>
</task>
<transition to="金額判定" name="部門經理審批通過">
<action name="Task_ManagerApproved" class="com.firstflow.action.ManagerApprovedActionHandler"></action>
</transition>
<transition to="結束" name="部門經理駁回">
<action name="Action_ManagerDisapprove" class="com.firstflow.action.ManagerDisapproveActionHandler"></action>
</transition>
</task-node>
<node name="財務撥款">
<action name="Action_AccountantProcess" class="com.firstflow.action.AccountantProcessActoinHandler"></action>
<transition to="結束" name="郵件通知">
<action name="Action_Mail" class="com.firstflow.action.SendMailActionHandler"></action>
</transition>
</node>
<decision name="金額判定">
<handler class="com.firstflow.decision.MoneyCheckDecisionHandler"></handler>
<transition to="總經理審批" name=">5000元總經理審批"></transition>
<transition to="財務撥款" name="<5000元 財務撥款"></transition>
</decision>
<task-node name="總經理審批">
<task name="Task_PresidentApprove">
<assignment class="com.firstflow.task.PresidentApproveAssignmentHandler"></assignment>
</task>
<transition to="財務撥款" name="總經理審批通過">
<action name="Action_PresidentApproved" class="com.firstflow.action.PresidentApprovedActionHandler"></action>
</transition>
<transition to="結束" name="總經理駁回">
<action name="Action_PresidentDisapproved" class="com.firstflow.action.PresidentDisapprovedActionHandler"></action>
</transition>
</task-node>
<end-state name="結束"></end-state>
</process-definition>
在樣例流程中,除了開始和結束結點外,我們定義了三種類型的結點:
任務結點<task-node>
任務結點是一個需要人工參與的結點類型。當流程進入結點時,會生成相應的任務實例(TaskInstatnce),並通過委派接口AssignmentHandler或jBPM表達式將任務委派給一個或多個特定的角色或參與者。結點自身進入等待狀態,直到任務被參與者完成或者跳過,流程繼續。
判定結點<decision>
判定結點的設計目標是根據上下文環境和程序邏輯,判定流程轉向。通過指定一個實現DecisionHandlder接口的Java委派類或jBPM表達式,來返回轉向(transition)的字符竄類型的名稱(可以是中文哦),來達到決定流程方向的功能。
普通結點<node>
普通結點也可以定義相應的處理任務,通過定義相應的ActioinHandler類。同任務結點不同的是,普通結點定義的任務是由流程自動執行的,無須人工干預。
三種結點都可定義結點事件(event):
node-enter,該事件在流程進入結點時觸發
node-leave,該事件在流程離開節點是觸發
可以在事件上掛接ActioinHandler接口的實現類來完成一些特定的功能。
三種節點都可以定義異步處理方式(async屬性):
異步處理意味着每個結點的事務處理是通過消息機制分離的,不再同一線程中統一調用執行。而是由消息監聽線程從消息隊列中取得消息體來運行相應得程序。
此外我們定義了結點間的轉向(transition),用來記錄和處理狀態的變遷。每個轉向中,可以委派一個或多個的ActioinHandler接口實現類,負責處理節點變遷時的上下文狀態變更及回調用戶定義的處理程序。
流程的程序接口說明
動作處理接口(ActioinHandler)
接口方法:void execute( ExecutionContext executionContext ) throws Exception
該接口是jPDL中最常用的一個回調接口。從它的接口方法可以發現,它僅僅暴露了流程執行上下文變量ExecutionContext。用戶程序通過ExecutionContext來了解流程的執行狀態,並通過改變ExecutionContext中的屬性值來影響流程的執行。
ActioinHandler接口可以在所有能包含事件(event)、動作(action)元素的地方被回調。
判定處理接口(DecisionHandlder)
接口方法:String decide(ExecutionContext executionContext) throws Exception
判定接口僅適用於判定節點(decision)中。從它的接口方法可以看出,方法要返回一個字符串型的結果,這個結果必須和判定節點擁有的轉向(transition)集合中的一條轉向名稱相匹配。
在DecisionHandlder的接口方法中一樣能訪問到ExecutionContext變量,這爲判定提供了執行上下文的根據。當然,如果有必要,用戶也可以在該接口中改變ExecutionContext中的變量值。
委派處理接口(AssignmentHandler)
接口方法:void assign(Assignable assignable, ExecutionContext executionContext) throws Exception;
委派處理接口被用戶任務元素(task)的委派(assignment)子元素中,它的職責很明確,就是將任務分配給指定的人員或角色。
在AssignmentHandler接口的方法中,Assignable變量通常指任務實例(TaskInstance)。通過將ExecutionContext和TaskInstance兩個變量都暴露給接口方法,用戶就可以根據流程上下文情況,來決定要將指定的任務分配個誰。
流程的部署
用戶使用jPDL的流程設計器定義業務流程,當然,你也可以直接用文檔編輯器直接編輯processdefinition.xml定義文件。定義文檔是可以直接被ProcessDefinition類載入使用的,但在正式運行的系統中,流程定義信息更多是使用關係型數據庫來存儲。從流程定義文件將數據導入流程數據庫的過程,我們稱之爲流程部署。
jPDL的流程部署文件包含processdefinition.xml的定義部分和Java處理器的代碼部分,這些文件可以被一起打包成.jpdl的zip格式包而後上傳服務器端。這個過程可以在流程設計器界面的“deployment”標籤頁中操作:
這裏我們着重要講述的是接受部署文件上載的服務器端配置。在jBPM3.2的包中帶着一個jPDL的管理控制檯web應用,默認名字爲jbpm-console。該應用帶有接受流程定義包部署的程序,但不是最小化的。實際上完成流程部署功能的,只是jbpm-jpdl.jar核心包中的一個servlet類:org.jbpm.web.ProcessUploadServlet . 完成這個Servlet的成功部署,需要以下工作:
1. 配置web.xml,將servlet配置成啓動時加載,如下:
<web-app>
<servlet>
<servlet-name>GDP Deployer Servlet</servlet-name>
<servlet-class>org.jbpm.web.ProcessUploadServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>GDP Deployer Servlet</servlet-name>
<url-pattern>/upload/*</url-pattern>
</servlet-mapping>
</web-app>
2. 建立流程定義存儲數據庫表:
Demo中,我們使用的數據庫是MySQL的,在E:\Java\tools\jbpm-jpdl-3.2.2\db\目錄下有個jbpm.jpdl.mysql.sql數據庫腳本文件。但我們不能直接導入該文件, 會提示有錯誤, 應爲該文件的SQL語句末尾少了分號,在批量執行時,MySQL報錯。需要在每一行SQL的末尾添加一個分號,這樣就可以用source命令導入了。
3. 配置Hibernate.cfg.xml
由於jBPM的數據庫持久化是依靠Hibernate進行的,因此需要配置Hibernate.cfg.xml使其適應我們的MySQL環境
<!-- hibernate dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/linly</property>
<property name="hibernate.connection.username">linly</property>
<property name="hibernate.connection.password">coffee</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
4. Import需要的jar包
這裏的jar包包括三部分:jbpm的核心包;Hibernate及其支撐包;MySQL的JDBC驅動包。
到此,我們的配置工作完成,這是實現jBPM流程部署服務端的最小化應用配置。
流程控制及API使用
樣例程序中的Handler接口實現
下面,根據上述的接口分類,列出樣例程序中的類名及相應的功能說明,具體可參考源代碼。
動作處理接口(ActioinHandler)
這裏要提到一個很重要的區別,就是作用於Node上的ActoinHandler和作用於Transition上的ActoinHandler是有不同的。區別在於,Node上的ActoinHandler在結束業務邏輯處理後,必須調用executionContext.leaveNode();或executionContext.leaveNode(transition)來保證流程向下執行;而作用於Transition上的則不需要。
判定處理接口(DecisionHandlder)
委派處理接口(AssignmentHandler)
流程測試剖析
本章節,我們將給大家剖析兩個流程測試類。一個是簡單的基於內存模型的流程測試FirstFlowProcessTest;一個是更貼近實用的,基於MySQL數據庫操作的標準測試案例。通過對這兩個測試例程的分析,來直觀的學習如何通過Java API操作jPDL。
簡單流程測試案例
測試案例類:FirstFlowProcessTest.java