2016-04-22 7 views
0

すべてのルールを起動して終了します。私の例では2つのルールしか持っていませんが、それらは相互に関係しています。つまり、ルール2はルール1の後に起動する必要があります。 問題は、ルール1の出力を印刷するだけです。内部的に同じメッセージ(Client is interested in skiing)を出してください。Drools:ルール2は起動せず、ルール1は内部で起動します(ループに入ります)

package com.sample; 

import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 

import org.kie.api.KieServices; 
import org.kie.api.runtime.KieContainer; 
import org.kie.api.runtime.KieSession; 

/** 
* This is a sample class to launch a rule. 
*/ 
public class TestSimpleRules { 

    public static final void main(String[] args) { 
     try { 
      // load up the knowledge base 
      KieServices ks = KieServices.Factory.get(); 
      KieContainer kContainer = ks.getKieClasspathContainer(); 
      KieSession kSession = kContainer.newKieSession("ksession-rules"); 

      // go ! 
      Client client = new Client(); 
      Season season = new Season(); 
      client.addProduct("snowboard"); 
      client.addProduct("ski poles"); 
      season.setSeason("winter"); 
      kSession.insert(client); 
      kSession.insert(season); 
      kSession.fireAllRules(); 
     } catch (Throwable t) { 
      t.printStackTrace(); 
     } 
    } 

    public static class Client { 

     private Set<String> buyingHistory; 
     private String interestedIn; 

     public Client() 
     { 
      buyingHistory = new HashSet<String>(); 
     } 

     public Set<String> getBuyingHistory() { 
      return this.buyingHistory; 
     } 

     public void addProduct(String product) { 
      this.buyingHistory.add(product); 
     } 

     public String getInterestedIn() { 
      return this.interestedIn; 
     } 

     public void setInterestedIn(String interestedI) { 
      this.interestedIn = interestedIn; 
     } 

    } 

    public static class Season { 

     private String currentSeason; 

     public String getSeason() { 
      return this.currentSeason; 
     } 

     public void setSeason(String season) { 
      this.currentSeason = season; 
     } 

    } 

} 

ルール:最初の

package com.javacodegeeks.drools; 

import com.sample.TestSimpleRules.Client; 
import com.sample.TestSimpleRules.Season; 

rule "Rule #1" 
    when 
     c : Client(Client.getBuyingHistory() contains "snowboard", thisBuyingHistory : buyingHistory) and 
     s: Season(Season.getSeason() == "winter") 
    then 
     System.out.println(thisBuyingHistory); 
     c.setInterestedIn("skiing"); 
     System.out.println("Client is interested in skiing"); 
     update(c); 
end 

rule "Rule #2" 
    when 
     c: Client(Client.getInterestedIn() == "skiing" && !(Client.getBuyingHistory() contains "ski jacket"), thisBuyingHistory : buyingHistory) 
    then 
     System.out.println("Ski jacket is recommended"); 
end 

答えて

0

いくつかの技術的な詳細:

  1. クラス名とメソッド呼び出しを修飾しないでください。
  2. フィールドを参照するには、フィールド名だけで十分です。ゲッターを呼び出す必要はありません。
  3. 最外層にandを使用する必要はありません。
  4. フィールドに変数をバインドし、そのフィールドのアサーションを単一の構造体に書き込むことができます。
  5. modifyを使用してファクトを更新することが推奨されます。
  6. オペレータnot containsがあるため、ネゲートされた制約を記述する必要はありません。

(上記の全ては、Droolsのマニュアルから学習することができる。)

rule "Rule #1" 
when 
    c: Client(buyHist: buyingHistory contains "snowboard") 
    s: Season(season == "winter") 
then 
    System.out.println(buyHist); 
    modify(c){ setInterestedIn("skiing") } 
    System.out.println("Client is interested in skiing"); 
end 

rule "Rule #2" 
when 
    c: Client(interestedIn == "skiing", 
       buyingHistory not contains "ski jacket") 
then 
    System.out.println("Ski jacket is recommended"); 
end 

最初のルールを発火のループは、すべての再評価につながるフィールドinterestedInの変形に起因します一部のClientを参照するルール。 "Rule #1"に発砲からの不適格性の制約がないので、再び発動する。

rule "Rule #1" 
when 
    c: Client(buyHist: buyingHistory contains "snowboard" 
       interestedIn != "skiing") 
    s: Season(season == "winter") 
then ... end 

はこのような状況を処理する他の方法があります。安全な救済策はinterestedIn"skiing"に等しくない場合にのみ起動するようにルールを制限することです。ルール属性no-loopはあまり安全ではありません。前述の文書で他のオプションを確認してください。

関連する問題