第6章 Java ルールエンジンアプリケーションプログラミングインターフェース

6.1. はじめに

JBoss Rules は、JSR94 の実装である Java rule engine アプリケーションプログラミングインターフェース (API) を提供します。複数のルールエンジンをこの単一の API で実行することができます。本章を読んで、この API の機能について詳しく学びましょう。

注記

JSR94 はルール言語自体とは全く対話しません。
ルールエンジン全体の機能としては、JSR94 標準は「最小公分母」を表すことに注意してください。そのため、JSR94 API の機能は標準の JBoss Rules API の機能よりも少なくなります。そのため、JSR94 を使用すると JBoss Rulesrule engine によって提供される機能の一部が無効になります。
完全な機能 (globalsDRLDSLXML ファイルなど) へアクセスするには、property maps を使用します。これにより、移植不可能な機能が導入されることに注意してください。さらに、JSR94 はルール言語を提供しないため、ルールエンジンを切り替えても複雑さはほとんど解消されません。よって、ほとんど利点がありません。そのため、JSR94 の使用が要求される場合に Red Hat はサポートを行いますが、プログラマーは JBoss Rules API を使用することが強く推奨されます。

6.2. API の使用方法

JSR94 は 2 つの部分で構成されます。1 つ目は Administrative API で、RuleExecutionSets のビルドおよび登録に使用されます。2 つ目は run-time session で、同じ RuleExecutionSets を実行します。

6.2.1. RuleExecutionSets のビルドと登録

RuleServiceProviderManagerRuleExecutionSets の登録と読み出しを管理します。JBoss Rules RuleServiceProvider 実装は、Class.forNamem を使用してクラスがロードされた時に 静的ブロック によって自動的に登録されます (これは JDBC ドライバーとほぼ同様です)。

例6.1 RuleServiceProvider の自動登録

// RuleServiceProviderImpl is registered to "http://drools.org/"
// via a static initialization block
Class.forName("org.drools.jsr94.rules.RuleServiceProviderImpl");

// Get the rule service provider from the provider manager.
RuleServiceProvider ruleServiceProvider =
  RuleServiceProviderManager.getRuleServiceProvider("http://drools.org/");
RuleServiceProvider は、RuleRuntime および RuleAdministration API へのアクセスを提供します。RuleAdministration は、RuleExecutionSets を管理するための管理 API を提供します。これにより、RuleRuntime より読み出しできる RuleExecutionSet の登録が可能になります。
RuleExecutionSet を作成し登録するには、次の手順に従います。
  1. RuleExecutionSet を作成します。RuleAdministrator は、空の LocalRuleExecutionSetProvider または RuleExecutionSetProvider を返すファクトリメソッドを提供します。
  2. LocalRuleExecutionSetProvider を使用して、stream などのローカルのシリアライズ不可能なソースより LocalRuleExecutionSetProvider をロードします。
    RuleExecutionSetProvider を使用して、DOM 要素やナレッジパッケージなどのシリアライズ可能なソースより RuleExecutionSets をロードできます。

注記

ruleAdministrator.getLocalRuleExecutionSetProvider( null ); および ruleAdministrator.getRuleExecutionSetProvider( null ); メソッドは両方 null をパラメーターとして許可します。これは、これらのメソッドの properties map は現在使用されていないからです。

例6.2 RuleAdministrator API を用いた LocalRuleExecutionSet の登録

// Get the RuleAdministration 
RuleAdministrator ruleAdministrator = ruleServiceProvider.getRuleAdministrator();
LocalRuleExecutionSetProvider ruleExecutionSetProvider =
  ruleAdministrator.getLocalRuleExecutionSetProvider( null );

// Create a Reader for the drl
URL drlUrl = new URL("http://mydomain.org/sources/myrules.drl");
Reader drlReader = new InputStreamReader(  drlUrl.openStream()  );

// Create the RuleExecutionSet for the drl
RuleExecutionSet ruleExecutionSet =
  ruleExecutionSetProvider.createRuleExecutionSet( drlReader, null );
上記の例では、ruleExecutionSetProvider.createRuleExecutionSet( reader, null )properties map に対して null のパラメーターを取ります (しかし、実際は受信ソースの設定情報を提供するために使用されます)。null が渡されると、DRL ファイルより入力をロードするためデフォルトが使用されます。マップに使用できるキーは sourcedsl です。sourcedrl または xml を値として取ります。sourcedrl に設定して DRL ファイルをロードします。また同様に、sourcexml に設定して XML ファイルをロードします (xmldsl のキーと値の設定をすべて無視します) 。dsl キーは reader または string (ドメイン固有言語の内容) を値として使用します。

例6.3 LocalRuleExecutionSet の登録時におけるドメイン固有言語の指定

