プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle Business Process Managementによるビジネス・ルールの設計
12c (12.2.1.2.0)
E82791-01
目次へ移動
目次

前
次

8 スタンドアロン(非SOA/BPM)シナリオでのルールの使用

スタンドアロン(非SOA/BPM)シナリオでルールを使用する場合、RuleSessionルールを作成するか、デシジョン・ポイントAPIを使用できます。

RulesSessionオブジェクトの使用方法の詳細は、『Oracle Business Process Managementルール言語リファレンス』のRuleSessionの使用方法に関する項を参照してください。

デシジョン・ポイントAPIの使用方法の詳細は、「Rules SDKデシジョン・ポイントAPIの概要」を参照してください。

この章の内容は次のとおりです。

この章で示されているAPIの詳細は、Oracle Business Rules Java APIリファレンスを参照してください。

8.1 リポジトリからのディクショナリのロード

非SCA (SOA/BPM)アプリケーションは、そのアプリケーションによって使用されるルール・ディクショナリをパッケージ化し、そのアプリケーションがデプロイされるときにそれらがMDSリポジトリにコピーされるようにします。実行時にディクショナリを使用するためには、MDSから取得する必要があります。基本的なアクセス方法は、RuleRepository APIを使用してディクショナリにアクセスすることです。単純な仕様例を次に示します。

RuleRepository rr = RepositoryManager.getMDSRuleRepository(null);
 // pkg and name are the dictionary package and name (Strings).
 // Alternatively you could construct a DictionaryFQN
 RuleDictionary rd = rr.load(pkg, name);
 // if this is an editing session, edit session occurs and
 // then save it when done.
 rr.save(rd);
 // when the RuleRepository will not be used again it must be closed.
 rr.close();

一般的に、ディクショナリが変更されたときにアプリケーションが反応してディクショナリをリロードし、新しいルール定義の使用を開始する必要があります。リンクされたディクショナリが使用されている場合、ディクショナリのリロードの必要性の検知は複雑です。それは、ルート・ディクショナリでないものが変更されることがあるためです。

そのような場合、ルールを実行するためのディクショナリのロードに推奨されるメカニズムは、oracle.rules.sdk2.repository.DictionaryLoaderクラスです。DictionaryLoaderは、リンクされたディクショナリなどロードされたディクショナリを追跡し、ロード済のディクショナリをリロードする必要がある場合を判別できます。DictionaryLoaderは、DictionaryFinderインスタンスを使用して、すべてのディクショナリをロードします。DictionaryFinderが、ディクショナリを見つけるために呼び出される順序でaddFinderメソッドによってDictionaryLoaderインスタンスに追加されます。つまり、最初に追加されるファインダが、ディクショナリのロードを最初に試みることになります。DictionaryLoaderに目的のDictionaryFinderがすべて追加されたら、loadDictionary()メソッドが使用されてディクショナリがロードされます。reloadNeededメソッドを呼び出して、ディクショナリをリロードする必要があるかどうかを判別することができます。

 //
  // A RuleRepository instance is needed for its built-in DictionaryFinder
  //
  RuleRepository rr = RepositoryManager.getMDSRuleRepository(null);
  DictionaryFinder rrf = rr.getDictionaryFinder();
 
  //
  // Create the dictionary loader
  //
  DictionaryLoader dloader = new DictionaryLoader();
  dloader.addFinder(rrf);
  //
  // If the DecisionPointDictionaryFinder is required, add it
  //
  dloader.addFinder(new DecisionPointDictionaryFinder());
 
  //
  // Load the dictionary
  //
  DictionaryFQN fqn = new DictionaryFQN("somepackage", "myDictionary");
  RuleDictionary rd = dloader.loadDictionary(fqn);
 
  //
  // Check if the dictionary needs to be reloaded
  //
  if (dloader.reloadNeeded(fqn))
      rd = dloader.loadDictionary(fqn);
 
  //
  // When usage is complete, the RuleRepository must be closed.
  //
  rr.close();

8.2 ルール・ディクショナリの実行

RuleDictionaryからRuleSessionPoolを初期化するには、RuleSessioPoolの初期化と、デシジョン・ポイントAPIの使用の2つの方法があります。

詳細は、「Rules SDKデシジョン・ポイントAPIの概要」を参照してください

ルール実行のために初期化する場合、RuleDictionaryがロードされると、RuleSessionPoolはディクショナリから生成されたRLで初期化されます。

詳細は、『Oracle Business Process Managementルール言語リファレンス』のRuleSessionプールの使用方法に関する項を参照してください。

1つのデシジョン関数が呼び出される場合は、そのデシジョン関数によって参照されるルール・セットのみをロードすることが最も効率的です。RuleSessionPoolコンストラクタに渡されるRLテキストのリストを構築するサンプル・コードを次に示します。

