平田です。
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