ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Business Rulesランゲージ・リファレンス・ガイド
11g リリース1 (11.1.1.7)
B56239-04
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次
索引へ移動
索引

前
 
次
 

4 RuleSessionの使用

この章では、RuleSessionオブジェクトの使用方法を説明します。

この章の項目は、次のとおりです。

4.1 RuleSessionコンストラクタのプロパティ

この項では、ルール対応アプリケーションを作成する手順を示し、RuleSessionオブジェクトの使用方法について説明します。RuleSessionオブジェクトはパッケージoracle.rules.rlに含まれています。

RuleSessionコンストラクタは、引数がない場合、デフォルトのロケールおよびロギング・オプションが設定されたRuleSessionを戻します。

表4-1に、RuleSessionコンストラクタのプロパティを示します。

表4-1 RuleSessionのプロパティ

プロパティ名 プロパティ値

oracle.rules.rl.configLocale

任意のロケールに対するロケール・オブジェクト。マップにない場合は、デフォルトのロケールが使用されます。

デフォルト値: JVMデフォルト・ロケール

oracle.rules.rl.configLogging

ロギングはデフォルトで有効になります(true)。このプロパティが指定され、値がfalseの場合は、ロギングは無効になります。

デフォルト値: true


4.2 RuleSessionのメソッド

outputWriterプロパティは、printlnwatchおよびshowの出力先を決定します。

rulesetNameプロパティは、明示的にルールセット名を指定せずに、RL文の実行時にルールセットを設定します。デフォルトのrulesetNameはmainです。

executeRulesetメソッドは、指定のルールセット・テキスト(Stringまたはjava.io.Readerとして指定)を解析して実行します。

callFunctionメソッドは、名前付きRL関数(組込みRL関数または以前にexecuteRulesetメソッドの1つを使用してパラメータなしで定義した関数)を起動し、その結果を戻します。単一の引数を取る関数は、callFunctionWithArgumentメソッドを使用して起動できます。任意の数の引数を取る関数は、callFunctionWithArgumentListまたはcallFunctionWithArgumentArrayメソッドを使用してコールできます。引数のリストまたは配列には、各RL関数パラメータのJavaオブジェクトが記載されている必要があります。

4.3 RL型からJava型への変換

表4-2に、引数をRL関数に渡すためにJavaオブジェクト型をRL型に変換する方法、およびRL関数の戻り値をJavaに渡すためにRL型をJava型に変換する方法を示します。

表4-2 RLからJavaオブジェクトへの変換

Javaクラス RL型

java.lang.Integer

int

java.lang.Character

char

java.lang.Byte

byte

java.lang.Short

short

java.lang.Long

long

java.lang.Double

double

java.lang.Float

float

java.lang.Boolean

boolean

Object

Object

int[]

int[]

char[]

char[]

byte[]

byte[]

short[]

short[]

long[]

long[]

double[]

double[]

float[]

float[]

boolean[]

boolean[]

Object[]

Object[]


4.4 エラー処理

RuleSessionメソッドの起動でParseExceptionまたはTypeCheckExceptionがスローされても、RuleSessionの状態には影響を与えません。Javaアプリケーション(たとえば、対話型のコマンドライン)では、これらの例外を検出し、RuleSessionの使用を続行できます。

RuleSessionメソッドの起動でRLRuntimeExceptionがスローされた場合は、RuleSessionの状態に影響を与える可能性があり、アプリケーションでRuleSessionを処理できない状態になる場合があります。堅牢なアプリケーションの場合は、RLでRLRuntimeExceptionを検出し、例外がスローされた近辺でリカバリするように試みます。

その他の例外は、多くの場合、アプリケーションで処理できない重大な問題を示します。

4.5 RLクラスの反映

RLクラスは、Javaクラスと同様にRLプログラムで使用できます。newinstanceofおよびcastの演算子は、両方のクラスで使用できます。ただし、Javaプログラムに渡されたRLクラスのインスタンスは、実際にはoracle.rules.rl.RLObjectのインスタンスです。Javaプログラムでは、RLObjectを調べるためにRLClassRLPropertyおよびRLArrayクラスを使用できます。使用方法は、java.lang.Classjava.lang.reflect.Fieldおよびjava.lang.Arrayクラスを使用してjava.lang.Objectを反映する場合と同じです。RLCLassRLPropertyおよびRLArrayは、パッケージoracle.rules.rlに含まれます。