簡潔にするために、エラー・チェックおよび例外処理は表示していないことに注意してください。

RuleDictionary rd;  // previously loaded dictionary
        String dfAlias = "Alias for my Decision Function";
        DecisionFunction df =
 rd.getCombinedDataModel().getDecisionFunctionByAlias(dfAlias);
        List<String> rlList = new ArrayList<String>();
        //
        // Add the RL for the data model
        //
        rlList.add(rd.dataModelRL());
        //
        // Add the RL for each rule set referenced by the decision function
        //
        Collection<String> rsal = df.getRuleSets();
        for (String alias : rsal)
        {
            rlList.add(rd.ruleSetRL(alias));
        }

同じRuleSessionPoolから複数のデシジョン関数が呼び出される場合、各デシジョン関数によって参照されるルールセットのRLを追加することでこれが可能になます。同じルールセットを2回追加しないように注意してください。

ルールを使用して実行時に実行する他のルールセットを動的に選択するなど他のシナリオでは、ディクショナリ内のルールセットをすべてロードすることが必要になります。これを実行するサンプル・コードを、次に示します。

RuleDictionary rd;  // previously loaded dictionary
        List<String> rlList = new ArrayList<String>();
        //
        // Add the RL for the data model
        //
        rlList.add(rd.dataModelRL());
        //
        // Add the RL for each rule set referenced by the decision function
        //
        Collection<String> rsal = rd.getRuleSetAliases(true);
        for (String alias : rsal)
        {
            rlList.add(rd.ruleSetRL(alias));
        }

8.3 Rules SDKデシジョン・ポイントAPIの概要

この項では、Oracle Business Rules SDK (Rules SDK)を使用して、Oracle Business Rulesのディクショナリのルールにアクセスしたり、ルールを作成、変更および実行したり、ディクショナリの内容を操作するアプリケーションを記述したりする方法について説明します。Rules SDKの概要、およびRules SDKデシジョン・ポイントAPIの使用方法についても説明します。Rules SDKは、次の4つの領域で構成されています。

  • エンジン: ルール実行の準備をします。

  • ストレージ: ルールのディクショナリとリポジトリへのアクセスを提供します。

  • 編集: ディクショナリ・コンポーネントの作成と変更をプログラムで行えるようにします。

  • デシジョン・ポイント: ディクショナリにアクセスしたりデシジョン関数を実行するためのインタフェースを提供します。

説明以外の目的でRules SDKのこれらの領域が明示的に区別されることはありません。たとえば、ルールを編集するには、Rules SDKのストレージ領域を使用して、ディクショナリにもアクセスする必要があります。Rules SDKがこれらの領域に分割されているのは、個別のRules SDK APIを説明するためではなく、各種の使用モードを説明しやすくするためです。

8.3.1 デシジョン・ポイントAPIの使用

デシジョン・ポイントAPIを使用すると、ルールを簡単に実行できます。ほとんどのユーザーは、Oracle JDeveloperのルール・デザイナ拡張機能を使用して、データ・モデル要素、ルール、デシジョン表、ルールセットなどのOracle Business Rulesアーティファクトを作成します。したがって、ほとんどのユーザーは、Rules SDKのエンジン、ストレージまたは編集機能を直接使用する必要はありません。

Rules SDKのデシジョン・ポイント・パッケージを使用するには、次の3つの重要なクラスを理解する必要があります。

  • DecisionPoint: ファクトリの設計パターンに従ってDecisionPointInstanceのインスタンスを作成するヘルパー・クラスです。ほとんどのアプリケーションには、すべてのアプリケーション・スレッドで共有されるDecisionPointオブジェクトが1つ必要です。コール元はDecisionPointgetInstance()メソッドを使用して、定義済デシジョン・ポイントのコールに使用できるDecisionPointInstanceのインスタンスを取得します。

  • DecisionPointBuilder: ビルダーの設計パターンに従ってデシジョン・ポイントを作成します。

  • DecisionPointInstance: ユーザーはこのクラスのinvoke()をコールしてファクトをアサートし、デシジョン関数を実行します。

DecisionPointクラスでは、流れるようなインタフェース・モデルがサポートされているため、メソッドを連鎖させることができます。詳細は、次の章を参照してください。

http://www.martinfowler.com/bliki/FluentInterface.html

デシジョン・ポイントは、次のようなルール実行のいくつかの側面を管理します。

  • oracle.rules.rl.RuleSessionオブジェクトの使用

  • ディクショナリ更新時のディクショナリのリロード

Javaアプリケーションのデシジョン・ポイントを作成するために必要なものは次のとおりです。

  • MDSリポジトリからロードするディクショナリまたは事前ロード済のoracle.rules.sdk2.dictionary.RuleDictionaryインスタンスの名前。

  • 指定したディクショナリに格納されているデシジョン関数の名前。

