ヘッダーをスキップ
Oracle Fusion Middleware Oracle Business Rulesユーザーズ・ガイド
11g リリース1(11.1.1)
B55917-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

C Oracle Business Rulesに関するよくある質問

この付録では、Oracle Business Rulesに関するよくある質問を紹介します。

C.1 JavaオブジェクトをファクトとしてアサートしてからModifyアクションを使用せずに変更すると、ルールが起動しないのはなぜですか。

Javaオブジェクトをアサートした後でModifyアクションを使用せずに変更した場合は、オブジェクトをRules Engineに再アサートする必要があります。 したがって、変更したJavaオブジェクトに関連付けられたルールが起動しない場合は、Rules Engineでルール条件が再評価されておらず、ルールもアクティブ化されていないことを意味します。 このため、Modifyアクションを使用せずにJavaオブジェクトを変更した場合には、オブジェクトをRules Engineに再アサートする必要があります。

C.2 Oracle Business Rules RL LanguageとJavaの相違はなんですか。

Oracle Business Rules RL LanguageとJavaの相違の詳細は、『Oracle Fusion Middleware Oracle Business Rulesランゲージ・リファレンス・ガイド』の付録Aを参照してください。

C.3 RuleSessionでは並行性と同期化はどのように処理されますか。

Oracle Business Rules RuleSessionオブジェクトに対するメソッド・コールは、複数のスレッドによるコールによって、RuleSessionレベルでの例外が発生しないようにスレッド・セーフになっています。ただし、メソッドの実行に排他性やトランザクション保証はありません。Rules Engineの最低レベルのrunメソッドは同期化されるため、共有RuleSessionを持つ2つのスレッドは同時にrunを実行できません。 runへの一方のコールは、もう一方のコールが終了するまで待機する必要があります。

Oracle Business Rules関数は、デフォルトでは同期化されません。 Javaメソッド同様、Oracle Business Rules関数は並行して実行可能であり、プログラマは同期化されたブロックを使用して共有データ(たとえば、結果データを含むHashMap)へのアクセスを保護する必要があります。

一連のアクションがトランザクション形式のように実行されるようにするには、共有オブジェクト関連を同期化する必要があります。ユーザーは、RuleSessionオブジェクト関連は同期化しないでください。これは、RuleSessionメソッドをコールするときにスローされる例外が、RuleSessionオブジェクトの破棄を必要とする場合があるためです。

RuleSessionオブジェクトをOracle Business Rulesで使用するほとんどの場合、各スレッドまたはサーブレット・インスタンスは、ローカルのRuleSessionオブジェクトを作成して使用する必要があります。この使用パターンは、この方法でJDBC接続を使用した場合とおおよそ似ています。

次の例は、共有RuleSessionオブジェクトを使用する方法を示しています。

Thread-1が次のものを含む場合:

ruleSession.callFunctionWithArgument("assert", singleFact1);
ruleSession.callFunctionWithArgument("assert", singleFact2);

Thread-2が次のものを含む場合:

ruleSession.callFunction("run");
ruleSession.callFunction("clear");

この場合、2つのスレッドの実行は、例C-1に示すように進むことがあります。

例C-1 Oracle Business Rulesにおける共有RuleSessionオブジェクトの使用

Thread-1:  ruleSession.callFunctionWithArgument("assert", singleFact1);
Thread-2:  ruleSession.callFunction("run");
Thread-2:  ruleSession.callFunction("clear");
Thread-1:  ruleSession.callFunctionWithArgument("assert", singleFact2);

例C-1では、Thread-1がアサートした2つのファクトの両方が、runへのコール中にRuleSessionに存在することはありません。また、1つのスレッドのみがrunメソッドをコールすることに注意してください。 共有RuleSessionで複数のスレッドからrunをコールできるデザインを使用すると、非常に見つけにくい不具合が作成される可能性があり、パフォーマンス上の利点はありません。