// Get the RuleAdministration 
RuleAdministration ruleAdministrator = ruleServiceProvider.getRuleAdministrator();
LocalRuleExecutionSetProvider ruleExecutionSetProvider =
  ruleAdministrator.getLocalRuleExecutionSetProvider( null );

// Create a Reader for the drl
URL drlUrl = new URL("http://mydomain.org/sources/myrules.drl");
Reader drlReader = new InputStreamReader(  drlUrl.openStream()  );

// Create a Reader for the dsl and a put in the properties map
URL dslUrl = new URL("http://mydomain.org/sources/myrules.dsl");
Reader dslReader = new InputStreamReader( dslUrl.openStream()  );
Map properties = new HashMap();
properties.put( "source", "drl" );
properties.put( "dsl", dslReader );

// Create the RuleExecutionSet for the drl and dsl
RuleExecutionSet ruleExecutionSet =
  ruleExecutionSetProvider.createRuleExecutionSet( reader, properties );

重要

RuleExecutionSet を読み出すために使用する名前は、登録時に指定する必要があります (プロパティーを渡せるようにするためのフィールドもありますが、現在使用されていないため、null を渡します)。

例6.4 RuleExecutionSet の登録

// Register the RuleExecutionSet with the RuleAdministrator
String uri = ruleExecutionSet.getName();
ruleAdministrator.registerRuleExecutionSet(uri, ruleExecutionSet, null);

6.2.2. 「ステートフル」および「ステートレス」ルールセッションの使用

run-timeRuleServiceProvider より取得できます。これは、ステートフル および ステートレス rule engine セッションを作成するために使用されます。

例6.5 RuleRunTime の取得

RuleRuntime ruleRuntime = ruleServiceProvider.getRuleRuntime();
ルールセッション を作成するには、次の手順に従います。
  1. RuleRuntime の 2 つのパブリック定数である RuleRuntime.STATEFUL_SESSION_TYPE および RuleRuntime.STATELESS_SESSION_TYPE のいずれかを使用します。
  2. RuleSession をインスタンス化するために使用される RuleExecutionSet の URI (Uniform Resource Indicator) を提供します。
  3. properties mapnull に設定するか、properties map を使用してグローバルを指定します (次項に記載されています)。
  4. createRuleSession(....) メソッドは RuleSession インスタンスを返します。これを StatefulRuleSession または StatelessRuleSession へキャストします。

例6.6 ステートフルルール

(StatefulRuleSession) session =
  ruleRuntime.createRuleSession( uri,
                                 null,
                                 RuleRuntime.STATEFUL_SESSION_TYPE );
session.addObject( new PurchaseOrder( "lots of cheese" ) );
session.executeRules();
StatelessRuleSession は非常に単純な API を持ちます。これを使用して executeRules(List list) (オブジェクトのリストを渡す) を呼び出し、任意でフィルター呼び出します。その後、結果となるオブジェクトが返されます。

例6.7 ステートレスルール

(StatelessRuleSession) session =
  ruleRuntime.createRuleSession( uri,
                                 null,
                                 RuleRuntime.STATELESS_SESSION_TYPE );
List list = new ArrayList();
list.add( new PurchaseOrder( "even more cheese" ) );

List results = new ArrayList();
results = session.executeRules( list );

6.2.3. グローバル

JSR94 でグローバルをサポートすることは可能ですが、移植は不可能になります。JSR94でグローバルをサポートするには、properties map を渡すメソッドを RuleSession ファクトリに渡します。最初に、DRL または XML ファイルにグローバルを定義し、例外がスローされないようにします。
キーは DRL または XML ファイルに宣言された識別子を表します。このキーの値は、実行で使用するインスタンスになります。次の例では、結果はグローバル java.util.List リストに収集されます。

例6.8 グローバル

java.util.List globalList = new java.util.ArrayList( );
java.util.Map map = new java.util.HashMap( );
map.put( "list", globalList ); 
//Open a stateless Session
StatelessRuleSession srs =
  (StatelessRuleSession) runtime.createRuleSession( "SistersRules",
                                                    map,
                                                    RuleRuntime.STATELESS_SESSION_TYPE );
...
// Persons added to List
// call executeRules( ) giving a List of Objects as parameter
// There are rules which will put Objects in the List
// fetch the list from the map
List list = (java.util.List) map.get("list");
必ず DRL ファイルにグローバルリストを宣言してください。グローバルリストの宣言は次のように行います。

例6.9 グローバルリスト

package SistersRules; 
import org.drools.jsr94.rules.Person; 
global java.util.List list
rule FindSisters 
when 
    $person1 : Person ( $name1:name ) 
    $person2 : Person ( $name2:name ) 
    eval( $person1.hasSister($person2) ) 
then 
    list.add($person1.getName() + " and " + $person2.getName() +" are sisters"); 
    assert( $person1.getName() + " and " + $person2.getName() +" are sisters"); 
end

6.3. 参考文献

JSR94 の詳細については、次の文献を参照してください。