8.3.2 レンタカー・サンプル・アプリケーションの入手方法

この章では、Rules SDKとデシジョン・ポイントAPIの使用方法を示すレンタカー・アプリケーションについて説明します。このサンプル・アプリケーションは、CarRentalApplication.zipというZIPファイルで入手できます。このZIPファイルには、完全なJDeveloperアプリケーションとプロジェクトが含まれています。

Oracle Business Rules固有のサンプルとSOAのサンプルのソースコードは、Oracle SOA Suiteのサンプル・ページからオンラインで入手できます。

サンプルを使用するには、CarRentalApplication.zipを適切なディレクトリに解凍します。レンタカー・アプリケーションのプロジェクトには、ルール・ディクショナリおよびRules SDKを使用したいくつかのJavaサンプルが含まれています。

例についての詳細は、「等級サンプル・アプリケーションの概要」を参照してください。

8.3.3 レンタカー・サンプル・アプリケーションとプロジェクトを開く方法

レンタカー・サンプル・アプリケーションにより、Rules SDKデシジョン・ポイントAPIの使用方法がわかります。

レンタカー・サンプル・アプリケーションを開く手順は、次のとおりです。

  1. Oracle JDeveloperを起動します。
  2. サンプルを解凍したディレクトリにあるレンタカー・アプリケーションを開きます。たとえば、「ファイル」メニューから「開く」を選択し、「開く」ダイアログでCarRentalApplicationフォルダにナビゲートします。
  3. 「開く」ダイアログで「CarRentalApplication.jws」を選択し、「開く」をクリックします。
  4. 「アプリケーション・ナビゲータ」で「CarRentalApplication」を開き、「アプリケーション・ソース」「リソース」を開きます。CarRental.rulesという名前のOracle Business RulesディクショナリといくつかのJavaソース・ファイルが表示されます。

8.4 デシジョン・ポイントで使用するディクショナリの作成

レンタカー・サンプルでは、事前ロード済のOracle Business RulesディクショナリまたはMDSに格納されているリポジトリでRules SDKデシジョン・ポイントAPIを使用します。開発環境で作業する場合は、事前ロード済のディクショナリ・シグネチャでデシジョン・ポイントAPIを使用できます。本番環境では、一般にMDSリポジトリ・シグネチャでデシジョン・ポイントを使用します。

CarRentalディクショナリが事前に定義されており、レンタカー・サンプル・アプリケーションで使用できます。

デシジョン・ポイントAPIを使用するには、デシジョン関数を含むディクショナリを作成する必要があります(レンタカー・サンプル・アプリケーションには、事前定義済のディクショナリとデシジョン関数が用意されています)。

ディクショナリとデシジョン関数を作成するには、次の手順を実行します。

8.4.1 デシジョン・ポイントで使用するデータ・モデル要素の作成方法

注意:

スクリーン・ショットは、前のバージョンを反映していますが、内容は現在のリリースにも当てはまります。

デシジョン・ポイントを使用してアプリケーションを作成する場合、デシジョン関数に追加する次のディクショナリが必要になります。

サンプル・アプリケーションのデータ・モデルを表示する手順は、次のとおりです。

  1. Rules Designerで、「ファクト」ナビゲーション・タブをクリックします。
  2. 図8-1に示すように、「Javaファクト」タブを選択します。

    「Javaファクト」タブに、ディクショナリに組み込まれているファクト・タイプに加えて、インポートされた次の4つのファクト・タイプが表示されます。

    Driver Javaファクトは、プロジェクト内のDriver Javaクラスからインポートされています。

    Denial Javaファクトは、プロジェクト内のDenial Javaクラスからインポートされています。

    LicenseTypeファクトとVehicleTypeファクトは、Driverクラスで定義されている、ネストしたenumクラスからインポートされています。

    図8-1 レンタカー・サンプル・アプリケーション用に定義されているJavaファクト

    図8-1の説明が続きます
    「図8-1 レンタカー・サンプル・アプリケーション用に定義されているJavaファクト」の説明

Rules SDKのデシジョン・ポイントを使用する場合は、指定したディクショナリ内のデシジョン関数をコールします。コールするデシジョン関数には、デシジョン・ポイントの一部として実行される1つ以上のルールセットを含めることができます。

同じく、用意されているレンタカー・サンプル・アプリケーションのルールセットを表示するには、ルール・デザイナでCarRentalApplicationを展開します。CarRentalApplicationで、「リソース」を展開し、「CarRental.rules」をダブルクリックします

8.4.2 デシジョン・ポイントからコールするデシジョン関数の表示方法

デシジョン・ポイントAPIを使用する場合は、デシジョン関数を使用してOracle Business Rulesディクショナリを公開します。デシジョン関数の詳細は、デシジョン関数の使用を参照してください。

