2015-01-16 52 views
0

我想在我的規則中使用變量的初始化。 雖然以下簡化的drl不起作用,因爲「init」規則在「有計算機」規則之後執行。drools drl中的變量初始化失敗

package org.drools 
import example.brms.Dossier; 

global example.brms.Session session; 
global java.lang.String TCOMPUTER; 

rule "init" 
salience 10000 
when 
then 
    session.set("TCOMPUTER", "440949"); 
    System.out.println("all set!"); 
end 

rule "has computer" 
when 
    $dossier : Dossier(objects.group("T3").type(TCOMPUTER).exists()) 
then 
    session.info("GOT-COMPUTER", $dossier, TCOMPUTER.getClass()); 
end 

session.set(「TCOMPUTER」,「440949」);在內部調用ksession.setGobal(...)。

我插入2個卷宗事實和時機的規則:

log.debug("Inserting " + facts.size() + " facts"); 
for (Object fact : facts) { 
    ksession.insert(fact); 
} 

/** GO! **/ 
log.debug("ksession.fireAllRules()"); 
ksession.fireAllRules(); 

我得到這個在控制檯:

Starting Engine in PHREAK mode 
Inserting 2 facts 

Reducing to types null <-- why these to lines before fireAllRules ? 
Reducing to types null <-/ 

ksession.fireAllRules() 
Setting ksession global TCOMPUTER to 440949 
all set! 

檔案的類型()方法(objects.group( 「T3」 )。type(TCOMPUTER).exists())打印「Reducing to null null」。

所以看起來規則「有計算機」是在調用ksession.fireAllRules()之前執行的,並且之後調用規則「init」。這會導致變量不被設置。

這是怎麼發生的?

回答

1

只要插入了一個事實,引擎就可以自由地評估這個事實參與的條件元素和約束,因爲看起來合適。在此過程中評估的方法導致的副作用以某種隨機順序出現,除了發動機的奇想之外,什麼也不控制。這甚至在引擎完全由fireAllRules或類似的調用釋放之前發生。只有在右側執行時纔會發生,其順序可能受規則屬性(如顯着性)的影響。

設置全局變量應該由啓動Drools機器的應用程序完成。

+0

我明白了。問題是,我們想要一個沒有特殊設置但具有特定於客戶端規則的通用引擎。所以所有客戶特定的初始化應該在規則文件中。我確實找到了在多個網站上只使用「init」規則的方式,所以它在某種程度上似乎是常見的做法。我還發現,如果我在插入事實之前調用fireAllrules,然後再插入事實並再次調用fireAllrules,以使事情似乎按我的意願解決。但這樣做明智嗎?謝謝 – mvermand

+1

我一直認爲DRL應該具有相當於常量的定義,即使它只是一種宏觀功能。如果你可以做一個初步的fireAllRules來完成全局變量:這是一個很好的解決方法,我不明白應該出現什麼問題 - 只要沒有任何規則會以破壞性的方式觸發事實。 – laune