Drools:AfterMatchFiringEvent对OR条件的同一规则多次触发?

时间:2017-10-20 22:31:41

标签: java drools rule-engine kie

我在使用org.drools.compiler.lang.api提供的RuleDescrBuilder API构建的DrL文件中使用以下结构。

我触发一个匹配后事件,以跟踪后端中每个规则的命中数。但是,当输入(Predicate)匹配Rule1中的所有给定条件时,它会为一个输入触发多个afterMatchFiredEvents。

import com.objects.Predicate

global com.Util policyUtil

dialect "java"

rule "Rule1:RuleId"
    salience 2147483647
when
    predicate := Predicate(  )  
    (
    eval( policyUtil.evaluate(condition1) ) or
    eval( policyUtil.evaluate(condition2) ) or
    eval( policyUtil.evaluate(condition3) )
then

...

end

rule "defaultRule:defaultRule"
    salience 0
when
    predicate := Predicate(  )  
then

predicate.setValue1("default1");
predicate.setValue2("Default2");
drools.halt();

end

这是赛后事件触发器:

        public void afterMatchFired(AfterMatchFiredEvent event) {
            logger.info("Matching rule Name:: " + event.getMatch().getRule().getName());
            updateHitCountForRule(event.getMatch().getRule().getName());
        }

这就是使用ruledescbuilder的方式。

        RuleDescrBuilder rdb = pdb.newRule();
        CEDescrBuilder<?, ?> cedb = rdb.lhs();
        cedb = cedb.and();
        for(each condition in rule)
            cedb.eval().constraint(constraint).end();

问:为什么对于具有OR条件的相同规则,afterMatchFired多次触发?我假设没有正确使用eval。如果未正确使用eval,使用上述方法构建此类规则集的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这是因为Drools在模式之间处理or运算符的方式。幕后发生的事情是Drools根据您的原始规则创建了3条不同的规则:

rule "Rule1:RuleId 1"
salience 2147483647
when
    predicate := Predicate(  )      
    eval( policyUtil.evaluate(condition1) )
then
    ...
end

rule "Rule1:RuleId 2"
salience 2147483647
when
    predicate := Predicate(  )      
    eval( policyUtil.evaluate(condition2) )
then
    ...
end

rule "Rule1:RuleId 3"
salience 2147483647
when
    predicate := Predicate(  )      
    eval( policyUtil.evaluate(condition3) )
then
    ...
end

如您所见,Drools中的模式之间没有短路or运算符。如果您的所有eval都匹配,则您不仅会收到AfterMatchFiredEvent 3次,而且您的规则的action部分也会被执行3次。

避免这种情况的一种可能方法(即使它有点hacky)是使用事实作为标志来避免多次执行action部分:

rule "Rule1:RuleId"
salience 2147483647
when
    not RuleExecuted()
    predicate := Predicate(  )  
    (
        eval( policyUtil.evaluate(condition1) ) or
        eval( policyUtil.evaluate(condition2) ) or
        eval( policyUtil.evaluate(condition3) )
    )
then
    ...
    insert(new RuleExecuted());
end

在这种情况下,您仍会在听众中收到3个BeforeMatchFiredEvent个事件,但只有1个AfterMatchFiredEvent。您也将收到2个MatchCancelledEvent个活动。

希望它有所帮助,