レンタカー・サンプル・アプリケーションのデシジョン関数を表示する手順は、次のとおりです。

  1. Rules Designerで、「デシジョン関数」ナビゲーション・タブをクリックします。図8-2に示すように、CarRentalディクショナリ内の使用可能なデシジョン関数が表示されます。

    図8-2 レンタカー・サンプルのデシジョン関数

    図8-2の説明が続きます
    「図8-2 レンタカー・サンプルのデシジョン関数」の説明
  2. CarRentalDecisionFunctionの行を選択し、デシジョン関数のアイコンをダブルクリックします。図8-3に示すように、「デシジョン関数の編集」ダイアログが開きます。

    デシジョン関数の「入力」表には、Driverファクト・タイプの単一の引数が表示されます。

    デシジョン関数の「出力」表には、Denialファクト・タイプの単一の引数が表示されます。

    デシジョン関数の「ルールセットおよびデシジョン関数」領域の「選択済」ボックスには、「Denial Rules:if-then」が表示されます。

    図8-3 レンタカー・サンプル・アプリケーションのレンタカー・デシジョン関数

    図8-3の説明が続きます
    「図8-3 レンタカー・サンプル・アプリケーションのレンタカー・デシジョン関数」の説明

8.4.3 デシジョン関数のルールまたはデシジョン表の作成方法

レンタカー・サンプルには2つのルールセットが含まれています。一方にはIF/THENルール、もう一方にはデシジョン表が含まれています。デシジョン・ポイントの使用時は、IF/THENルールかデシジョン表のいずれか、または両方をアプリケーションで使用できます。

レンタカー・サンプル・アプリケーションのルールを表示する手順は、次のとおりです。

  1. 図8-4に示すように、ルール・デザイナで「Denial Rules:if-then」ルールセットをクリックします。

    図8-4 レンタカー・サンプル・アプリケーションのIF/THENルールを含むルールセット

    図8-4の説明が続きます
    「図8-4 レンタカー・サンプル・アプリケーションのIF/THENルールを含むルールセット」の説明

    「Denial Rules:if-then」ルールセットには、次の2つのルールが含まれています。

    • under age: このルールは、運転者の最低年齢を定義します。DriverインスタンスのageプロパティをグローバルのMinimum driver ageと比較します。運転者がこの年齢未満の場合、新しいDenialファクトがアサートされます。デシジョン関数へのコールにより、このDenialファクトが出力の定義に従って収集されます。

    • too many accidents: このルールは、それを超えると運転者がレンタルを拒否される、事故回数の上限値を定義します。また、このルールは、Denialが作成された理由を示す監査出力を提供するために、ユーザー定義関数auditもコールします。

  2. レンタカー・アプリケーションのデシジョン表を表示するには、図8-5に示すように、ルール・デザイナで「Denial Rules:decision table」ルールセットをクリックします。

    図8-5 レンタカー・サンプル・アプリケーションのデシジョン表を含むルールセット

    図8-5の説明が続きます
    「図8-5 レンタカー・サンプル・アプリケーションのデシジョン表を含むルールセット」の説明

8.4.4 デシジョン表を使用したレンタカー・サンプルの使用に関する必知事項

レンタカー・サンプル・アプリケーションには、「Denial Rules: decision table」ルールセットが含まれています。用意されているデシジョン関数サンプルでデシジョン表を使用するように切り替えるには、図8-6に示すように、デシジョン関数の「選択済」領域から「Denial Rules:if-then」を移動し、デシジョン表を使用して同様のルールを定義する「Denial Rules: decision table」ルールセットをこの領域に追加します。

図8-6 デシジョン表ルールセットを使用したレンタカー・サンプルのデシジョン関数

図8-6の説明が続きます
「図8-6 デシジョン表ルールセットを使用したレンタカー・サンプルのデシジョン関数」の説明

8.5 Rules SDKデシジョン・ポイントを使用したJavaアプリケーションの作成

開発環境でRules SDKを使用する場合は、事前ロード済のディクショナリでデシジョン・ポイントAPIを使用できます。本番環境では、一般にMDSリポジトリ・シグネチャでデシジョン・ポイントAPIを使用し、ディクショナリはMDSに格納されます。デシジョン・ポイントの使用方法の詳細は、「本番環境でのデシジョン・ポイントの使用に関する必知事項」を参照してください。

Oracle Business Rules固有のサンプルとSOAのサンプルのソースコードは、Oracle SOA Suiteのサンプル・ページからオンラインで入手できます。

CarRentalProjectプロジェクトには、レンタカー・サンプル・ファイルCarRentalWithDecisionPointUsingPreloadedDictionary.javaを含む、com.example.rules.demoパッケージが含まれています。このプロジェクトには、デシジョン・ポイントを使用するための様々なバリエーションをサポートする複数の.javaソース・ファイルも含まれています。表8-1に、レンタカー・サンプルの様々なバージョンのサマリーを示します。

