平田です。
Droolsでは、ルールの実行順序を制御する仕組みとしてルールフローが利用できます。
ルールフローを利用するための最小構成がどうなるか調べました。
依存ライブラリの指定
まず依存ライブラリをpom.xmlに指定します。
<dependency> <groupId>org.jbpm</groupId> <artifactId>jbpm-bpmn2</artifactId> <version>6.4.0.Final</version> </dependency>
ルールフローはBPMN2で記述しますが、 BPMN2に基づくフロー制御はjBPMを利用しています。このため、jbpm-bpmn2を指定します。
また、当然のことながらDroolsも使うので、kie-apiやdrools-compilerも指定する必要がありますが、jbpm-bpmn2の推移的依存性により指定しなくても動きます。ただし、アプリケーションの依存関係は明示的に指定する方が良いでしょう(jbpm-bpmn2の依存関係が変わると動かないため)。
ルールを使えるようにする
次に、ルールを使えるようにします。設定ファイルをsrc/main/resources/META-INF/kmodule.xmlとして保存します。
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> </kmodule>
何も指定していませんが、無いと動きません。
続いてルールファイルも用意します。今回はルールフローの動作確認用として、Stringオブジェクトにマッチして順次実行される三つのルールを作成しました。ruleflow-group属性を指定しているところがミソです。
package com.natswell.drools.playground.ruleflow;
rule "hop rule"
ruleflow-group "hop"
when
$str: String()
then
System.out.printf("hop: %s %n", $str);
end
rule "step rule"
ruleflow-group "step"
when
$str: String()
then
System.out.printf("step: %s %n", $str);
end
rule "jump rule"
ruleflow-group "jump"
when
$str: String()
then
System.out.printf("jump: %s %n", $str);
endルールフローを作成する
ルールフローを作成します。ルールフローを書くためのツールは複数用意されています。
一つ目はWorkbench (Red Hat JBoss BRMS / BPM SuiteではBusiness Central)と呼ばれるWebベースのオーサリング + 構成管理ツールです。ブラウザ上でルールやビジネスプロセスを定義し、さらに内蔵されたGitやMavenリポジトリで構成管理もできるツールですが、ルールフローを書きたいだけなのでオーバースペックです。
二つ目はEclipse公式のBPMNモデラーです。ツール自体は動くものの、ルールフローを実行するときに指定するプロセスIDをツール上から記入できませんでした (XMLを直接編集すればできますが…)。
三つ目はjBPM / Droolsプロジェクトで開発されたBPMN2プロセスエディタです。今回はこれを使いました。見た目は以下の様な図です。
BPMN2には様々なノードや属性が用意されていますが、基本的に開始ノード、終了ノードの間にルールタスクノードを並べて、以下の二つを指定します。
- プロセスID
- ルールタスクノードにおけるルールフローグループ(前述のルールで指定したruleflow-group属性と紐付きます)
BPMN2のXMLは、フローの構造を定義する情報(ノードと矢印など)の他に見た目の情報も入っています。このXMLを限界まで間引いた結果、以下の様なXMLでも動作しました。
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"> <process id="com.natswell.drools.playground.ruleflow.hello" > <startEvent id="start" name="start" isInterrupting="false" /> <businessRuleTask id="hop" name="hop" ruleFlowGroup="hop" /> <businessRuleTask id="step" name="step" ruleFlowGroup="step" /> <businessRuleTask id="jump" name="jump" ruleFlowGroup="jump" /> <endEvent id="end" name="end" /> <sequenceFlow id="start-hop" sourceRef="start" targetRef="hop" /> <sequenceFlow id="hop-step" sourceRef="hop" targetRef="step" /> <sequenceFlow id="step-jump" sourceRef="step" targetRef="jump" /> <sequenceFlow id="jump-end" sourceRef="jump" targetRef="end" /> </process> </definitions>
ルールフローを実行する
ルールフロー(というかjBPMのビジネスプロセス)を実行するには、Droolsでも使うKIE APIを使います。以下の様なコードで動きます。
public class MinimalRuleflowTest {
@Test public void helloRuleflow() {
KieSession ksession = KieServices.Factory.get().newKieClasspathContainer().newKieSession();
ProcessInstance proc = ksession.startProcess("com.natswell.drools.playground.ruleflow.hello");
assertThat(proc.getState(), is(ProcessInstance.STATE_ACTIVE));
ksession.insert("hello ruleflow.");
ksession.fireAllRules();
assertThat(proc.getState(), is(ProcessInstance.STATE_COMPLETED));
}
}実行すると、ルールで定義した標準出力がコンソールに出てきます。
08:27:33 ERROR [org.drools.core.xml.ExtensibleXmlParser] (main) (null: 2, 66): cvc-elt.1: 要素'definitions'の宣言が見つかりません。 hop: hello ruleflow. step: hello ruleflow. jump: hello ruleflow.
エラーが出ていますね。BPMN2を限界まで間引いたせいだと思います。プロセスエディタで書いたBPMN2ではこのエラーは出ません。
ということで、最小構成でルールフローを使うには以下が必要でした。
- 依存ライブラリ jbpm-bpmn2
- ルール設定ファイル + ルールファイル
- BPMN2ルールフロー(と、それを書くツール)
- 初期化コード
pom.xml src/main/resources/com/natswell/drools/playground/ruleflow/hello.bpmn src/main/resources/com/natswell/drools/playground/ruleflow/hello.drl src/main/resources/META-INF/kmodule.xml src/test/java/com/natswell/drools/playground/ruleflow/MinimalRuleflowTest.java