4.6 XMLナビゲーション

XLinkオブジェクトは、assertTree関数によって作成され、ファクトとしてアサートされます。RLルールでは、XLinkを使用して、assertTreeによってアサートされた要素の階層を推論できます。

4.7 ルール対応プログラムからの結果の取得

Oracle Business Rulesを使用してルール対応プログラムを作成したときの一般的な疑問は、「評価の結果を取得する方法は?」です。

この項では、ルール・エンジンからルール評価の結果を抽出または表示する方法について説明します。

内容は次のとおりです。


関連項目:

『Oracle Business Rulesユーザーズ・ガイド』のRules SDKデシジョン・ポイントAPIの使用に関する項


4.7.1 結果の例の概要

この項で使用する例は、高速道路の事故通知システムを示しています。それぞれの例は、ルール・エンジンの評価結果にアクセスするための異なる方法を示しています。これらの例では、2つのJavaクラスtraffic.TrafficIncidentおよびtraffic.IncidentSubscriptionを使用します。


注意:

サンプルのtraffic.*クラスは、Oracle Business Rulesに同梱されていません。


TrafficIncidentクラスは、交通状況に影響を与える事故の情報を表し、次のプロパティが含まれています。

  • どの高速道路か

  • 上りか下りか

  • 事故の種類

  • 事故発生時刻

  • 渋滞の見積時間(分単位)

IncidentSubscriptionクラスは、特定の高速道路における事故の通知へのサブスクリプションを記述し、次のプロパティが含まれています。

  • サブスクライバ - サブスクライバの名前

  • 該当する高速道路

  • 上りか下りか

この例では、高速道路で交通状況に影響を与える事故が発生したとき、これらのクラスを使用してTrafficIncidentオブジェクトをアサートし、ルール評価によって通知の受信者を判断します。

例に示すsessオブジェクトはRuleSessionで、事故通知の多数のサブスクリプションがアサートされます。単純化するために、TrafficIncidentオブジェクトは永続的でないことを前提にしています。実際には、このオブジェクトはアサート対象イベントを表し、その時点で登録されているサブスクライバにのみ通知が送信されます。

この例で使用するクラスはすべてJavaクラスです。ただし、RLクラスの反映を使用して、JavaでRLクラスのインスタンスを操作することもできます。


関連項目:

ドキュメントについては、oracle.rules.rlパッケージにあるRLClass、RLObject、RLPropertyおよびRLArrayクラスに関するJavadocを参照してください。RLオブジェクト、つまりRLクラスのインスタンスを使用すると、Javaオブジェクトと同様に、ルール・エンジンの結果を保持できます。


4.7.2 外部リソースを使用した結果の取得

この方法は、結果用のコンテナをアサートする方法と同じです。ただし、コンテナではなくオブジェクトを使用して、ルール・エンジンの外部にあるリソースに作用します。たとえば、予定の作業をキューに挿入したりスケジュールする場合、データベースを更新する場合、メッセージを送信する場合が該当します。結果を導出するには、アクションでアクセス可能な任意のJavaメソッドを起動できます。コンテナを使用する場合と同様に、外部リソースにアクセスするためにこの例で使用されているオブジェクトは、その内容が推論の対象でないため、再度アサートされることはありません。

例4-1に示すIncidentDispatcherオブジェクトは、アサートされて通知の配信に使用されます。

例4-1 外部リソースを使用した結果の取得

    rule incidentAlert
    {
        if (fact TrafficIncident ti &&
            fact IncidentSubscription s &&
                 s.highway == ti.highway &&
                 s.direction == ti.direction &&
            fact IncidentDispatcher dispatcher)
        {
            dispatcher.dispatch(s.subscriber, ti);
        }
    }

例4-2に示すJavaコードはIncidentDispatcherおよびTrafficIncidentをアサートし、ルール・エンジンを起動します。これは、推論の対象となるオブジェクトを使用しても実行できます。ただし、この場合は、ルール起動の無限ループを回避するために、ルール条件のテストが必要になります。