表8-1 デシジョン・ポイント・サンプルCarRentalProject内のJavaファイル

ベースJavaファイル名 説明

CarRental

これはすべてのサンプルのベース・クラスです。CarRentalディクショナリおよびDriverクラスのインスタンスを作成するcreateDriversメソッドを使用するための定数値が含まれています。

CarRentalWithDecisionPoint

DecisionPointタイプの静的属性およびDriverクラスの指定したインスタンスでデシジョン・ポイントを起動するcheckDriver()メソッドが含まれています。これらのメソッドはサンプル・アプリケーション用に含まれているため、MDSリポジトリと事前ロード済ディクショナリの両方のサンプルで同じcheckDriver()の実装を共有できます。

CarRentalWithDecisionPointUsingMdsRepository

MDSを使用してルール・ディクショナリのアクセスとロードを行うデシジョン・ポイントの作成サンプルが含まれています。本番環境では、ほとんどのアプリケーションはデシジョン・ポイントAPIをMDSで使用します。

CarRentalWithDecisionPointUsingPreloadedDictionary

RuleDictionaryクラスのインスタンスからデシジョン・ポイントを作成するサンプルが含まれています。このサンプルには、ディクショナリを手動でロードしてRuleDictionaryインスタンスを作成するためのコードも含まれています。

CarRentalWithRuleSession

エンジンAPIの高度な使用サンプルが含まれています。詳細はコメントに記述されています。

CarRentalWithRuleSessionPool

エンジンAPIの高度な使用サンプルが含まれています。詳細はコメントに記述されています。

Denial

ルールとデシジョン表の作成に使用されるDenialファクト・タイプを定義するクラスが含まれています。

Driver

ルールとデシジョン表の作成に使用されるDriverファクト・タイプを定義するクラスが含まれています。

DriverCheckerRunnable

同時ユーザーによるデシジョン・ポイントの起動をシミュレートするスレッドとして使用できるクラスが含まれています。

8.5.1 デシジョン・ポイント・ビルダーを使用したデシジョン・ポイントの追加方法

デシジョン・ポイントを使用するには、次の例に示すように、DecisionPointBuilderを使用してDecisionPointインスタンスを作成します。

    static {
        try {
            // specifying the Decision Function and a pre-loaded
            // RuleDictionary instance 
            m_decisionPoint =  new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(loadRuleDictionary())
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " + e.getMessage());
            e.printStackTrace();
        }
    }

前の例は、DecisionPointBuilderが流れるようなインタフェース・パターンをサポートしているため、デシジョン・ポイントの作成時にすべてのメソッドを容易に連鎖させることができることを示しています。DecisionPointBuilderでデシジョン・ポイントを構成するための最も一般的な3つのメソッドは、with()という名前を持つようにオーバーロードされます。各with()メソッドは、RuleDictionary型、DictionaryFQN型またはString型の単一の引数を使用します。DecisionPointBuilderは、類似のsetメソッドとgetメソッド(getDecisionFunction()setDecisionFunction()getDictionary()setDictionary()getDictionaryFQN()setDictionaryFQN())もサポートしています。

前の例に示すこの連鎖には、次のステップが含まれています。

  1. 最初のステップでは、次のようなコードでDecisionPointBuilderインスタンスを作成します。
    new DecisionPointBuilder()
    
  2. String引数を使用するwith()メソッドで、デシジョン・ポイントによって実行されるデシジョン関数の名前を定義します。このメソッドのコールは必須です。
    .with(DF_NAME)
    

    DF_NAMEには、アプリケーションで定義したデシジョン関数の名前を指定します。たとえば、レンタカー・サンプル・アプリケーションでは、DF_NAMECarRental.javaCarRentalDecisionFunctionと定義されています。

  3. これ以外の2つのwith()メソッドのうち、いずれか1つのみをコールします。このサンプル・コードでは、指定したデシジョン関数を含む事前ロード済のルール・ディクショナリ・インスタンスを使用しています。loadDictionary()メソッドは、ファイルからRuleDictionaryのインスタンスをロードします。例8-1に、loadDictionary()メソッドを示します。詳細は、「事前ロード済のディクショナリでデシジョン・ポイントを使用する方法」を参照してください。
    .with(loadRuleDictionary())
    
  4. DecisionPointインスタンスを作成して戻すために、build()メソッドをコールします。

DecisionPointインスタンスは、アプリケーションのすべてのインスタンス間で共有されます。このためこのインスタンスは静的な属性で、静的なブロック内で作成されます。DecisionPointを初期化する別の方法としては、DecisionPointインスタンスを作成して戻した静的なメソッドを使用して、m_decisionPoint属性を初期化することが考えられます。

8.5.2 事前ロード済のディクショナリでデシジョン・ポイントを使用する方法

