今回のテーマ
久しぶりにDroolsを触ったら、3.0系の頃から現在の6.0系で、だいぶ変わっていたので、はまった所の解決策や新たな発見などの紹介です。
Droolsとは?
BRMS(Business Rule Management System)製品の一つ。JBoss Rulesのコミュニティ版として提供されているもの。
他のBRMS製品だと、IBM Operational Decision Managerとか。
Apacheソフトウェアライセンス2.0の下でリリースされたオープンソースのソフトウェア(Droolsのライセンス情報へのリンク)。
なので、商用利用の敷居が低い。
従来からビジネスルール(業務ロジックと言った方がしっくりするか)は、
そのアプリケーション内部にハードコーディングしていました(今もほとんどがそうしている)。
当然、そのアプリケーションが採用しているプログラミング言語でコーディングしているので、
ビジネスルールを提供する側(いわゆる業務側)からすると、そのコードを見せられても解りません。
BRMSっておいしいの?
__ビジネスルールの見える化__をしたいならお勧めかと。
例えば、プログラミング言語で記述されたビジネスルール(そのプログラミング言語のIF文で記述されたルール)よりは、
Excelで記述されたディシジョンテーブル形式のビジネスルールの方が解りやすいと思います。
Droolsでは、Excelでディシジョン形式のルールを記述し、それをルールエンジンで利用することができます(Droolsでは他にもグラフィカルに表現するツールを持っている)。
他にもうたい文句で、業務側自らで、ビジネスルールを変更できるので、仕様変更に柔軟に対応できるとか、ビジネスルールをホットデプロイできますよとかあります。
が、ろくにテストもしていないビジネスルールを、ホイホイとデプロイされたらたまったもんではないので、__見える化__がいいとこ。
(ビジネスルールのテスト環境を充実させれば、ありですが・・・)
他にもこんな機能を提供
- BRE(Business Rule Engine)、ビジネスルールエンジン。コア機能。
- Webオーサリングツール。
- ルール管理アプリケーション(Droolsのワークベンチ)。
- コア開発用のEclipse IDEのプラグイン。
本題
下記コード断片の全体は、次のGitHubを参照。PRJ_Drools
その1:ルールファイルをどうやってルールエンジンに読み込ませるか?
Drools3.Xの頃は、例えば、Excelで作ったディシジョンテーブル形式のルールやDRL(Drools Rule Language)形式は、
自前のjavaアプリケーションからInputStreamで読み込んで、ルールエンジンに与えていました。
それから、ルールエンジンに対するオプションやロガー等もDroolsが提供するAPIを通して設定をしていました。
今の6.0系では、mavenで扱いやすいようになっていて、ルールファイルは"src/main/resources"以下に置く模様。
オプションやロガー等は、"src/main/resources/META-INF/kmodule.xml"ファイルに記述する模様。
Drools6.xのKieScannerクラスを使うと、mavenリポジトリを監視して、新規のルールファイルのリリースが
あればそれをルールエンジンのKieContainerにデプロイしてくれる。
業務システムを構築するならば、こういった仕組みが必要なのも納得。
しかし、
- ちょいお試し
- Excelディシジョンテーブル形式の記述がうまく動かないので、途中でDRL形式に変換したをデバッグ出力。
- ルールファイルをプログラムの中で差し替え。
- プログラムで、ちょっと加工。
みたいなことをしたい時は、Drools APIでやりたいものです。
Drools APIを使えば、"kmodule.xml"ファイルが無くてもルールエンジンを動かす事ができます(GitHubのプロジェクトでは使っていません)。
ということで、いくつかコードの断片を。
InputStreamを使ってルールファイルを読む。
Droolsドキュメント
の「4.2.2.4. Defining a KieModule programmatically」を参考にしました。
Stack Overflow
の「Can't run hello world on drools - dlr files are not picked from classpath by KieContainer」を参考にしました。
InputStreamが使えるので、ファイルシステムから読むもよし、プログラムの中で動的にストリームを組み立てて読ませるもよし、色々できるようになります。
ポイントは、__"src/main/resources/"の部分。
ルールエンジンのメモリ配置が"src/main/resources/"__を前提にしています(mavenを前提にしているためかも)。
はじめ、これが解らず、物理ファイルシステムのパスを相対パスにしてみたり、絶対パスを書いてみたり、パス区切り文字を変えてみたり色々ためしてみましたが、最後、これに行きつきました。
// ルールファイルを読み込むInputStream
InputStream is = null;
try {
// ルールファイルのストリームを生成。
// DRL(Drools Rule Language)形式でもよいし、excelのディシジョンテーブル形式でもよい。
// drools-decisiontables.jarがクラスパスにないとexcelのディシジョンテーブルは読めません。
is = new FileInputStream(ruleFilePath);
// ルールエンジンのメモリファイルシステム上のデフォルトパスは"src/main/resources/"
kfs.write("src/main/resources/" + ruleFileName, kieServices.getResources().newInputStreamResource(is));
その2:Excelディシジョンテーブルで条件値に定数だけでなく、javaのコードが書ける!!!
今まで知らなったが、試しにやってみたらできた。前からできたのかも。
これまでは、ディシジョンテーブルの条件値をセルに書くときは、定数だけだと思っていましたが、
Javaのコードを書けることが分かりました。
ポイントは、ルールテンプレート部分の__「eval($param)」__の部分です。
eval関数の中を評価してくれます。eval関数でくくってあげないと、セルの中は__単なる文字列__として扱われてしまいます。
CONDITION |
---|
$pd:ProductDifference |
eval($param) |
許容範囲 |
Math.abs(afterProcduct.getHeight() - beforeProduct.getHeight()) < 1 |
Math.abs(afterProcduct.getHeight() - beforeProduct.getHeight()) >= 1 |
参考URL:
Chapter 5. The Rule Language