2015-01-16 53 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