例8-1に、ファイルからRuleDictionaryのインスタンスをロードするloadRuleDictionary()メソッドを示します。

例8-1に示すように、ファイルから直接ディクショナリの読取りまたは書込みを行う場合は、必ずエンコーディングをUTF-8に設定します。そうでない場合、ディクショナリで使用するUnicode文字が破損してしまいます。UTF-8オプションは、FileInputStreamまたはOutputStreamWriterコンストラクタ内で明示的に設定する必要があります。FileReaderFileWriterなどのJavaクラスは使用できません。これらのクラスはプラットフォームのデフォルト・エンコーディングを常に使用しており、それは通常はUnicodeバリアントではなくASCIIバリアントだからです。

例8-1 ルール・ディクショナリのロード・メソッド

private static RuleDictionary loadRuleDictionary(){ 
        RuleDictionary dict = null; 
        BufferedReader reader = null; 
        try { 
            reader = new BufferedReader( 
                        new InputStreamReader( 
                            new FileInputStream( 
                                new File(DICT_LOCATION)), "UTF-8")); 
            dict = RuleDictionary.readDictionary(reader, 
                                                 new 
DecisionPointDictionaryFinder(null)); 
 
            List<SDKWarning> warnings = new ArrayList<SDKWarning>(); 
 
            dict.update(warnings); 
            if (warnings.size() > 0) { 
                System.err.println("Validation warnings: " + warnings); 
            } 
        } catch (SDKException e){ 
            System.err.println(e); 
        } catch (FileNotFoundException e){ 
            System.err.println(e); 
        } catch (IOException e){ 
            System.err.println(e); 
        } finally { 
            if (reader != null) { try { reader.close(); } catch (IOException 
ioe) {ioe.printStackTrace();}} 
        } 
        return dict; 
    } 

8.5.3 エグゼキュータ・サービスを使用してデシジョン・ポイントでスレッドを実行する方法

レンタカー・サンプルでは、Oracle Business Rulesを使用して複数の同時ユーザーをシミュレートできます。次のコード例に、JavaのExecutorServiceインタフェースを使用して、デシジョン・ポイントを起動する複数のスレッドを実行する方法を示します。ExecutorServiceは、Rules SDKデシジョン・ポイントAPIに含まれていません。

        ExecutorService exec = Executors.newCachedThreadPool();
        List<Driver> drivers = createDrivers();
 
        for (int i = 0; i < NUM_CONCURRENT; i++) {
            Driver driver = drivers.get(i % drivers.size());
            exec.execute(new DriverCheckerRunnable(driver));
        }

前の例には、サンプル・アプリケーションの次のコードが含まれています。

  • エグゼキュータ・サービスを作成します。

    ExecutorService exec = Executors.newCachedThreadPool();
    
  • CarRental.javaに定義されているcreateDrivers()メソッドをコールして、Driverインスタンスのリストを作成します。

    List<Driver> drivers = createDrivers();
    
  • Driverインスタンスのリストをループしてdriverリストに運転者を格納します。

  • ループでDriverCheckerRunnableインスタンスから複数のスレッドを開始します。これらのインスタンスはデシジョン・ポイントを開き、各運転者に対してルールを実行します。このコードの詳細は、「デシジョン・ポイント・インスタンスの作成および使用方法」を参照してください。

次のコード例は、スレッドの完了を待機するコードです。

        try {
            exec.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exec.shutdown();
    }

8.5.4 デシジョン・ポイント・インスタンスの作成および使用方法

DriverCheckerRunnableインスタンスはcheckDriver()メソッドをコールします。例8-2に、CarRentalWithDecisionPointで定義されているcheckDriver()メソッドを示します。checkDriver()メソッドは、Driverインスタンスによるデシジョン・ポイントの起動を処理します。

例8-2は、次のことを示しています。

  • 次のコードにより、DecisionPointBuilderで定義された静的なDecisionPointからDecisionPointInstanceを取得します。

     DecisionPointInstance instance = m_decisionPoint.getInstance();
    
  • デシジョン・ポイントに関連付けられているデシジョン関数のシグネチャに従って入力を追加します。ここでは入力としてList型の引数を1つ定義しています。このListには、Driverインスタンスが格納されます。

                instance.setInputs(new ArrayList<Object>() {
                        {
                            add(driver);
                        }
                    });
    
  • デシジョン・ポイントを起動し、戻り値を格納します。戻り型は、デシジョン・ポイントでコールされるデシジョン関数と同じパターンに従います。

     List<Object> outputs = instance.invoke();
    

    この例では、invoke()は、DenialインスタンスのListが格納された長さ1のListを戻します。

  • 1以外のサイズのListが戻された場合は、エラーが生成されます。

    if (outputs.isEmpty())
      System.err.println("Oops, no results");
    
  • デシジョン・ポイントから戻される最初のエントリは、List<Denial>型のリストにキャストされます。

                java.util.List<Denial> denials =
                    (java.util.List<Denial>)outputs.get(0);
    
  • denialsリストが空の場合、Denialインスタンスはルールによってアサートされませんでした。これは、車を運転者に貸してもよいことを意味しています。それ以外の場合は、運転者がレンタルを拒否された理由を出力します。

                if (denials.isEmpty()) {
                    System.out.println("Rental is allowed for " +
                                       driver.getName());
                } else {
                    for (Denial denial : denials) {
                        System.out.println("Rental is denied for " +
                                           denial.getDriver().getName() +
                                           " because " + denial.getReason());
                    }
                }
    

