Oracle Business Rules SDK(Rules SDK)を使用すると、Oracle Business Rulesのディクショナリのルールにアクセスしたり、ルールを作成、変更および実行したり、ディクショナリの内容を操作するアプリケーションを記述できます。 この章では、Rules SDKの概要、およびRules SDKデシジョン・ポイントAPIの使用方法について説明します。
この章の内容は次のとおりです。
詳細は、『Oracle Fusion Middleware Java API Reference for Oracle Business Rules』を参照してください。
Rules SDKは、次の4つの領域で構成されています。
エンジン: ルール実行の準備をします。
ストレージ: ルールのディクショナリとリポジトリへのアクセスを提供します。
編集: ディクショナリ・コンポーネントの作成と変更をプログラムで行えるようにします。
デシジョン・ポイント: ディクショナリにアクセスしたりデシジョン関数を実行するためのインタフェースを提供します。
説明以外の目的でRules SDKのこれらの領域が明示的に区別されることはありません。 たとえば、ルールを編集するには、Rules SDKのストレージ領域を使用して、ディクショナリにもアクセスする必要があります。 Rules SDKがこれらの領域に分割されているのは、個別のRules SDK APIを説明するためではなく、各種の使用モードを説明しやすくするためです。
デシジョン・ポイントAPIを使用すると、ルールを簡単に実行できます。 ほとんどのユーザーは、Oracle JDeveloperのRules Designer拡張機能を使用して、データ・モデル要素、ルール、デシジョン表、ルールセットなどのOracle Business Rulesアーチファクトを作成します。 したがって、ほとんどのユーザーは、Rules SDKのエンジン、ストレージまたは編集機能を直接使用する必要はありません。
Rules SDKのデシジョン・ポイント・パッケージを使用するには、次の3つの重要なクラスを理解する必要があります。
DecisionPoint
: ファクトリの設計パターンに従ってDecisionPointInstance
のインスタンスを作成するヘルパー・クラスです。 ほとんどのアプリケーションには、すべてのアプリケーション・スレッドで共有されるDecisionPoint
オブジェクトが1つ必要です。 コール元はDecisionPoint
のgetInstance()
メソッドを使用して、定義済デシジョン・ポイントのコールに使用できるDecisionPointInstance
のインスタンスを取得します。
DecisionPointInstance
: ユーザーはこのクラスのinvoke()
をコールしてファクトをアサートし、デシジョン関数を実行します。
DecisionPoint
クラスでは、流れるようなインタフェース・モデルがサポートされているため、メソッドを連鎖させることができます。 詳細は、次を参照してください。
http://www.martinfowler.com/bliki/FluentInterface.html
デシジョン・ポイントは、次のようなルール実行のいくつかの側面を管理します。
oracle.rules.rl.RuleSession
オブジェクトの使用
ディクショナリ更新時のディクショナリのリロード
Javaアプリケーションのデシジョン・ポイントを作成するために必要なものは次のとおりです。
MDSリポジトリからロードするディクショナリまたは事前ロード済のoracle.rules.sdk2.dictionary.RuleDictionary
インスタンスの名前。
指定したディクショナリに格納されているデシジョン関数の名前。
この章では、Rules SDKとデシジョン・ポイントAPIの使用方法を示すレンタカー・アプリケーションについて説明します。 このサンプル・アプリケーションは、CarRentalApplication.zip
というZIPファイルで入手できます。 このZIPファイルには、完全なJDeveloperアプリケーションとプロジェクトが含まれています。
Oracle Business Rules固有のサンプルのソースコードを、次のWebサイトからオンラインで入手できます。
http://www.oracle.com/technology/sample_code/products/rules
SOAのサンプルは、次のWebサイトから入手できます。
http://www.oracle.com/technology/sample_code/products/soa
サンプルを使用するには、CarRentalApplication.zip
を適切なディレクトリに解凍します。 レンタカー・アプリケーションのプロジェクトには、ルール・ディクショナリおよびRules SDKを使用したいくつかのJavaサンプルが含まれています。
レンタカー・サンプル・アプリケーションにより、Rules SDKデシジョン・ポイントAPIの使用方法がわかります。
レンタカー・サンプル・アプリケーションを開く手順は、次のとおりです。
Oracle JDeveloperを起動します。
サンプルを解凍したディレクトリにあるレンタカー・アプリケーションを開きます。 たとえば、「ファイル」メニューから「開く」を選択し、「開く」ダイアログでCarRentalApplicationフォルダにナビゲートします。
「開く」ダイアログで「CarRentalApplication.jws」を選択し、「開く」をクリックします。
「アプリケーション・ナビゲータ」で「CarRentalApplication」を開き、「アプリケーション・ソース」と「リソース」を開きます。 CarRental.rules
という名前のOracle Business RulesディクショナリといくつかのJavaソース・ファイルが表示されます。
レンタカー・サンプルでは、事前ロード済のOracle Business RulesディクショナリまたはMDSに格納されているリポジトリでRules SDKデシジョン・ポイントAPIを使用します。 開発環境で作業する場合は、事前ロード済のディクショナリ・シグネチャでデシジョン・ポイントAPIを使用できます。 本番環境では、一般にMDSリポジトリ・シグネチャでデシジョン・ポイントを使用します。
CarRentalディクショナリが事前に定義されており、レンタカー・サンプル・アプリケーションで使用できます。
デシジョン・ポイントAPIを使用するには、デシジョン関数を含むディクショナリを作成する必要があります(レンタカー・サンプル・アプリケーションには、事前定義済のディクショナリとデシジョン関数が用意されています)。
ディクショナリとデシジョン関数を作成するには、次の手順を実行します。
デシジョン・ポイントを使用してアプリケーションを作成する場合、デシジョン関数に追加する次のディクショナリが必要になります。
ルールまたはデシジョン表の作成に使用するデータ・モデル要素を含むディクショナリ。ADF Business Componentsのファクト・タイプを使用する場合は、デシジョン・ポイントのサポート・ディクショナリのリンクを追加する必要があります。 詳細は、第2章「データ・モデル要素の使用」を参照してください。詳細は、第10章「Oracle Business RulesとADF Business Componentsの使用」を参照してください。
ファクト定義を含むディクショナリ。 詳細は、第3章「ファクトとバケット・セットの使用」を参照してください。
用意されているレンタカー・サンプル・アプリケーションのデータ・モデルを表示する手順は、次のとおりです。
Rules Designerで、「ファクト」ナビゲーション・タブをクリックします。
図7-1に示すように、「Javaファクト」タブを選択します。
「Javaファクト」タブに、ディクショナリに組み込まれているファクト・タイプに加えて、インポートされた次の4つのファクト・タイプが表示されます。
Driver
Javaファクトは、プロジェクト内のDriver
Javaクラスからインポートされています。
Denial
Javaファクトは、プロジェクト内のDenial
Javaクラスからインポートされています。
LicenseType
ファクトとVehicleType
ファクトは、Driver
クラスで定義されている、ネストした列挙クラスからインポートされています。
Rules SDKのデシジョン・ポイントを使用する場合は、指定したディクショナリ内のデシジョン関数をコールします。 コールするデシジョン関数には、デシジョン・ポイントの一部として実行される1つ以上のルールセットを含めることができます。
用意されているレンタカー・サンプル・アプリケーションのルールセットを表示する手順は、次のとおりです。
Rules Designerで「CarRentalApplication」を開きます。
「CarRentalApplication」で「リソース」を開きます。
「CarRental.rules」をダブルクリックします。
デシジョン・ポイントAPIを使用する場合は、デシジョン関数を使用してOracle Business Rulesディクショナリを公開します。デシジョン関数の詳細は、第6章「デシジョン関数の使用」を参照してください。
レンタカー・サンプル・アプリケーションのデシジョン関数を表示する手順は、次のとおりです。
Rules Designerで、「デシジョン関数」ナビゲーション・タブをクリックします。 図7-2に示すように、CarRentalディクショナリ内の使用可能なデシジョン関数が表示されます。
CarRentalDecisionFunctionの行を選択し、デシジョン関数のアイコンをダブルクリックします。 図7-3に示すように、「デシジョン関数の編集」ダイアログが開きます。
デシジョン関数の「入力」表には、Driverファクト・タイプの単一の引数が表示されます。
デシジョン関数の「出力」表には、Denialファクト・タイプの単一の引数が表示されます。
デシジョン関数の「ルールセットおよびデシジョン関数」領域の「選択済」ボックスには、「Denial Rules:if-then」が表示されます。
レンタカー・サンプルには、2つのルールセットが含まれています。一方にはIF/THENルールが含まれ、もう一方にはデシジョン表が含まれています。 デシジョン・ポイントを使用する場合は、IF/THENルールまたはデシジョン表、あるいはその両方をアプリケーションで使用できます。
レンタカー・サンプル・アプリケーションのルールを表示する手順は、次のとおりです。
図7-4に示すように、Rules Designerで「Denial Rules:if-then」ルールセットをクリックします。
「Denial Rules:if-then」ルールセットには、次の2つのルールが含まれています。
under age: このルールは、運転者の最低年齢を定義します。 Driver
インスタンスのage
プロパティをグローバルのMinimum driver age
と比較します。 運転者がこの年齢未満の場合、新しいDenial
ファクトがアサートされます。 デシジョン関数へのコールにより、このDenial
ファクトが出力の定義に従って収集されます。また、このルールは、Denial
が作成された理由を示す監査出力を提供するために、ユーザー定義関数audit
もコールします。
too many accidents: このルールは、事故件数の上限しきい値を定義します。事故件数がこの値を超える運転者に対するレンタルは拒否されます。また、このルールは、Denial
が作成された理由を示す監査出力を提供するために、ユーザー定義関数audit
もコールします。
レンタカー・アプリケーションのデシジョン表を表示する手順は、次のとおりです。
図7-5に示すように、Rules Designerで「Denial Rules:decision table」ルールセットをクリックします。
レンタカー・サンプル・アプリケーションには、「Denial Rules: decision table」ルールセットが含まれています。 用意されているデシジョン関数サンプルでデシジョン表を使用するように切り替えるには、図7-6に示すように、デシジョン関数の「選択済」領域から「Denial Rules:if-then」を移動し、デシジョンテーブルを使用して同様のルールを定義する「Denial Rules: decision table」ルールセットをこの領域に追加します。
開発環境でRules SDKを使用する場合は、デシジョン・ポイントAPIを事前ロード済のディクショナリで使用できます。 本番環境では、一般にMDSリポジトリ・シグネチャでデシジョン・ポイントAPIを使用し、ディクショナリはMDSに格納されます。 デシジョン・ポイントの使用方法の詳細は、第7.5項「本番環境でのデシジョン・ポイントの使用に関する必須情報」を参照してください。
Oracle Business Rules固有のサンプルのソースコードを、次のWebサイトからオンラインで入手できます。
http://www.oracle.com/technology/sample_code/products/rules
SOAのサンプルは、次のWebサイトから入手できます。
http://www.oracle.com/technology/sample_code/products/soa
CarRentalProjectプロジェクトには、レンタカー・サンプル・ファイルのCarRentalWithDecisionPointUsingPreloadedDictionary.java
を含むcom.example.rules.demo
パッケージが含まれています。 また、デシジョン・ポイントの様々な使用方法をサポートするいくつかの
.java
ソース・ファイルも含まれています。 表7-1に、レンタカー・サンプルの様々なバージョンの要約を示します。
Rules SDKデシジョン・ポイントAPIの使用方法の詳細は、『Oracle Fusion Middleware Java API Reference for Oracle Business Rules』を参照してください。
表7-1 デシジョン・ポイント・サンプルCarRentalProject内のJavaファイル
ベースJavaファイル名 | 説明 |
---|---|
|
これはすべてのサンプルのベース・クラスです。 CarRentalディクショナリおよび |
|
|
|
MDSを使用してルール・ディクショナリのアクセスとロードを行うデシジョン・ポイントの作成サンプルが含まれています。 本番環境では、ほとんどのアプリケーションはデシジョン・ポイントAPIをMDSで使用します。 |
|
|
|
エンジンAPIの高度な使用サンプルが含まれています。詳細はコメントに記述されています。 |
|
エンジンAPIの高度な使用サンプルが含まれています。詳細はコメントに記述されています。 |
|
ルールとデシジョン表の作成に使用される |
|
ルールとデシジョン表の作成に使用される |
|
同時ユーザーによるデシジョン・ポイントの起動をシミュレートするスレッドとして使用できるクラスが含まれています。 |
デシジョン・ポイントを使用するには、例7-1に示すように、DecisionPointBuilder
を使用してDecisionPoint
インスタンスを作成します。
例7-1 デシジョン・ポイント・ビルダーの使用
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(); } }
例7-1は、DecisionPointBuilder
が流れるようなインタフェース・パターンをサポートしているため、デシジョン・ポイントの作成時にすべてのメソッドを容易に連鎖させることができることを示しています。 DecisionPointBuilder
でデシジョン・ポイントを構成するための最も一般的な3つのメソッドは、with()
という名前を持つようにオーバーロードされます。 各with()
メソッドは、RuleDictionary
型、DictionaryFQN
型またはString
型の単一の引数を使用します。 DecisionPointBuilder
は、類似のsetメソッドとgetメソッド(getDecisionFunction()
、setDecisionFunction()
、getDictionary()
、setDictionary()
、getDictionaryFQN()
、setDictionaryFQN()
)もサポートしています。
例7-1に示すこの連鎖には、次のステップが含まれています。
最初のステップでは、次のようなコードでDecisionPointBuilder
インスタンスを作成します。
new DecisionPointBuilder()
String
引数を使用するwith()
メソッドで、デシジョン・ポイントによって実行されるデシジョン関数の名前を定義します。このメソッドのコールは必須です。
.with(DF_NAME)
DF_NAME
には、アプリケーションで定義したデシジョン関数の名前を指定します。 たとえば、レンタカー・サンプル・アプリケーションでは、DF_NAME
がCarRental.java
でCarRentalDecisionFunction
と定義されています。
これ以外の2つのwith()
メソッドのうち、いずれか1つのみをコールします。 このサンプル・コードでは、指定したデシジョン関数を含む事前ロード済のルール・ディクショナリ・インスタンスを使用しています。 loadDictionary()
メソッドは、ファイルからRuleDictionary
のインスタンスをロードします。 例7-2に、loadDictionary()
メソッドを示します。 詳細は、第7.3.2項「事前ロード済のディクショナリでデシジョン・ポイントを使用する方法」を参照してください。
.with(loadRuleDictionary())
DecisionPoint
インスタンスを作成して戻すために、build()
メソッドをコールします。
DecisionPoint
インスタンスはアプリケーションのすべてのインスタンスで共有されます。このため、静的属性であり、静的ブロックに作成されます。 DecisionPoint
を初期化する別の方法として、DecisionPoint
インスタンスを作成して戻した静的メソッドでm_decisionPoint
属性を初期化する方法があります。
例7-2に、ファイルからRuleDictionaryのインスタンスをロードするloadRuleDictionary()
メソッドを示します。
例7-2 ルール・ディクショナリのロード・メソッド
private static RuleDictionary loadRuleDictionary(){ RuleDictionary dict = null; Reader reader = null; Writer writer = null; try { reader = new FileReader(new File(DICT_LOCATION)); 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();}} if (writer != null) { try { writer.close(); } catch (IOException ioe) {ioe.printStackTrace();}} } return dict; }
レンタカー・サンプルでは、Oracle Business Rulesを使用して複数の同時ユーザーをシミュレートできます。 例7-3に、JavaのExecutorService
インタフェースを使用して、デシジョン・ポイントを起動する複数のスレッドを実行する方法を示します。 ExecutorService
は、Rules SDKデシジョン・ポイントAPIに含まれていません。
例7-3 デシジョン・ポイントを起動するスレッドによる運転者の確認
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)); }
例7-3には、サンプル・アプリケーションの次のコードが含まれています。
エグゼキュータ・サービスを作成します。
ExecutorService exec = Executors.newCachedThreadPool();
CarRental.java
に定義されているcreateDrivers()
メソッドをコールして、Driver
インスタンスのリストを作成します。
List<Driver> drivers = createDrivers();
Driver
インスタンスのリストをループしてdriverリストに運転者を格納します。
ループでDriverCheckerRunnable
インスタンスから複数のスレッドを開始します。 これらのインスタンスはデシジョン・ポイントを開き、各運転者に対してルールを実行します。 このコードの詳細は、第7.3.4項「デシジョン・ポイント・インスタンスの作成および使用方法」を参照してください。
例7-4に、スレッドの完了を待機するコードを示します。
DriverCheckerRunnable
インスタンスはcheckDriver()
メソッドをコールします。 例7-5に、CarRentalWithDecisionPoint
で定義されているcheckDriver()
メソッドを示します。 checkDriver()
メソッドは、Driver
インスタンスによるデシジョン・ポイントの起動を処理します。
例7-5 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(); } } }
例7-5は、次のことを示しています。
次のコードにより、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()); } }
システムにインストールされているレンタカー・サンプルで、例7-2に示すコードのDICT_LOCATION
の値をシステムのディクショナリの場所にあわせて変更します。
システムでレンタカー・サンプルを実行する手順は、次のとおりです。
「アプリケーション・ナビゲータ」で、「編集」メニューから「パスのコピー」を選択します。
CarRentalWithDecisionPointUsingPreloadedDictionary.java
ファイルで、パスの値をDICT_LOCATION
の値に貼り付けます。
CarRentalProjectで、CarRentalWithDecisionPointUsingPreloadedDictionary.javaファイルを選択します。
右クリックしてドロップダウン・リストから「実行」を選択します。
例7-6にサンプル出力を示します。
例7-6 レンタカー・サンプルの出力
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
本番環境では、MDSリポジトリを使用してOracle Business Rulesのディクショナリを格納できます。 MDSリポジトリを使用してディクショナリを格納する場合は、第7.3.1項「デシジョン・ポイント・ビルダーを使用したデシジョン・ポイントの追加方法」と第7.3.2項「事前ロード済のディクショナリでデシジョン・ポイントを使用する方法」で示したステップが、ディクショナリにアクセスするように変わります。 CarRentalWithDecisionPointUsingMdsRepository
に、MDSでデシジョン・ポイントを使用するためのサンプル・コードを示します。
デシジョン・ポイントを使用してMDSのディクショナリにアクセスする方法を示すデプロイメント・ステップの完全なサンプルは、第9.4項「Rules SDKコールを含む等級アプリケーションのサーブレットの追加」を参照してください。
例7-7に、DecisionPointBuilder
でDictionaryFQN
を使用してMDSリポジトリのディクショナリにアクセスする方法を示します。 完全なサンプルは、CarRentalWithDecisionPointUsingMdsRepository
のサンプル・コードにあります。
例7-7 MDSリポジトリでのデシジョン・ポイント・ビルダーの使用
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());
例7-1のステップと同様に、例7-7は次のことを示しています。
最初のステップで、次のコードによりDecisionPointBuilder
インスタンスを作成します。
new DecisionPointBuilder()
String
引数を使用するwith()
メソッドで、デシジョン・ポイントによって実行されるデシジョン関数の名前を定義します。このメソッドのコールは必須です。
.with(DF_NAME)
DF_NAME
には、アプリケーションで定義したデシジョン関数の名前を指定します。 たとえば、レンタカー・サンプル・アプリケーションでは、これはCarRental.java
でCarRentalDecisionFunction
と定義されています。
これ以外の2つのwith()
メソッドのうち、いずれか1つのみをコールします。 このサンプル・コードでは、DictionaryFQN
をコールしてMDSリポジトリにアクセスします。 例7-8に、ディクショナリ・パッケージとディクショナリ名を使用してDictionaryFQN
を作成するルーチンを示します。
.with(DICT_FQN)
DecisionPoint
インスタンスを作成して戻すために、build()
メソッドをコールします。
例7-8 MDSリポジトリでのDictionaryFQNメソッドの使用
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";