2

CEP の例を Drools 5X から 6X に変換しようとしているときに奇妙なエラーが発生しました: - 正確には Drool 6.1.0.Final。

この小さなプロジェクトのインスピレーションの源は、次のリンクにあります:=> PlugTree

Drools がフィールド エクストラクタを作成できないことを示すエラーが表示されます。これは、ドメイン POJO でセッター/ゲッターを作成するのを忘れたときに発生するエラーです。

SEVERE : Unable to build KieBaseModel:rules Unable to create Field Extractor for 'amount'Field/method 'amount' not found for class 'com.sample.Sale': [Rule name='StoreOne - Has Passed it's Sales Record'] java .lang.RuntimeException:クラス 'com.sample.Sale' のフィールド/メソッド 'amount' が見つかりません

私は問題をルール ファイルの 'declare' ステートメントに突き止めました (完全なリストを下にリストします)。

declare Sale
    @role(event)
end

これだけを使用するとエラーが発生しますが (V5 では発生しません)、次の「変更された」宣言ステートメントを使用してもエラーは発生しません。それは何もしません...

declare Sale
    @role(event)
    article : String
    amount : long
    quantity : int
end

それがすることは何もありません。コンパイルして実行しますが、ファクトが挿入 (または認識) されません。

これが私のJavaテストハーネスです:

package com.sample.cep;

import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.event.rule.DebugAgendaEventListener;
import org.kie.api.event.rule.DebugRuleRuntimeEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import org.kie.api.runtime.rule.EntryPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class CEPExample {

    public static void main(String[] args) {


        try {
            // load up the knowledge base & get the kSession
            KieServices ks = KieServices.Factory.get();
            KieContainer kContainer = ks.getKieClasspathContainer();
            KieSession kSession = kContainer.newKieSession("ksession-rules");

            // CEP - get the KIE related configuration container and set the EventProcessing (from default cloud) to Stream
            KieBaseConfiguration config = ks.newKieBaseConfiguration();
            config.setOption( EventProcessingOption.STREAM );


            // Listeners
            kSession.addEventListener( new DebugAgendaEventListener() );
            kSession.addEventListener( new DebugRuleRuntimeEventListener() );

            // To setup a file based audit logger, uncomment the next line 
            // KieRuntimeLogger loggerKie = ks.getLoggers().newFileLogger( kSession, "./logger" );
            // KieRuntimeLogger consoleLogger = ks.getLoggers().newConsoleLogger(kSession); 

            Logger logger = LoggerFactory.getLogger(CEPExample.class);
            logger.info("\n*********************************>>>> Drools CEP Example \n");   

            // Each Event is Inserted into WorkingMemory through an *EntryPoint*
            EntryPoint entryPointStoreOne = kSession.getEntryPoint( "StoreOne" );
            EntryPoint entryPointStoreTwo = kSession.getEntryPoint( "StoreTwo" );


            // Insert EventData into WM for StoreOne
            entryPointStoreOne.insert(new Sale("meat", 40, 5) );
            entryPointStoreOne.insert(new Sale("bananna", 5, 10) );
            entryPointStoreOne.insert(new Sale("pear", 5, 10) );
            entryPointStoreOne.insert(new Sale("yogurt", 5, 50) );
            entryPointStoreOne.insert(new Sale("led TV", 10000, 1) );

            // Insert EventData into WM for StoreTwo
            entryPointStoreTwo.insert(new Sale("meat", 40, 5) );
            entryPointStoreTwo.insert(new Sale("bananna", 5, 10) );
            entryPointStoreTwo.insert(new Sale("pear", 5, 10) );
            entryPointStoreTwo.insert(new Sale("yogurt", 5, 50) );



            // Fire all Rules
            kSession.fireAllRules();


            // Close Logger
            //logger.close();

            // Close the session
            kSession.destroy();

            System.out.println("*** DONE *** ");

        } catch (Throwable t) {
            t.printStackTrace();
        } 

    } // End Method - MAIN




//  // Helper Class to INSERTEVENT
//  private static void insertEvent(EntryPoint entryPoint, Sale sale, String article, long amount, int quantity) {
//  
//      sale.setArticle(article);
//      sale.setAmount(amount);
//      sale.setQuantity(quantity);
//      entryPoint.insert(sale);
//      
//  } // End Class insertEvent  



}// End Class CEPExample

そして、ここに私のルールファイルがあります:

//created on: Nov 28, 2014
package com.sample

import com.sample.Sale;


// Declarations

declare Sale
    @role(event)

    //article : String
    //amount : long
    //quantity : int
end



rule "StoreOne - Has Passed it's Sales Record"
    when
        Number( $totalSalesAmount : intValue, intValue > 1000 )
        from accumulate ( Sale($amount : amount, $quantity : quantity) 
        from entry-point "StoreOne", sum( $amount*$quantity ))
    then
        System.out.println("StoreOne - Has passed its Sales Record!");
end


rule "StoreTwo - has Passed its Sales Record"
    when
        Number( $totalSalesAmount : intValue, intValue > 1000 )
        from accumulate ( Sale($amount : amount, $quantity : quantity) from entry-point "StoreTwo", sum( $amount * $quantity ))
    then
        System.out.println("StoreTwo - Has passed its Sales Record!");  
end

そして私の kmodule.xml ファイル:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="ksession-rules"/>
    </kbase>
</kmodule>

これも関連があると思います-リスナーを使用したコンサルト出力(変更された宣言ステートメント(属性のリスト)用):

Nov 29, 2014 4:31:10 PM org.drools.compiler.kie.builder.impl.ClasspathKieProject notifyKieModuleFound
INFO: Found kmodule: file:/C:/Users/versaggi/workspace-spring-framework/CEPProject/target/classes/META-INF/kmodule.xml
Nov 29, 2014 4:31:10 PM org.drools.compiler.kie.builder.impl.KieRepositoryImpl addKieModule
INFO: KieModule was added:FileKieModule[ ReleaseId=com.versaggi:CEPProject:0.0.1-SNAPSHOTfile=C:\Users\versaggi\workspace-spring-framework\CEPProject\target\classes]
Nov 29, 2014 4:31:14 PM com.sample.cep.CEPExample main
INFO: 
*********************************>>>> Drools CEP Example 

==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:1:24780333:24780333:1:StoreOne:NON_TRAIT:com.sample.cep.Sale@17a1e2d], getObject()=com.sample.cep.Sale@17a1e2d, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreOne, factHandle=[fact 0:1:24780333:24780333:1:StoreOne:NON_TRAIT:com.sample.cep.Sale@17a1e2d], leftTuple=null, originOffset=-1, propagationNumber=2, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:2:20723018:20723018:2:StoreOne:NON_TRAIT:com.sample.cep.Sale@13c354a], getObject()=com.sample.cep.Sale@13c354a, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreOne, factHandle=[fact 0:2:20723018:20723018:2:StoreOne:NON_TRAIT:com.sample.cep.Sale@13c354a], leftTuple=null, originOffset=-1, propagationNumber=3, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:3:16489063:16489063:3:StoreOne:NON_TRAIT:com.sample.cep.Sale@fb9a67], getObject()=com.sample.cep.Sale@fb9a67, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreOne, factHandle=[fact 0:3:16489063:16489063:3:StoreOne:NON_TRAIT:com.sample.cep.Sale@fb9a67], leftTuple=null, originOffset=-1, propagationNumber=4, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:4:33509294:33509294:4:StoreOne:NON_TRAIT:com.sample.cep.Sale@1ff4fae], getObject()=com.sample.cep.Sale@1ff4fae, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreOne, factHandle=[fact 0:4:33509294:33509294:4:StoreOne:NON_TRAIT:com.sample.cep.Sale@1ff4fae], leftTuple=null, originOffset=-1, propagationNumber=5, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:5:27946348:27946348:5:StoreOne:NON_TRAIT:com.sample.cep.Sale@1aa6d6c], getObject()=com.sample.cep.Sale@1aa6d6c, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreOne, factHandle=[fact 0:5:27946348:27946348:5:StoreOne:NON_TRAIT:com.sample.cep.Sale@1aa6d6c], leftTuple=null, originOffset=-1, propagationNumber=6, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:6:26643062:26643062:6:StoreTwo:NON_TRAIT:com.sample.cep.Sale@1968a76], getObject()=com.sample.cep.Sale@1968a76, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreTwo, factHandle=[fact 0:6:26643062:26643062:6:StoreTwo:NON_TRAIT:com.sample.cep.Sale@1968a76], leftTuple=null, originOffset=-1, propagationNumber=7, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:7:26870209:26870209:7:StoreTwo:NON_TRAIT:com.sample.cep.Sale@19a01c1], getObject()=com.sample.cep.Sale@19a01c1, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreTwo, factHandle=[fact 0:7:26870209:26870209:7:StoreTwo:NON_TRAIT:com.sample.cep.Sale@19a01c1], leftTuple=null, originOffset=-1, propagationNumber=8, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:8:1161635:1161635:8:StoreTwo:NON_TRAIT:com.sample.cep.Sale@11b9a3], getObject()=com.sample.cep.Sale@11b9a3, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreTwo, factHandle=[fact 0:8:1161635:1161635:8:StoreTwo:NON_TRAIT:com.sample.cep.Sale@11b9a3], leftTuple=null, originOffset=-1, propagationNumber=9, rule=null, type=0]]
==>[ObjectInsertedEventImpl: getFactHandle()=[fact 0:9:2257152:2257152:9:StoreTwo:NON_TRAIT:com.sample.cep.Sale@227100], getObject()=com.sample.cep.Sale@227100, getKnowledgeRuntime()=org.drools.core.impl.StatefulKnowledgeSessionImpl@527389, getPropagationContext()=PhreakPropagationContext [entryPoint=EntryPoint::StoreTwo, factHandle=[fact 0:9:2257152:2257152:9:StoreTwo:NON_TRAIT:com.sample.cep.Sale@227100], leftTuple=null, originOffset=-1, propagationNumber=10, rule=null, type=0]]
*** DONE *** 