8.5.4.1 getInstance()でデシジョン・ポイント・インスタンスを作成するサンプル・コード

DriverCheckerRunnableインスタンスはcheckDriver()メソッドをコールします。例8-2に、CarRentalWithDecisionPointで定義されているcheckDriver()メソッドを示します。checkDriver()メソッドは、Driverインスタンスによるデシジョン・ポイントの起動を処理します。

例8-2 getInstance()でデシジョン・ポイント・インスタンスを作成するコード

public class CarRentalWithDecisionPoint extends CarRental {
 
    protected static DecisionPoint m_decisionPoint;
    
    public static void checkDriver(final Driver driver) {
        try {
            DecisionPointInstance instance = m_decisionPoint.getInstance();
            instance.setInputs(new ArrayList<Object>() {
                    {
                        add(driver);
                    }
                });
            List<Object> outputs = instance.invoke();
 
            if (outputs.isEmpty())
                System.err.println("Oops, no results");
 
            java.util.List<Denial> denials =
                (java.util.List<Denial>)outputs.get(0);
            if (denials.isEmpty()) {
                System.out.println("Rental is allowed for " +
                                   driver.getName());
            } else {
                for (Denial denial : denials) {
                    System.out.println("Rental is denied for " +
                                       denial.getDriver().getName() +
                                       " because " + denial.getReason());
                }
            }
        } catch (RLException e) {
            e.printStackTrace();
        } catch (SDKException e) {
            e.printStackTrace();
        }
    }
    
}

8.6 レンタカー・サンプルの実行

システムにインストールされているレンタカー・サンプルで、例8-1に示すコードのDICT_LOCATIONの値をシステムのディクショナリの場所にあわせて変更します。

システムでレンタカー・サンプルを実行する手順は、次のとおりです。

  1. 「アプリケーション・ナビゲータ」で、「編集」メニューから「パスのコピー」を選択します。
  2. CarRental.javaファイルで、パスの値をDICT_LOCATIONの値に貼り付けます。
  3. CarRentalProjectで、CarRentalWithDecisionPointUsingPreloadedDictionary.javaファイルを選択します。
  4. 右クリックしてリストから「実行」を選択します。

8.6.1 レンタカーのサンプル出力

例8-3に、レンタカー・アプリケーションのサンプル出力を示します。

例8-3 レンタカー・サンプルの出力

Rental is allowed for Carol
Rental is allowed for Alice
Rental is allowed for Alice
Rental is allowed for Carol
Rental is denied for Bob because under age, age was 15, minimum age is 21
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Mar 13, 2009 11:18:00 AM oracle.rules.rl.exceptions.LogWriter flush
INFO: Fired: under age because driver age less than minimum threshold for license number d222
Rental is denied for Bob because under age, age was 15, minimum age is 21
Rental is allowed for Alice
Rental is allowed for Eve

8.7 本番環境でのデシジョン・ポイントの使用に関する必知事項

本番環境では、MDSリポジトリを使用してOracle Business Rulesのディクショナリを格納できます。MDSリポジトリを使用してディクショナリを格納する場合は、「デシジョン・ポイント・ビルダーを使用したデシジョン・ポイントの追加方法」「事前ロード済のディクショナリでデシジョン・ポイントを使用する方法」で示したステップが、ディクショナリにアクセスするように変わります。CarRentalWithDecisionPointUsingMdsRepositoryに、MDSでデシジョン・ポイントを使用するためのサンプル・コードを示します。

デシジョン・ポイントを使用してMDSのディクショナリにアクセスする方法を示すデプロイメント・ステップの完全なサンプルは、「Rules SDKコールを含む等級アプリケーションのサーブレットの追加」を参照してください。

