81.2. ステートフルな KIE セッション

ステートフルな KIE セッションは、推論を使用して、時間の経過とともにファクトを繰り返し変更していくセッションです。ステートフルな KIE セッションでは、KIE セッションの以前の呼び出し (以前のセッション状態) からのデータは、セッションの呼び出し間で保持されますが、ステートレスな KIE セッションではそのデータは破棄されます。

警告

ステートフルな KIE セッションの実行後に dispose() メソッドを呼び出して、セッションの呼び出し間でメモリーリークが発生しないようにしてください。

以下のユースケースで、ステートフルな KIE セッションは一般的に使用されます。

  • 監視 (株式市場の監視や購入プロセスの自動化など)
  • 診断 (不具合検出プロセスまたは医療診断プロセスの実行など)
  • ロジスティックス (荷物の追跡や配達のプロビジョニングなど)
  • コンプライアンスの確保 (市場取引における合法性の検証など)

たとえば、以下の火災報知機のデータモデルと DRL ルールのサンプルをご覧ください。

スプリンクラーと火災報知機のデータモデル

public class Room {
  private String name;
  // Getter and setter methods
}

public class Sprinkler {
  private Room room;
  private boolean on;
  // Getter and setter methods
}

public class Fire {
  private Room room;
  // Getter and setter methods
}

public class Alarm { }

スプリンクラーとアラームを有効にするための DRL ルールセットのサンプル

rule "When there is a fire turn on the sprinkler"
when
  Fire($room : room)
  $sprinkler : Sprinkler(room == $room, on == false)
then
  modify($sprinkler) { setOn(true) };
  System.out.println("Turn on the sprinkler for room "+$room.getName());
end

rule "Raise the alarm when we have one or more fires"
when
    exists Fire()
then
    insert( new Alarm() );
    System.out.println( "Raise the alarm" );
end

rule "Cancel the alarm when all the fires have gone"
when
    not Fire()
    $alarm : Alarm()
then
    delete( $alarm );
    System.out.println( "Cancel the alarm" );
end


rule "Status output when things are ok"
when
    not Alarm()
    not Sprinkler( on == true )
then
    System.out.println( "Everything is ok" );
end

When there is a fire turn on the sprinkler ルールの場合は、火災が発生すると、その部屋に対して Fire クラスのインスタンスが作成され、KIE セッションに挿入されます。このルールは、Fire インスタンスに一致する特定の room に制約を追加し、その部屋のスプリンクラーのみがチェックされるようにします。このルールが実行すると、スプリンクラーが有効になります。他のルールのサンプルは、これに基づいてアラームをいつ有効または無効にするかを決定します。

ステートレスな KIE セッションは、標準的な Java 構文に依存してフィールドを変更しますが、ステートフルな KIE セッションはルールの modify ステートメントに依存して、変更をデシジョンエンジンに通知します。次に、デシジョンエンジンが変更を判断し、後続のルール実行への影響を評価します。このプロセスは、推論 および 真理維持 を使用するデシジョンエンジンの機能の一部であり、ステートフルな KIE セッションでは不可欠となります。

この例では、ルールのサンプルと Red Hat Process Automation Manager プロジェクトの ~/resources ディレクトリー内の他のすべてのファイルは、以下のコードで構築されます。

KIE コンテナーの作成

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

このコードは、クラスパスで見つかったすべてのルールファイルをコンパイルし、このコンパイルの結果である KieModule オブジェクトを KieContainer に追加します。

最後に、KieSession オブジェクトが KieContainer からインスタンス化され、指定したデータに対して実行されます。

ステートフルな KIE セッションをインスタンス化してデータを入力

KieSession ksession = kContainer.newKieSession();

String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
Map<String,Room> name2room = new HashMap<String,Room>();
for( String name: names ){
    Room room = new Room( name );
    name2room.put( name, room );
    ksession.insert( room );
    Sprinkler sprinkler = new Sprinkler( room );
    ksession.insert( sprinkler );
}

ksession.fireAllRules();

コンソールの出力

> Everything is ok

データが追加されると、デシジョンエンジンはすべてのパターン一致を完了しますが、ルールは実行されていないため、設定済みの検証メッセージが表示されます。新しいデータがルール条件をトリガーすると、デシジョンエンジンはルールを実行してアラームを有効にし、後で有効になったアラームをキャンセルします。

新しいデータを入力してルールをトリガー

Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
Fire officeFire = new Fire( name2room.get( "office" ) );

FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
FactHandle officeFireHandle = ksession.insert( officeFire );

ksession.fireAllRules();

コンソールの出力

> Raise the alarm
> Turn on the sprinkler for room kitchen
> Turn on the sprinkler for room office

ksession.delete( kitchenFireHandle );
ksession.delete( officeFireHandle );

ksession.fireAllRules();

コンソールの出力

> Cancel the alarm
> Turn off the sprinkler for room office
> Turn off the sprinkler for room kitchen
> Everything is ok

この場合は、返された FactHandle オブジェクトの参照が保持されます。ファクトハンドルは、挿入されたインスタンスへの内部エンジン参照であり、後でインスタンスを撤回または変更できるようにします。

この例が示すように、以前のステートフルな KIE セッションのデータと結果 (有効化されたアラーム) は、後続のセッションの呼び出し (アラームのキャンセル) に影響します。