V5 の CEP の例は Web 上にほとんどなく、V6 KIE の例はさらに少ないため、このエラーの原因とその修正方法について考えていただければ幸いです。

4

2 に答える 2

2

declareDRL 言語のステートメントは、2 つの異なる目的に使用できます。

  1. メタデータ ( など@role) を POJO に追加する
  2. ルール (および Java アプリケーション コード) 内で使用するクラスを (Java コードを必要とせずに) 宣言します。

declareこの区別は、ステートメント内に 1 つ以上のフィールドが存在することに由来します。

2 番目の形式を使用する場合、Java コードは宣言されたクラスのオブジェクトを通常の方法で作成できません。(KieBase.getFactType()) を使用してパッケージからクラスを検索し、インスタンスを作成し (FactType.newInstance())、ジェネリック セッター (FactType.set()、 setFromMap())。

POJO セールと宣言されたクラスのセールを同時に行うと、何か問題が発生する可能性は十分にあります。kmodule.xml を使用してビルドを試したことはありませんが (試したことはありません)、Java から KieBuilder を呼び出してエラーをチェックすると、次のようになります (Sale フィールドコメントされていません)。

[main] ERROR org.drools.compiler.kie.builder.impl.AbstractKieModule - Unable to build KieBaseModel:defaultKieBase
New declaration of sale.Sale can't declaredeclares a different set of fields  
existing : ...
declared : ...