例4-2 外部リソースを使用した結果の例

        sess.callFunctionWithArgument("assert", new IncidentDispatcher());
 
        // An accident has happened
        TrafficIncident ti = new TrafficIncident();
        ti.setHighway("I5");
        ti.setDirection("south");
        ti.setIncident("accident");
        ti.setWhen(new GregorianCalendar(2005, 1, 25, 5, 4));
        ti.setDelay(45);
 
        sess.callFunctionWithArgument("assert", ti);
        sess.callFunction("run");

4.8 RLスタック・トレースのデバッグ

ランタイムでは、RLスタック・トレースに詳細なデバッグ情報が提供されます。エラーが発生した場合は、可能なかぎり、問題箇所の識別に役立つ特別なコンテキストが提供されます。この特別なコンテキストは、ルールSDKとルール・デザイナを併用している場合に有効です。

スタック・トレースには、ルール条件、ルール・アクション、関数、変数およびRLクラス定義に関する情報を示す特別なコンテキストが含まれています。XPath形式のフォーマットは、RL構成とそれに続くカッコで囲まれた名前(名前が指定されている場合)で構成されます。構成の後に大カッコで囲まれた番号nが表示される場合は、前の構成に続いてn番目の項目を示します。ルールSDKと併用している場合、ルール・デザイナでは、RL生成によってエラーの場所を非常に特定しやすくなります。

たとえば、例4-3に示されたルールセットについて考えてみます。このルールセットを実行すると、次のレポートが提供されます。

RLNullPointerException: object cannot be null
    at line 12 column 13 in stackTraceContext /Rule(porsche)/Pattern(car)/Test[1]
    at line 17 column 5 in stackTraceContext

例4-3 テスト・ルールセット

ruleset stackTraceContext
{
    class Car
    {
        String make;
        String model;
    }

    rule porsche
    {
        if (fact Car car &&
            car.make.startsWith("Porsche"))
        {
            println(car.make + " " + car.model);
        }
    }

    assert(new Car());
}

ruleset stackTraceContext

