DroolsでPPAP
Droolsって知っていますか?おそらく知っている方はかなり少ないのではないかと勝手に思っています。 Droolsとは、JBossが開発しているOSSのビジネスロジック統合プラットフォームです。簡単にはルールエンジンとして使えます。 ルールエンジンとは、ある特定のビジネスロジックをIF文のコードではなく表やツリーなどで表現し、入力に対してそれを適用することで期待する動作を行うためのプログラムのことです。 if-thenの条件定義がdrlファイルで設定でき、そのdrlファイルは表形式などのGUIで生成できるので、ビジネスロジックに関する意思決定者がエンジニアでなくても直接変更することができるところが魅力なのかなと思います。
今回はこのDroolsの紹介のためにPPAPブームにあやかることにしました。
正直PPAPとかよくわからないですがノリで良いんじゃないかと思います。深く考えたら負けです。
Droolsのアーキテクチャの説明から入るとかなりボリューミーで苦しい感じになるので
ここではDroolsでできることの基礎だけ載せます。あとDroolsではWorkbenchというアプリケーションが非常に重要なのですが、それも今回は触れないことにします。
なおPPAPの紹介はありませんが、このエントリによってDroolsでPPAPが理解できたら嬉しいです。たぶんできません。
DroolsでPPAP
まずmodelを用意します。
src/main/java/innossh/drools/ppap/model/Apple.java src/main/java/innossh/drools/ppap/model/Pen.java src/main/java/innossh/drools/ppap/model/Pineapple.java
public class Apple {
}
public class Pen {
}
public class Pineapple {
}
なんという手抜き。続いてruleを用意します。
メインのdrlファイルとkmodule.xmlという設定ファイルが必要になります。kmodule.xmlはルールを実行するためのsessionの定義などを行います。
src/main/resources/META-INF/kmodule.xml
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="PpapKBase" packages="PpapKBase">
<ksession name="PpapKBase.session" type="stateful" />
</kbase>
</kmodule>
src/main/resources/META-INF/PpapKBase/rules.drl
package innossh.drools.ppap;
import innossh.drools.ppap.model.Apple;
import innossh.drools.ppap.model.Pen;
import innossh.drools.ppap.model.Pineapple;
declare ApplePen
end
declare PineapplePen
end
rule "When you have a pen and an apple"
when
$pen : Pen()
$apple : Apple()
then
System.out.println("I have a pen");
System.out.println("I have an apple");
insert(new ApplePen());
System.out.println("Apple-pen!");
end
rule "When you have a pen and a pineapple"
when
$pen : Pen()
$pineapple : Pineapple()
then
System.out.println("I have a pen");
System.out.println("I have a pineapple");
insert(new PineapplePen());
System.out.println("Pineapple-pen!");
end
rule "When you have an applepen and a pineapplepen"
when
$applePen : ApplePen()
$pineapplePen : PineapplePen()
then
System.out.println("Apple-pen...");
System.out.println("Pineapple-pen...");
System.out.println("Pen-Pineapple-Apple-Pen!");
end
drlファイルには複数のルールを定義することが可能で、互いのルールが依存関係にある場合にはよしなに解釈してくれます。
またApplePenクラスやPineapplePenクラスはmodelとして作りませんでしたが、drlファイル内で declare ~ として定義することができます。
あとはこのルールを実行するメインクラスもしくはテストクラスを作りましょう。
src/test/java/innossh/drools/ppap/PpapTest.java
package innossh.drools.ppap;
import innossh.drools.ppap.model.Apple;
import innossh.drools.ppap.model.Pen;
import innossh.drools.ppap.model.Pineapple;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import static org.junit.Assert.assertEquals;
public class PpapTest {
@Test
public void testPpap() {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("PpapKBase.session");
Pen pen = new Pen();
Apple apple = new Apple();
Pineapple pineapple = new Pineapple();
kieSession.insert(pen);
kieSession.insert(apple);
kieSession.insert(pineapple);
int rules = kieSession.fireAllRules();
assertEquals(3, rules);
}
}
まず疑問に思うのが KIE ってなんぞ? kmodule も k が付いていたし。というところですよね。
これはKnowledge is Everythingの略らしく、Droolsよりも広いJBossのオープンソースプロジェクトの名前らしいです。KIEプロジェクトの中にDroolsやその他のオープンソースプロダクトが含まれているイメージでしょうか。そのため各種ライブラリにkieという名前が付いているようです。
実行の流れはsessionを作成しそこにpen, apple, pineappleを追加してあげてruleをfireするといった具合です。
実行結果は...
I have a pen I have an apple Apple-pen! I have a pen I have a pineapple Pineapple-pen! Apple-pen... Pineapple-pen... Pen-Pineapple-Apple-Pen!
はい。おもしろいでしょうか!その答えはPPAPにあるでしょう。
...
とってもシンプルなコードをわざわざちゃんと読んだ人は気づいたかもしれませんが、ペンパイナッポーアッポーペンにはペンが2つ必要になるはずなのに、
sessionへの入力には1つのペンしか使用していませんね。
入力された要素はDroolsではFactと呼ぶのですが、このFactは全てのルールに与えられます。そのためペンが1つでもルールの条件が成立し意図した結果が得られます。
ちなみにDroolsのルールの実行回数はなかなか制御が難しいところで、簡単に無限ループを発生させるルールを書いてしまいます。気を使う必要があるのでDroolsを使ったからといって簡単にエンジニアの手から離れることはなさそうだなと思いました。
余談
Droolsの情報はかなり少ないです。公式ドキュメントはキャプチャが古いしリンク切れも多いし、ググればGoogle Groupsのやり取りばかりがヒットし、StackOverFlowやJIRAでは質問は見つかれどだれもコメントをしていないなど、精神的につらいです。なのでDroolsのエントリがどなたかの手助けになれば幸いです。Droolsについてもっと書かなくては。
情報少ないのにコミュニティとしてはアクティブにも見えるし次期バージョンのbetaも公開されているので、ユーザがいるのかいないのか謎に包まれているのですが、
個人的な見解ではエンタープライズ版は使われていて、その運用はJBossのエンジニアがやっているから特に外部に情報も少なく、OSS版であるDroolsはオープンソースになっていることに意義があるだけで実際のユーザは少ないのではないか、と予想しています。間違っていたらJBossの方々ごめんなさいね。