ところで、この例ではイベント処理機能を使用しておらず、問題は cEP とはまったく関係ありません。

後で

「標準ファクト」と「イベント ファクト」の挿入との唯一の違いは、エンジンがタイムスタンプ フィールドを追加する必要がある場合があることです (メタ データが属性として既に存在することを示している場合を除きます)。

技術的には、挿入のコーディング方法は、ファクト型の定義方法によって異なります。Java クラス (項目 1 による宣言によって「イベント」フレーバーが追加されます) または本格的な宣言のいずれかです。 、前述のように。プレーン ファクトとイベント ファクトの挿入に関して、これ以上の違いはありません。

また、(パターン評価のために属性を取得するための)アクセスにも違いはありませんが、イベントには追加のタイムスタンプ属性 (明示的な属性にマップされていない限り) があり、テンポラル オペレーターが適用されたときに暗黙的に取得されます。

処理には違いがあり、最も顕著なのは一時的な演算子が (属性ではなく) イベント自体に適用されることです。また、イベントは自動撤回の対象となる場合があり、ウィンドウで選択できます。

于 2014-11-30T09:11:13.880 に答える
2

これを Google Drools Board に投稿したところ、適切な回答が得られました。再投稿は次のとおりです。

デビッド・ソッタラ:

少し歴史が必要です。6.2 およびそれ以前のバージョン: 残念ながら、「宣言」は歴史的に 2 つの非常に (!) 異なるユースケースで過負荷になっています。1 つは、DRL で新しいインライン クラスを定義することです。もう 1 つは、拡張と注釈のために既存のクラスを再宣言することです。前者では、新しいバイトコードが生成されます。後者では、Drools は既存のバイトコードを使用し、クラスの使用に関するメタデータを収集するだけです。