{

class Car

{

String make;

String model;

}

rule porsche

{

if (fact Car car &&

car.make.startsWith("Porsche"))

{

println(car.make + " " + car.model);

}

}

assert(new Car());

4.9 RuleSessionプールの使用

ルールを使用する典型的なアプリケーションでは、個々のリクエストに対応する異なるファクトを使用して、同じルールを何回も評価します。RuleSessionの初期化に要する時間は、含まれているルールの数によって異なりますが、通常は数秒です。これに対し、ルールの実行に必要なのは、初期化よりはるかに短い時間です。したがって、RuleSessionを1回初期化し、新規の各リクエストに対して再利用することで、パフォーマンスを向上させることができます。RuleSessionプールを使用すると、RuleSessionインスタンスのプールを作成できるため、ルールを使用するアプリケーションのパフォーマンスとスケーラビリティが向上します。

4.9.1 RuleSessionプールの作成方法

負荷の増加に対応したパフォーマンスを実現するには、複数のRuleSessionが必要です。RuleSessionインスタンスのプールにより、ルールを使用するアプリケーションのパフォーマンスとスケーラビリティが向上します。プールは、RLコードのリストを使用してインスタンス化されます。RLコードは、プールで作成された各RuleSessionを初期化するために使用されます。RLコードは、リストに記載されている順に実行されます。最初に作成するRuleSessionインスタンスの数を指定できます。一般的には小さい値を指定しますが、通常は、このデフォルト値で十分です。

RLコードは通常、ルールSDKで作成されたRuleDictionaryから生成されます。例4-4は、RuleDictionaryから生成されたRLコードでRuleSessionPoolを作成および使用する方法を示しています。

例4-4 RuleSessionプールの作成方法

     RuleDictionary rd;
     // Code to load rule dictionary not shown
     List rlList = new ArrayList();
     rlList.add(rd.dataModelRL());
     List rulesetAliases = rd.getRuleSetAliases(true);
     for (String alias : rulesetAliases)
     {
         rlList.add(rd.ruleSetRL(alias));
     }
 
     RuleSessionPool pool = new RuleSessionPool(rlList);

アプリケーションで使用中のルールが更新された場合は、後続のルール実行で新しいルールが使用されるように、アプリケーションは新しいルールをロードする必要があります。これをプールでサポートするには、refreshPoolメソッドを起動して新しいRLのリストを渡します。プールが更新されると、getPoolableRuleSessionで戻されるRuleSessionは、新しいRLコードで初期化されています。更新前に取得されたRuleSessionがreturnPoolableRuleSessionを使用して戻された場合、そのRuleSessionはプールに戻されません。更新後のプールに保存されるのは、新しいRLコードで初期化されたRuleSessionのみです。

4.9.2 RuleSessionプールの使用方法

RuleSessionを使用してルールを実行する場合は、プールからRuleSessionを取得し、実行後にプールに戻します。プール可能なRuleSessionを取得するには、getPoolableRuleSessionメソッドを起動します。プールでは、必要に応じて新しいRuleSessionが作成されます。getPoolableRuleSessionの起動は、空きRuleSessionの待機を妨げることはありません。

ルール実行の完了後、プール可能なRuleSessionをプールに戻すには、returnPoolableRuleSessionメソッドを起動します。プールに戻されたRuleSessionをプールでリセットするには、組込みRL関数のreset()を起動します。これによって、作業メモリーからすべてのファクトが削除され、そのRuleSessionは次の実行のために準備されます。プールから取得したすべてのRuleSessionは、プールに戻す必要があります。ルールの実行中に発生したエラーが原因で今後の使用に適さなくなったRuleSessionは、プールで検出されて廃棄されます。

reset()関数は、作業メモリーの消去に加えて、非ファイナル・グローバル変数のイニシャライザを再実行します。非ファイナル・グローバル変数のイニシャライザを使用すると、必要な場合は、リセット時に他の初期化を実行できます。

例4-5は、プールからRuleSessionを使用する方法を示しています。

例4-5 RuleSessionプールの使用方法

     PoolableObject po = pool.getPoolableRuleSession();
     RuleSession engine = po.getPooledObject();
     // use the RuleSession to execute rules as required here
     pool.returnPoolableRuleSession(po);

プールのサイズに対するソフト上限を指定できます。この指定によって、一時的な需要の増加に対応するためにプールを拡大する一方、需要の減少時には、プールをソフト上限まで縮小できます。

getPoolableRuleSessionが起動されてプールが空の場合には、RuleSessionプールの実装を使用してRuleSessionインスタンスを作成します。負荷が非常に大きい場合は、ソフト制限を超えるインスタンス件数になります。

負荷の減少に従って、プール内のRuleSesionインスタンスの数は、ソフト制限まで自動的に減少します。

4.10 RuleSessionオプションの使用方法

RuleSessionを使用したRLランタイムは、次のオプションをサポートしています。

4.10.1 CFG_LOGGINGシステム・プロパティの使用

RL Languageランタイムでは、システム・プロパティとしてのCFG_LOGGINGと、RuleSessionコンストラクタに渡されるコンフィグ・マップのBooleanが検索されます。システム・プロパティの値は、マップの値でオーバーライドされます。

4.10.2 CFG_DECISION_TRACE_LEVELオプションの使用方法

RuleSession.CFG_DECISION_TRACE_LEVEL初期化パラメータをインクルードして、RuleSessionまたはRuleSessionPoolコンストラクタに渡される構成マップのレベルを指定することで、RuleSessionまたはRuleSessionPoolのトレース・レベルを構成できます。これはRuleSessionの作成時のデシジョン・トレース・レベルを設定します。reset()を起動すると、reset()の後、ルール実行中にレベルが変更されていた場合にレベルを構成値に戻すことができます。詳細は、第1.7.2項「ルール・エンジン・レベルのデシジョン・トレースの使用方法」を参照してください。

4.10.3 CFG_DECISION_TRACE_LIMITオプションの使用方法

トレースのサイズは、デシジョン・トレースのエントリ数を制限することで制限します。JVM内で使用可能なすべてのヒープを消費するトレースを作成することから、ルール内の不具合の可能性があるため、ルール起動の無限ループを回避するために制限が必要となります。トレースの制限は、setDecisionTraceLimit関数を使用して設定します。この制限は、RuleSession (またはRuleSessionPool)で構成することも可能です。構成するには、RuleSessionまたはRuleSessionPoolコンストラクタに渡される構成マップに目的の制限を指定したRuleSession.CFG_DECISION_TRACE_LIMIT初期化パラメータをインクルードします。詳細は、第1.7.2項「ルール・エンジン・レベルのデシジョン・トレースの使用方法」を参照してください。