19
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DroolsにInputStreamでExcelディシジョンテーブルを食わせる、他

Last updated at Posted at 2016-03-21

今回のテーマ

久しぶりに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

19
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?