残念ながら、互換性の理由から、ユース ケースを区別するために 2 つのキーワードを使用することはできませんでした。残念ながら、支払う代償はあいまいです。これが、より堅牢な機能を優先して機能全体を非推奨にしようとしている理由です。さらに、属していないパッケージで「外部」クラスを宣言する歴史的な機能が、事態をさらに悪化させました。

あいまいさを解消するために使用する (弱い) 戦略は、基本的に次のとおりです。宣言がクラスパス内の既存のクラスまでたどることができない場合、それは「定義」と見なされ、バイトコードが生成されます。名前が競合する可能性がある場合は、次のルールが適用されます。宣言にフィールドがない場合は、「再宣言」と見なされます。宣言にクラスパス内のクラスとまったく同じフィールドがある場合、それは「再宣言」と見なされます。それ以外の場合、エラーが生成されて報告されます。

これは、コード内で多くのことが発生する可能性があることを示しています。- ルールがクラスパス上の「販売」クラスに関して記述されていて、そのクラスに必要なゲッター/セッターがすべて含まれていない場合、メインの Java コードがそのクラスをインスタンス化するため、宣言は役に立ちません。 -field 宣言は「再宣言」と見なされるため、DRL はクラスパスのクラスを使用します。5.5 は getter だけを探していたのかもしれませんが、それ以降のバージョンでは getter と setter の両方が必要です。- 属性を指定した宣言が実際には「定義」と見なされ、同じ名前と属性を持つクラスが生成されるのだろうかと思いますが、これは Java コードから提供するインスタンスと実際には一致しません。

[編集: Plugtree サイトを確認し、コードを再確認した後]

「Sale」クラスは、以前は org.nicozan.examples.droolsfusion にありました。インポートせずに com.sample.cep.CEPExample クラスで使用するので、com.sample.cep にあると仮定します (!リスナー トレースで確認済み!); ただし、DRL はパッケージ com.sample を使用し、com.sample.cep.Sale ではなく com.sample.Sale をインポートします。したがって、宣言は常に「定義」です。最初の宣言では、属性のない com.sample.Sale が作成され、コンパイラは文句を言います。2 番目のケースでは、ルールは com.sample.Sale (適切な属性を持つ) を使用してコンパイルされますが、別のクラスである com.sample.cep.Sale のインスタンスを挿入するため、ルールは起動しません。

ローカルで定義されたクラスで自己回路をインポートするため、コンパイル時のエラーは発生しません。これは、修正できる可能性があります。@マリオ、フォローアップに基づいて、これを追跡するのを手伝ってもらえますか?

私が書いているように診断することで、これがリストの他の人に対する「宣言」の現在の動作も明確にすることを願っています。

ソリューション:

私が変更したルールファイルで:

**import com.sample.Sale;**

に:

**import com.sample.cep.Sale;**

それはそれを修正しました。しかし、その過程で私が学んだことは、単純な修正よりもはるかに価値がありました. 他の方に伝わりますように…。

于 2014-12-01T18:14:41.630 に答える