第2章 KIE セッション
Red Hat Decision Manager では、KIE セッションはランタイムデータを保存して実行します。KIE セッションは KIE ベースから作成されるか、またはプロジェクトの KIE モジュール記述子ファイル (kmodule.xml) で KIE セッションを定義している場合は、KIE コンテナーから直接作成されます。
kmodule.xml ファイルの KIE セッション設定例
<kmodule>
...
<kbase>
...
<ksession name="KSession2_1" type="stateless" default="true" clockType="realtime">
...
</kbase>
...
</kmodule>
KIE ベースは、プロジェクトの KIE モジュール記述子ファイル (kmodule.xml) で定義するリポジトリーで、Red Hat Decision Manager のすべてのルールおよびその他のビジネスアセットが含まれていますが、ランタイムのデータは一切含まれていません。
kmodule.xml ファイルの KIE ベース設定例
<kmodule>
...
<kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">
...
</kbase>
...
</kmodule>
KIE セッションは、ステートレスでも、ステートフルでも可能です。ステートレスな KIE セッションでは、KIE セッションの以前の呼び出し (以前のセッション状態) からのデータは、次のセッションの呼び出しまでに破棄されます。ステートフルな KIE セッションでは、そのデータは保持されます。使用する KIE セッションのタイプは、プロジェクトの要件と、さまざまなアセット呼び出しからのデータをどのように維持するかにより決まります。
2.1. ステートレスな KIE セッション
ステートレスな KIE セッションは、推論を使用せずに、時間の経過とともにファクトを繰り返し変更していくセッションです。ステートレスな KIE セッションでは、KIE セッションの以前の呼び出し (以前のセッション状態) からのデータはセッションの呼び出し間で破棄されますが、ステートフルな KIE セッションではそのデータは保持されます。ステートレスな KIE セッションは、生成する結果が KIE ベースのコンテンツと、特定の時点で実行するために KIE セッションに渡されるデータによって決定されるという点で、関数と同様に動作します。KIE セッションには、以前に KIE セッションに渡されたデータのメモリーはありません。
以下のユースケースで、ステートレスな KIE セッションは一般的に使用されます。
- 検証 (住宅ローンの対象となるかを検証するなど)
- 計算 (住宅ローンのプレミアムの計算など)
- ルーティングとフィルターリング (受信した電子メールをフォルダーにソートしたり、受信した電子メールを送信先に送信したりすることなど)
たとえば、以下の運転免許のデータモデルおよび DRL ルールのサンプルをご覧ください。
運転免許申請のデータモデル
public class Applicant {
private String name;
private int age;
private boolean valid;
// Getter and setter methods
}
運転免許申請の DRL ルールのサンプル
package com.company.license rule "Is of valid age" when $a : Applicant(age < 18) then $a.setValid(false); end
Is of valid age ルールは、18 歳未満の申請者全員を失格にします。Applicant オブジェクトがデシジョンエンジンに挿入されると、デシジョンエンジンは各ルールの制約を評価し、一致するものを探します。"objectType" 制約は常に暗黙的で、その後に明示的なフィールド制約の任意の数が評価されます。変数 $a は、ルール結果で一致したオブジェクトを参照するバインディング変数です。
ドル記号 ($) はオプションで、変数名とフィールド名を識別する上で役立ちます。
この例では、ルールのサンプルと Red Hat Decision Manager プロジェクトの ~/resources フォルダー内の他のすべてのファイルは、以下のコードで構築されます。
KIE コンテナーの作成
KieServices kieServices = KieServices.Factory.get(); KieContainer kContainer = kieServices.getKieClasspathContainer();
このコードは、クラスパスで見つかったすべてのルールファイルをコンパイルし、このコンパイルの結果である KieModule オブジェクトを KieContainer に追加します。
最後に、StatelessKieSession オブジェクトが KieContainer からインスタンス化され、指定したデータに対して実行されます。
ステートレスな KIE セッションをインスタンス化し、データを入力
StatelessKieSession kSession = kContainer.newStatelessKieSession();
Applicant applicant = new Applicant("Mr John Smith", 16);
assertTrue(applicant.isValid());
ksession.execute(applicant);
assertFalse(applicant.isValid());
ステートレスな KIE セッションの設定では、execute() の呼び出しは KieSession オブジェクトをインスタンス化するコンビネーションメソッドとして機能し、すべてのユーザーデータを追加してユーザーコマンドを実行し、fireAllRules() を呼び出してから、dispose() を呼び出します。したがって、ステートレスな KIE セッションでは、ステートフルな KIE セッションの時のようにセッションの呼び出し後に fireAllRules() または dispose() を呼び出す必要はありません。
この場合、指定された申請者は 18 歳未満であるため、申請は拒否されます。
より複雑なユースケースについては、以下の例を参照してください。この例では、ステートレスな KIE セッションを使用し、コレクションなどの反復可能なオブジェクトのリストに対してルールを実行します。
運転免許申請の拡張データモデル
public class Applicant {
private String name;
private int age;
// Getter and setter methods
}
public class Application {
private Date dateApplied;
private boolean valid;
// Getter and setter methods
}
運転免許申請の拡張 DRL ルールセット
package com.company.license rule "Is of valid age" when Applicant(age < 18) $a : Application() then $a.setValid(false); end rule "Application was made this year" when $a : Application(dateApplied > "01-jan-2009") then $a.setValid(false); end
ステートレスな KIE セッションで実行が反復可能な拡張 Java ソース
StatelessKieSession ksession = kbase.newStatelessKnowledgeSession();
Applicant applicant = new Applicant("Mr John Smith", 16);
Application application = new Application();
assertTrue(application.isValid());
ksession.execute(Arrays.asList(new Object[] { application, applicant })); 1
assertFalse(application.isValid());
ksession.execute
(CommandFactory.newInsertIterable(new Object[] { application, applicant })); 2
List<Command> cmds = new ArrayList<Command>(); 3
cmds.add(CommandFactory.newInsert(new Person("Mr John Smith"), "mrSmith"));
cmds.add(CommandFactory.newInsert(new Person("Mr John Doe"), "mrDoe"));
BatchExecutionResults results = ksession.execute(CommandFactory.newBatchExecution(cmds));
assertEquals(new Person("Mr John Smith"), results.getValue("mrSmith"));
- 1
Arrays.asList()メソッドによって生成されたオブジェクトの反復可能なコレクションに対してルールを実行するメソッド。すべてのコレクション要素は、一致したルールが実行される前に挿入されます。execute(Object object)およびexecute(Iterable objects)メソッドは、BatchExecutorインターフェイスから派生したexecute(Command command)メソッドを包むラッパーです。- 2
CommandFactoryインターフェイスを使用したオブジェクトの反復可能なコレクションの実行。- 3
- 多くのさまざまなコマンドまたは結果出力識別子と作業するための
BatchExecutorおよびCommandFactory設定。CommandFactoryインターフェイスは、StartProcess、Query、SetGlobalなど、BatchExecutorで使用できる他のコマンドをサポートしています。
2.1.1. ステートレスな KIE セッションのグローバル変数
StatelessKieSession オブジェクトは、セッションスコープのグローバル、デリゲートグローバル、または実行スコープのグローバルとして解決されるように設定できるグローバル変数 (グローバル) をサポートしています。
セッションスコープのグローバル: セッションスコープのグローバルの場合は、
getGlobals()メソッドを使用して、KIE セッショングローバルへのアクセスを提供するGlobalsインスタンスを返すことができます。これらのグローバルは、すべての実行呼び出しに使用されます。実行呼び出しは異なるスレッドで同時に実行する可能性があるため、可変グローバルには注意が必要です。セッションスコープのグローバル
import org.kie.api.runtime.StatelessKieSession; StatelessKieSession ksession = kbase.newStatelessKieSession(); // Set a global `myGlobal` that can be used in the rules. ksession.setGlobal("myGlobal", "I am a global"); // Execute while resolving the `myGlobal` identifier. ksession.execute(collection);-
デリゲートグローバル: デリゲートグローバルの場合は、識別子を値にマップする内部コレクションに値を保存できるように、(
setGlobal(String, Object)を使用して) 値をグローバルに割り当てることができます。この内部コレクションの識別子は、すべての提供されるデリゲートの中で優先されます。この内部コレクションで識別子が見つからない場合に、デリゲートグローバルが (もしあれば) 使用されます。 -
実行スコープのグローバル: 実行スコープのグローバルの場合は、
Commandオブジェクトを使用して、実行特有のグローバル解決用にCommandExecutorインターフェイスに渡されるグローバルを設定できます。
CommandExecutor インターフェイスでは、グローバル、挿入されたファクト、およびクエリー結果の out identifier を使用してデータをエクスポートすることもできます。
グローバル、挿入されたファクト、およびクエリー結果の out identifier
import org.kie.api.runtime.ExecutionResults;
// Set up a list of commands.
List cmds = new ArrayList();
cmds.add(CommandFactory.newSetGlobal("list1", new ArrayList(), true));
cmds.add(CommandFactory.newInsert(new Person("jon", 102), "person"));
cmds.add(CommandFactory.newQuery("Get People" "getPeople"));
// Execute the list.
ExecutionResults results = ksession.execute(CommandFactory.newBatchExecution(cmds));
// Retrieve the `ArrayList`.
results.getValue("list1");
// Retrieve the inserted `Person` fact.
results.getValue("person");
// Retrieve the query as a `QueryResults` instance.
results.getValue("Get People");