jBPM 是一個非常優秀的開源工作流引擎
雖然他不是一個一站式的工作流平台
不過它已經為我們提供了比較豐富的底層操作
為了滿足特定的項目需求
我們一般需要對其進行二次開發
才能適用於具體的業務需求
其中一個主要的擴展點是針對 TaskNode 進行的用戶的分配
TaskNode 是 jBPM 中一個非常重要的概念
一個任務節點可以包含若干個任務
不同的任務可以由不同的人來完成
任務實例被分配給 actorId 來完成
其中指定到人的分配工作就是 Assignment 要處理的
這也是我們需要定制的功能
為了實現用戶的分配
我們需要實現 AssignmentHandler 接口
接口原型如下
public interface AssignmentHandler extends Serializable {
void assign(Assignable assignable
ExecutionContext executionContext) throws Exception;
}
通常用代碼實現的話
我們可以讓一個類實現這個接口
並在 swimlane 或者 tasknode 中的 assignment 指定該類
但是
這樣的靈活性是顯然不夠的
在系統的使用過程中
分配策略會不斷的進行調整
因此我們需要更為靈活的解決方案
jBPM 本身可以使用基於 Bean Shell 的腳本來寫分配策略
但是 Bean Shell 不是那麼強大
我們需要更為強大的解決方案
因此
我們選用了已經被 JBoss 收為旗下的 JBoss Drools
規則引擎 (在
的時候曾經改名為 JBoss Rules
又改回來了)
jBPM 和 Drools 雖然同在 JBoss 旗下
不過他們目前並沒有很好的進行整合
所以我們還是要利用它們系統系統的一些功能來做整合
同樣也是實現 AssignmentHandler 接口
不過另外我們利用了 jBPM 裡面的一個小小的技巧
看一下這段配置
AgentAssignmentRule 紅色標注的這段配置
我們可以理解為
在 RulesAssignmentHandler 這個類裡有一個 ruleName 這樣的屬性
在初始化這個類的時候
jBPM 會把配置中 ruleName 的值 set 給 RulesAssignmentHandler 中 ruleName 的屬性
public class RulesAssignmentHandler implements AssignmentHandler {
protected String ruleName;
public String getRuleName() {
return ruleName;
}
public void setRuleName(String ruleName) {
this
ruleName = ruleName;
}
protected RuleBase readRule(String ruleName) throws Exception {
// 到 classes 下的 /rules 下加載相應的文件
String rulePath =
/rules/
+ ruleName +
drl
;
Resource resource = new ClassPathResource(rulePath);
Reader reader = new InputStreamReader(resource
getInputStream());
PackageBuilder builder = new PackageBuilder();
builder
addPackageFromDrl(reader);
Package pkg = builder
getPackage();
RuleBase ruleBase = RuleBaseFactory
newRuleBase();
ruleBase
addPackage(pkg);
return ruleBase;
}
protected void initRuleContextData(ExecutionContext executionContext
WorkingMemory workingMemory) {
ContextInstance ci = executionContext
getContextInstance();
Map vars = ci
getVariables();
workingMemory
insert(ci);
workingMemory
insert(vars);
}
public void assign(Assignable assignable
ExecutionContext executionContext) throws Exception {
RuleBase ruleBase = readRule(ruleName);
WorkingMemory workingMemory = ruleBase
newStatefulSession();
// 為了簡便操作
我只是拿了放入 ExecuteContext 中的 variable 進行邏輯處理
initRuleContextData(executionContext
workingMemory);
workingMemory
insert(assignable);
workingMemory
fireAllRules();
}
}
對應的 AgentAssignmentRule
drl 文件內容如下
假定 ExecutionContext 中有 price 這個 variable
我們判定當這個值 >
的時候
我們將此任務分配給 senior_agent 來處理
package org
agilejava
workflow
import java
util
Map
import org
jbpm
taskmgmt
exe
Assignable
rule
Assign Agent
when
a : Assignable()
Map(this[
price
] >=
)
then
a
setActorId(
senior_agent
);
end
就這樣
我們就完成了最為簡單的 jBPM 和 Drools 的整合
當然這種方式只是簡單的利用了 jBPM 的一些特性來做的
我們每次都得指定這個 RulesAssignmentHandler
還是很麻煩的
更好的方式就是我們改寫 ProcessDefinition
xml 的 parser
讓 Drools 的規則定義成為和 swimlane
actor
id
expression 這樣的分配方式同樣級別的
讓 Drools 成為 jBPM 的一等公民
這個以後研究好了再來和大家分享
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28609.html