次のコード例は、DecisionPointBuilderと一緒にDictionaryFQNを使用してMDSリポジトリのディクショナリにアクセスする方法を示します。完全なサンプルは、CarRentalWithDecisionPointUsingMdsRepositoryのサンプル・コードにあります。

    static {
        try {
            // specifying the Decision Function and Dictionary FQN
            // loads the rules from the MDS repository.
            m_decisionPoint = new DecisionPointBuilder()
                                .with(DF_NAME)
                                .with(DICT_FQN)
                                .build();
        } catch (SDKException e) {
            System.err.println("Failed to build Decision Point: " +
                               e.getMessage());

「デシジョン・ポイント・ビルダーを使用したデシジョン・ポイントの追加方法」の項の手順と同様に、前の例では次のことを示しています。

  1. 最初のステップで、次のコードによりDecisionPointBuilderインスタンスを作成します。

    new DecisionPointBuilder()
    
  2. String引数を使用するwith()メソッドで、デシジョン・ポイントによって実行されるデシジョン関数の名前を定義します。このメソッドのコールは必須です。

    .with(DF_NAME)
    

    DF_NAMEには、アプリケーションで定義したデシジョン関数の名前を指定します。たとえば、レンタカー・サンプル・アプリケーションでは、これはCarRental.javaCarRentalDecisionFunctionと定義されています。

  3. これ以外の2つのwith()メソッドのうち、いずれか1つのみをコールします。このサンプル・コードでは、DictionaryFQNをコールしてMDSリポジトリにアクセスします。ステップ4のコード例は、ディクショナリ・パッケージとディクショナリ名を使用してDictionaryFQNを作成するルーティングを示します。

    .with(DICT_FQN)
    
  4. DecisionPointインスタンスを作成して戻すために、build()メソッドをコールします。

    protected static final String DICT_PKG = "com.example.rules.demo";
    protected static final String DICT_NAME = "CarRental";
    
    protected static final DictionaryFQN DICT_FQN =
        new DictionaryFQN(DICT_PKG, DICT_NAME);
    protected static final String DF_NAME = "CarRentalDecisionFunction";

8.8 デシジョン・ポイントとデシジョン・トレースに関する必知事項

Rules SDK APIには、デシジョン・トレース処理に役立つメソッドが含まれています。これらのメソッドは、トレース内で使用されているRL名を、関連するディクショナリで使用されている別名に置き換えるよう、デシジョン・トレースを処理します。これにより、デシジョン・トレースのネーミングとOracle Business Rulesディクショナリで使用されているネーミングとの一貫性が保たれます。

デシジョン・トレースを処理するための基本APIには、RuleDictionaryオブジェクトとDecisionTraceオブジェクトが必要です。

RuleDictionary dict = ...;
DecisionTrace trace = ...;
dict.processDecisionTrace(trace);

このコードは、別名によってディクショナリ内と同じ名前を使用するように、デシジョン・トレース内のネーミングを変換する処理コールを示しています。

Rules SDKデシジョン・ポイントAPIには、デシジョン・トレースを構成し、デシジョン・ポイントの起動時に結果のトレースを取得できるようにするメソッドが含まれています。

表8-2に、デシジョン・トレース・オプションを設定するためのデシジョン・ポイントAPIメソッドを示します。

表8-2 デシジョン・ポイントのデシジョン・トレースのメソッド

メソッド 説明

decisionTrace

起動のためのコールから作成されたデシジョン・トレースを取得します。

DecisionTraceを戻します

getDecisionTraceLevel

RuleSessionによって使用されるデシジョン・トレース・レベルを取得します。この値のデフォルトはDECISION_TRACE_OFFです。これはトレース情報が何も収集されていないことを意味しています。可能な値は、DECISION_TRACE_OFFです。

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

戻り型: String

getDecisionTraceLimit

デシジョン・トレースの制限、またはトレースのために取得されるトレース要素の最大数を取得します。

戻り型: int

setDecisionTraceLevel

RuleSessionによって使用されるデシジョン・トレース・レベルを設定します。このパラメータ値はStringです。可能な値は、DECISION_TRACE_OFFです。

DECISION_TRACE_DEVELOPMENT

DECISION_TRACE_PRODUCTION

setDecisionTraceLimit

デシジョン・トレースの制限、またはトレースのために取得されるトレース要素の最大数を設定します。

8.8.1 デシジョン・トレースの使用例

例8-4に、デシジョン・ポイントAPIによるデシジョン・トレースの使用例を示します。

デシジョン・トレースの詳細は、『Oracle SOA SuiteおよびOracle Business Process Management Suiteの管理』のFusion Middleware Controlコンソールでのルール実行のトレースに関する項参照してください。

例8-4 デシジョン・ポイントAPIからのデシジョン・トレースの使用

DecisionPoint dp = new DecisionPointBuilder()
  .with(new DictionaryFQN("com.foo", "Bar"))
  .with("MyDecisionFunction")
  .setDecisionTraceLevel(DecisionPointBuilder.DECISION_TRACE_DEVELOPMENT)
  .setDecisionTraceLimit(24000)
  .build();
 
...
 
DecisionPointInstance dpi = dp.getInstance();
 
dpi.invoke();
 
DecisionTrace trace = dpi.decisionTrace();