コラム/第6回 デモアプリケーションを使って JBoss BRMS を理解する ~ルールフロー~

Hitachi Solutions

2015年4月3日

第6回 デモアプリケーションを使って JBoss BRMS を理解する ~ルールフロー~

Red Hat JBoss Middleware

前回の「第5回 デモアプリケーションを使って JBoss BRMS を理解する」では、Coolstore デモの一つのルールについて見てきました。Coolstore デモはルールをグループ化し、順番に評価する仕組み(ルールフロー)が使われています。今回は、ルールフローについてご紹介していきます。

ルールフローとルールフローグループ

JBoss BRMS ではビジネスルールをフローに従って評価することができます。ルールフローをBPMN2.0の記法を用いて定義し、ビジネスルールタスクでルールフローグループ(複数のルールをグループ化した単位)を指定して呼び出すことで、この機能を実現します。 ここで注意したいポイントは、if-then-else のように前後の処理に依存する手続き型のフローではないという点です。 それぞれのルールは独立しており、同一のルールフローグループに属する他のルールや、前後のフローで実行されるルールには依存しません。

図 1 ルールフロー

図 1 ルールフロー

ルールエンジンの内部構造

ルールフローの処理を見て行く前に、ルールエンジンの内部構造を簡単にご紹介します。

図 2 ルールエンジンの内部構造

図 2 ルールエンジンの内部構造

ファクト ルールで評価する対象となるインスタンス。 Coolstoreデモではショッピングカートや購入アイテムに該当
アジェンダ ルールとファクトをマッチングした結果を保持する領域
アクティベーション ルールとファクトのマッチング結果(評価は未実施)。アクティベーションの評価はファクトのinsert() / update() / retract() が呼ばれたタイミングで実行される

insert() / update() / retract()は、ワーキングメモリ上のファクトを操作するためのメソッドで引数にファクトのインスタンスを指定します。これらのメソッドを呼ぶことにより、ワーキングメモリ、アジェンダの状態が変化します。

insert() insert()により、ファクトがワーキングメモリに投入されると、ルールエンジンはファクトとルールのマッチングを行う
update() update()により、引数で指定したファクトに関連づけられたアジェンダが実行(ルールが評価)され、ファクトの状態が更新される
retract() retract()により、ファクトがワーキングメモリから削除されるとともに、削除されたファクトに関連づけられたアクティベーションも削除される

ルールフロー

ルールを順次評価するためのフローをBPMN2.0形式で定義します。ビジネスルールタスクが呼ばれる毎にルールが実行されませんので、ビジネスルールタスク毎にルールを実行させる場合は、明示的に update() 関数を呼び出してルールを実行させる必要があります。

図 3 ルールの評価と実行

図 3 ルールの評価と実行

ルールフローグループ

ルールフローグループは、複数のルールに同じラベルをつけてグループ単位でルールの評価と実行をする場合に利用します。ルールフローの各ビジネスルールタスクからルールフローグループを指定してルールの評価と実行を行います。

DRL でのruleflow-groupの定義


rule "Apply Cart Item Promotions"
    no-loop true
    ruleflow-group "promo-cart-rules"
    dialect "mvel"
    when
        $sci : ShoppingCartItem( $itemId : itemId)
        PromoEvent( itemId == $itemId && $pctOff : percentOff) from entry-point "Promo Stream"
    then
        $sci.setPromoSavings( $sci.price * $pctOff );
        update( $sci );
        $sci.setPrice( $sci.price * (1 - $pctOff) );
        update( $sci );
end

※JBoss BRMS 6 からRuleFlowGroup と AgendaGroup が統合されました。 プログラムからは次のように指定してルールフローグループ/アジェンダグループを実行することができます。

KieSession session;
// 中 略
session.getAgenda().getAgendaGroup("promo-cart-rule").setFocus();
session.fireAllRules();

ルールフローでのルールの評価と実行の仕組み

例えば、次のような2つのルールを実行するルールフローを考えてみましょう。

ルールA
  ruleflow-group="group-1"
  条件 : Itemがカートに登録されている
  アクション : 数量を10に更新する
ルールB
  ruleflow-group="group-2"
  条件 : Itemがカートに登録されている かつ 数量>5
  アクション : 10%値引きする

ビジネルスールタスクから評価されるルールが明示的にupdate()をしていない場合は、ビジネスルールタスクを実行する毎にアジェンダにルールとファクトの組み合わせが登録されますが、ルールは実行されません。 ルールフローの最後にアジェンダに登録されたファクトとルールの組み合わせに従ってルールが実行されます。

図 4 ルールフローの動作(updateしない場合)

図 4 ルールフローの動作(updateしない場合)

ビジネスルールタスクで評価されるルールが明示的に update() をしている場合は、ビジネスルールタスクを実行する毎にアジェンダにルールとファクトの組み合わせが登録されます。update()の実行によりアジェンダに登録されたルールとファクトの組み合わせに従ってルールが実行され、ワーキングメモリ上のファクトが更新されます。

図 5 ルールフローの動作(updateする場合)

図 5 ルールフローの動作(updateする場合)

Coolstoreデモのルールフロー

Coolstoreデモのルールフローは、次のような処理の流れになっています。 それぞれの商品の値引や送料が決まらなければ合計金額を算出できませんので、ルールフローの特徴が活かされています。

  1. カートに登録した商品の値引きを計算
  2. カートに登録した商品の合計金額を計算
  3. 送料を計算
  4. 送料の値引きを計算
  5. 商品代金、送料を含む合計時間を計算

Coolstoreデモでは、PriceProcess.bpmn2 でルールフローが定義されており、 brms-coolstore-demo/projects/brms-coolstore-demo/src/main/java/com/redhat/coolstore/service/ShoppingCartServiceImplBRMS.java でアプリケーションからルールフローが呼ばれていますので、これらのプログラムを参考にしてみてください。

最後に

今回はルールフローについてみていきました。ルールのグループ化は、ルールフローからの利用以外でも有効な方法です。BRMS を利用する場合には、ルールのグループ化やルールフローなども考慮して設計すると良いでしょう。

著者紹介

レッドハット株式会社
JBossサービス事業部
ソリューションアーキテクト 大溝 桂 様

サン・マイクロシステムズにてC言語/Java言語を利用した基幹業務システムの開発などを経験後、2012年にレッドハット株式会社に入社。パートナを担当するプリセールスエンジニアとして、JBoss Middlewareの拡販とパートナ企業の技術者育成に従事。

Red Hat コンテンツ一覧

関連商品・キーワード