共有RuleSessionオブジェクトに対するすべてのアクセスを同期化して、意図した動作を保証する必要があります。ただし、RuleSessionインスタンスが例外をスローして回復不能になることがあるため、このオブジェクトを同期化オブジェクトとしては使用しないでください。かわりに、別の共有オブジェクトを同期点として使用します。

RuleSessionで使用する共有サーバー・プロセスのプロデューサ/コンシューマ・モデルを想定できます。このモデルでは、複数のスレッドが共有RuleSessionに対してファクトをアサートし、1つのスレッドが定期的にrunをコールし、結果を読み取ってそれらを出力します。これにより、スレッドの競合が生じる可能性はなくなります。これは、2つのコード・セグメントを順次実行する必要があり、混在させることができないためです。 たとえば、例C-2例C-3および例C-4にあるような、共有オブジェクトに関するコード、プロデューサ・コードおよびコンシューマ・コードです。

例C-2 RuleSessionの共有オブジェクト

RuleSession ruleSession;
Object ruleSessionLock = new Object();

例C-3 RuleSessionのプロデューサ・コード

public String addFacts(FactTypeA fa, FactTypeB fb, FactTypeC fc){
   String status = "";
   synchronized(ruleSessionLock){
     try {
       ruleSession.callFunctionWithArgument("assert", fa);
       ruleSession.callFunctionWithArgument("assert", fb);
       status = "success";
     } catch (Exception e) {
       // a method that creates a new RuleSession loads it with rules
       initializeRuleSession();
       status = "failure";
     }
     return status;
}

例C-4 RuleSessionのプロデューサ・コード

public List exec(){
  synchronized(ruleSessionLock){
    try {
      ruleSession.callFunction("run");
      List results = (List)ruleSession.callFunction("getResults");
      ruleSession.callFunction("clearResults");
      return results;
    }  catch (Exception e) {
      // a method that creates a new RuleSession loads it with rules
      initializeRuleSession();
      return null;
    }
  }
}

注意:

複数のスレッドがRuleSessionオブジェクトを共有している場合、複数のスレッドがrunメソッドをコールすると、非常に見つけにくい不具合が作成される可能性があり、パフォーマンス上の利点はありません。

C.4 自己結合を正しく表現するにはどうすればよいですか。

ファクトを使用した場合、Oracle RLのランタイム動作で極端な結果が生成されることがあります。

例C-5のOracle RLコードについて考えます。

例C-5 ファクトFを使用した自己結合

class F {int i; };
rule r1 {
  if (fact F f1 && fact F f2) {
    println("Results: " + f1.i + ", " + f2.i);
  }
}
assert(new F(i:1));
assert(new F(i:2));
run();

例C-5で行がいくつ出力されるか考えます。 f1f2の両方については、同じファクト・インスタンスが一致できるため、答えは4行です。

したがって、例C-5では次の出力が生成されます。

Results: 2, 2
Results: 2, 1
Results: 1, 2
Results: 1, 1

3番目のFのある同じ例を使用すると(たとえば、assert(new F(i:3));)、9つの行が出力されます。また同時に、3番目の語句&& fact F F3が追加されると、27の行が出力されます。

個別のファクトについてすべての組合せおよび順序を見つけようとしている場合は、例C-6に示すように、テスト内に追加語句が必要になります。

例C-6 ファクトFのすべての組合せの検索

rule r1 {
  if (fact F F1 && fact F F2 && F1 != F2) {
    println("Results: " + F1.i + ", " + F2.i);
  }
}

例C-6のコードでは、次の出力が生成されます。

Results: 2, 1
Results: 1, 2

ファクトのすべての組合せを検出する最も簡単な方法は、最速ではなく順序も不同ですが、例C-7に示したコードを使用するものです。

例C-7 ファクトFの組合せの検索

rule r1 {
  if (fact F F1 && fact F F2 && id(F1) < id(F2)) {
    println("Results: " + F1.i + ", " + F2.i);
  }
}

例C-7に示した関数id()をテスト・パターンで実行すると直接比較よりも時間がかかるため、各オブジェクトで一意の値に対してテストするのが最も速い方法になります。たとえば、整数値プロパティoidを、クラスの各インスタンスの固有値を割り当てられたクラスに追加できます。

例C-8は、oid値を使用する同じルールを示しています。

例C-8 高速の完全比較

rule r1 {
  if (fact F F1 && fact F F2 && F1.oid < F2.oid) {
    println("Results: " + F1.i + ", " + F2.i);
  }
}

この問題は、例C-9に示した関数を使用して、Oracle Rules Engineからすべての重複するファクトを削除しようとした場合にも生じることがあります。

例C-9 重複するファクトを取り消す不正な例

rule rRemoveDups {
  if (fact F F1 && fact F F2 && F1.i == F2.i) {
    retract(F2);
  }
}


ただし、このルールは重複のみでなくタイプFのすべてのファクトを削除します。これは、F1およびF2が同じファクト・インスタンスである場合があるためです。 例C-10は、このルールの正しいバージョンを示しています。

例C-10 重複するファクトを取り消す修正された例

rule rRemoveDups {
  if (fact F F1 && fact F F2 && F1 != F2 && F1.i == F2.i) {
    retract(F2);
  }
}

C.5 Oracle Business Rulesではプロパティ変更リスナーをどのように使用しますか。

Oracle Rules Engineは、Java PropertyChangeListener設計パターンをサポートしています。これにより、PropertyChangeSupportクラスを使用するJavaファクトのインスタンスは、プロパティ値が変更されたときに自動的にOracle Rules Engineに通知できます。Javaファクトは、Oracle Rules Engineで使用するこのパターンの実装に必須ではありません。

通常、Oracle Rules Engineに対して以前アサートされたJavaオブジェクトのプロパティ値が変更された場合は、新しいプロパティ値でルールを再評価するため、オブジェクトを再アサートする必要があります。PropertyChangeEventを起動するプロパティの場合、これらのプロパティの値を変更すると、値が変更されて、ファクトがOracle Rules Engineに対して再アサートされます。

PropertyChangeListener設計パターンをクラスに実装する手順は次のとおりです。

  1. このパッケージをクラスにインポートします。

    import java.beans.PropertyChangeSupport;
    
  2. プライベート・メンバー変数をクラスに追加します。

    private PropertyChangeSupport m_pcs = null;
    
  3. コンストラクタで、PropertyChangeSupportオブジェクトを作成します。

    m_pcs = new PropertyChangeSupport(this);
    
  4. 次の各setterに対して、firePropertyChangeへのコールを追加します。

    public void setName( String name ){
        String oldVal =  m_name;
        m_name = name;
        m_pcs.firePropertyChange( "name", oldVal, m_name );
    }
    
  5. addPropertyChangeListenerメソッドを実装します(m_pcsに委任します)。

    public void addPropertyChangeListener(PropertyChangeListener pcl){
        m_pcs.addPropertyChangeListener( pcl );
    }
    
  6. removePropertyChangeListenerメソッドを実装します(m_pcsに委任します)。

    public removePropertyChangeListener(PropertyChangeListener pcl){
        m_pcs.removePropertyChangeListener( pcl );
    }
    

アプリケーションの設計について、変更されたオブジェクトを常に明示的に再アサートするか、またはPropertyChangeListener設計パターンを実装するかを決定する場合は、次の点を考慮してください。

C.6 Oracle Business Rulesでデシジョン・サービスを使用する場合にどのような制限がありますか。

BPELプロセスでBusiness Rulesを使用する場合、次のような制限があります。

他の制限は、付録D「デシジョン・サービスの入力と出力はどのように制限されますか。」を参照してください。

XMLファクト・タイプの参照可能オプションの設定の詳細は、第3.2項「XMLファクトの使用」を参照してください。

C.7 ディクショナリ名またはディクショナリ・パッケージ名を変更するにはどうすればよいですか。

ディクショナリ名またはディクショナリ・パッケージ名を変更するには、Jdeveloperのオプション「ファイル」→「名前の変更」を使用します。「リファクタ」→「名前の変更」は使用しないでください。「リファクタ」オプションは、ディクショナリやディクショナリ・パッケージには適用されません。

詳細は、第2.2.5項「ディクショナリまたはディクショナリ・パッケージの名前の変更方法」および付録D.3「ディクショナリまたはディクショナリ・パッケージの名前の変更」を参照してください。

C.8 ルールにJavaコードを挿入するにはどうすればよいですか。

実際、Javaコードをルールに挿入することはありません。 ただし、ルール条件またはアクションからJavaメソッドを起動できます。

C.9 BPELでデシジョン・サービスにJavaベース・ファクトを使用することはできますか。

Oracle BPEL PMが起動できるのは、デシジョン・サービスとして公開されたデシジョン関数のみであるため、デシジョン関数の入力および出力はXMLファクト・タイプである必要があります。

入力XMLファクトをJavaファクトに変換する場合は、Javaファクト・タイプを使用する既存のルールセットまたはデシジョン関数を使用できます。たとえば、convertFromXMLというルールセットになんらかのルールを作成し、このルールセットをデシジョン関数ルールフロー内でJavaルールセットの前に挿入できます。 同様に、Javaファクトを出力XMLファクトに変換するルールセットを作成し、このルールセットをデシジョン関数ルールフロー内でJavaルールセットの後に挿入できます。

また、ルールでJavaファクト・タイプのプロパティのみを使用し、メソッドやフィールドを使用しない場合は、次の手順でJavaファクト・タイプをXMLファクト・タイプで置換できます。

  1. Javaファクト・タイプを削除します(最初にファクト・タイプおよびプロパティの別名を慎重にメモしてください)。

  2. 類似するXMLファクト・タイプをインポートし、そのファクト・タイプおよびプロパティの別名を、削除したJavaファクト・タイプおよびプロパティと同じになるように編集します。

C.10 BPELデシジョン・サービスでデバッグ機能を有効化するにはどうすればよいですか。

BPELデシジョン・サービスに対するルールセット実行中のデバッグ出力を有効化するには、SOAルール・ロガーを有効化します。 SOAルール・ロガーがTRACEレベルに設定されていると、watchAllの出力がSOA診断ログに記録されます。 Fusion Middleware Controlコンソールを使用してロギング・レベルを変更した場合、指定のレベルを使用するようにアプリケーションを再デプロイする必要はありません。

SOAのoracle.soa.service.rulesおよびoracle.soa.services.rules.obrtraceロガーの使用の詳細は、『Oracle Fusion Middleware Oracle SOA Suite管理者ガイド』を参照してください。

C.11 Oracle Business Rulesでバージョニングをサポートするにはどうすればよいですか。

Oracle Business Rulesでは、バージョニングが次の2つの方法でサポートされています。

注意: サーバー・アプリケーションは、ディクショナリ変更がMDS内で参照可能になると、その変更にレスポンスできます。ルール・サービス・エンジン(デシジョン・サービス)では、これが自動的に実行されます。非SCAアプリケーションの場合、これはRuleRepositoryインタフェースを使用して実行できます。この時点では、ドラフト・バージョンをサポートするには、MDSのサンドボックス機能を使用します。Oracle Business RulesのRuleRepositoryインタフェースでは、これがサポートされています。

C.12 ルールおよびルールセットで優先度を使用する場合、優先度の順序はどうなりますか。

優先度は最上位から最下位の順序で、優先度の高いルールまたはルールセットから先に実行されます。たとえば、優先度1から4のルールを作成すると、各ルールは4、3、2、1という実行優先度の順に実行されます。

ただし、ルールの純粋な宣言モデルが損なわれるため、できるだけ優先度の使用を避ける必要があることに注意してください。 多数の優先度を使用していることに気づいた場合の最善策は、通常、ルール間の依存性を表すguard句を使用するためルールを試行して再構築し、特定の順序で実行することを意図する場合はルールを複数のルールセットに分割することです。詳細は、第4.5.5項「ルールの優先度の設定方法」を参照してください。

C.13 xsd:string入力済要素を持つXMLスキーマをタイプJAXBElementとしてインポートするのはなぜですか。

JAXB 2.0仕様では、minOccurs="0"nillable="true"の要素のデフォルト・タイプ・マッピングはJAXBElement<T>となります。Tは、要素に対して定義されているタイプのデフォルト・マッピングです。 たとえば、xsd:stringJAXBElement<String>xsd:intJAXBElement<Integer>xsd:integerJAXBElement<BigInteger>にそれぞれマップされます。 これは、nillable="true"は、ドキュメントに定義されていない要素(minOccurs=0を使用)と定義されているが属性nil="true"を持つ要素の間で、ユーザーがセマンティックの相違を定義済であることを意味しているためです。これは微妙な違いであり、通常は不明な値および「値なし」であることがわかっている値との違いを定義するために使用されます。

ルールでJAXBElementタイプのプロパティを使用するには、そのプロパティが非NULLかどうかを最初にチェックする必要があります。その後、"value"プロパティまたはgetValue()メソッドを使用して、基礎となるタイプの値を取得できます。

fact FactType1 &&
    FactType1.prop1 != null &&
    FactType1.prop1.value == "abc"

または、nillable要素がタイプJAXBElement<T>ではなくタイプTにマップされるように、カスタマイズしたJAXBバインディングを定義できます。 ただし、これでは存在しない要素およびnil要素の違いを判別できなくなるため、無駄な変換です。この場合、nillable属性はあまり役立ちませんが、JavaでObjectタイプのフィールドがデフォルトでNULLに初期化されたり、明示的にNULLに初期化できるのと同様に、文書では要素をnilとして明示的に定義できます。

そのためには複数の方法があります。 いずれの場合も、これらの属性を最上位レベルのxsd:schema要素の開始タグに追加します。

xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0"
  1. すべてのプロパティでバインディングを使用するように指定するには、これをxsd:schemaの開始タグ内の先頭に追加します。

    <xsd:annotation>
        <xsd:appinfo>
            <jaxb:globalBindings generateElementProperty="false"/>
        </xsd:appinfo>
    </xsd:annotation>
    
  2. 特定のプロパティでのみバインディングを使用するように指定するには、必要な各要素に次のような注釈を追加します。

    <xsd:element name="stringElement2" type="xsd:string" minOccurs="0" nillable="true">
        <xsd:annotation>
            <xsd:appinfo>
                 <jaxb:property generateElementProperty="false" />
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:element>
    
  3. 外部カスタマイズ・ファイルに定義を追加し、スキーマをデータ・モデルに追加する際に引数として渡します。この方法は、SchemaBrowserクラスをプログラムでコールし、Rules Designerで公開しない場合にのみ可能です。

C.14 Javaクラスに加えた変更がデータ・モデルに反映されないのはなぜですか。

SCA-INF/classesディレクトリでコンパイルされたクラスはインポートしないでください。 このディレクトリのクラスを変更すると、データ・モデルにリロードできなくなります。

C.15 Rules SDKを使用して式にNULLを含めるにはどうすればよいですか。

次のRules SDKコードを使用すると、null値を含めることができます。

SimpleTest test = pattern.getSimpleTestTable().add();
test.getLeft().setValue(attr);
test.setOperator(Util.TESTOP_NE);
test.getRight().setValue("null");

C.16 ディクショナリを格納するためのリポジトリとしてWebDAVがサポートされていますか。

Oracle Fusion Middleware 11gリリース1(11.1.1)のOracle Business Rulesでは、ディクショナリを格納するためにWebDAV(Web Distributed Authoring and Versioning)リポジトリはサポートされていません。 Oracle Business Rulesでは、MDS(ファイルまたはデータベースを使用)リポジトリを使用したディクショナリの格納がサポートされています。