DRools:无循环 true 属性不适用于 update() 方法推断
DRools: no-loop true attribute not working with update() method inference
我有一个简单的 DRools 包,其中包含一条规则,其 DRL 源如下:
package com.rules.standard.isolatesFlags.GRUPPI_FAMIGLIE;
import org.package.path.ResultIsolate;
global org.apache.log4j.Logger logger;
function void finalizeIsolate(ResultIsolate isolate, Logger logger) {
/* implementation */
}
function void setIsolateCSIFlag(ResultIsolate isolate, Integer csiAlarm, Logger logger) {
/* implementation */
}
rule "ConfirmEsccolWasplab"
dialect "mvel"
salience 10
enabled true
no-loop true
when
$a : ResultIsolate( deviceId == "WASPLAB_core" , microId == "h_W_ESCO" )
$b : ViewPlateResult( plateStatus >= 60 , plateCode == "h_CCA" ) from $a.isolatePlates
then
finalizeIsolate($a,logger);
setIsolateCSIFlag($a,new Integer(-1),logger);
update($a);
end
然后,在我的 Java EJB 中,我执行如下规则:
kSession = kbase.newStatefulKnowledgeSession();
kSession.addEventListener(ruleListener);
logger.debug("Injecting global variabiles isTest and logger and EJB MicroRulesUtils into StatefulKnowledgeSession");
kSession.setGlobal("logger", org.apache.log4j.Logger.getLogger(MicroBusinessIsolateFlagsImpl.class));
kSession.insert(resultIsolate);
kSession.fireAllRules((int)MicroBusinessIsolateFlags.MAX_FIREABLE_RULES); //1000
ruleListener
是一个实现 AgendaEventListener
接口的 vlass,在方法 beforeActivationFired
的实现中,我计算了每个事实激活和触发的规则数量。
事实上,在我的 EJB 中,在触发规则之后,我检查:
if(ruleListener.getNumberOfFiredRules() >= MAX_FIREABLE_RULES) {
logger.info("Isolate flags rules fired more than ",MicroBusinessIsolateFlags.MAX_FIREABLE_RULES, " times. Check configuration to prevent inference loops from occurring.");
logger.info(ruleListener.getRulesActivationsLog()); //print fired rules and how many times
}
因此,总是会显示此警告。这怎么可能?正如我所说,我有一个包含单个规则和 no-loop true
属性的包,我希望规则本身不会因其 RHS 而被激活。但它是。那是一个错误吗?
此外,在添加其他未激活的包规则(包含的规则的条件不匹配)之后,我总是将这些规则记录为已触发 1000 次(循环)。
我正在使用 DRools 5.0.1 并且不允许升级它。
不,这不是错误。这就是该功能的工作原理。
调用 update
在功能上等同于调用 'fireRules'。就好像我们退出了当前的 'fire rules' 流程,然后使用新数据重新运行所有规则。由于是新的 运行,没有以前的执行,所以 no-loop
不适用。
这是与 insert
(例如)的对比。当您在规则的 RHS 中调用 insert
时,引擎只会重新评估 当前 运行 中的后续规则。在这种情况下,'no-loop'确实适用,因为我们仍然处于相同的运行,并且之前的执行仍然存在。
no-loop
旨在防止同一规则在一次规则执行中多次触发。它并不是为了防止规则在多次执行中触发。
要使您的规则不在更新时触发,您需要修改左侧以排除右侧设置的条件。由于您省略了 setIsolateCSIFlag
函数的定义,因此我将编写一个简单的示例:
rule "EXAMPLE"
no-loop
when
Address( $locality: locality )
$purchase: Purchase( sum > 0, tax == null )
then
$purchase.calcualteTaxForLocality($locality); // sets 'tax' to some value
update( $purchase );
end
由于 Purchase 实例现在有一个非空 tax
值,因此在 update
之后规则不会再次触发。在您的情况下,您应该根据 setIsolateCSIFlag
方法实际执行的任何操作更新条件 (LHS) 以不触发。或者,也不要调用 update
.
我有一个简单的 DRools 包,其中包含一条规则,其 DRL 源如下:
package com.rules.standard.isolatesFlags.GRUPPI_FAMIGLIE;
import org.package.path.ResultIsolate;
global org.apache.log4j.Logger logger;
function void finalizeIsolate(ResultIsolate isolate, Logger logger) {
/* implementation */
}
function void setIsolateCSIFlag(ResultIsolate isolate, Integer csiAlarm, Logger logger) {
/* implementation */
}
rule "ConfirmEsccolWasplab"
dialect "mvel"
salience 10
enabled true
no-loop true
when
$a : ResultIsolate( deviceId == "WASPLAB_core" , microId == "h_W_ESCO" )
$b : ViewPlateResult( plateStatus >= 60 , plateCode == "h_CCA" ) from $a.isolatePlates
then
finalizeIsolate($a,logger);
setIsolateCSIFlag($a,new Integer(-1),logger);
update($a);
end
然后,在我的 Java EJB 中,我执行如下规则:
kSession = kbase.newStatefulKnowledgeSession();
kSession.addEventListener(ruleListener);
logger.debug("Injecting global variabiles isTest and logger and EJB MicroRulesUtils into StatefulKnowledgeSession");
kSession.setGlobal("logger", org.apache.log4j.Logger.getLogger(MicroBusinessIsolateFlagsImpl.class));
kSession.insert(resultIsolate);
kSession.fireAllRules((int)MicroBusinessIsolateFlags.MAX_FIREABLE_RULES); //1000
ruleListener
是一个实现 AgendaEventListener
接口的 vlass,在方法 beforeActivationFired
的实现中,我计算了每个事实激活和触发的规则数量。
事实上,在我的 EJB 中,在触发规则之后,我检查:
if(ruleListener.getNumberOfFiredRules() >= MAX_FIREABLE_RULES) {
logger.info("Isolate flags rules fired more than ",MicroBusinessIsolateFlags.MAX_FIREABLE_RULES, " times. Check configuration to prevent inference loops from occurring.");
logger.info(ruleListener.getRulesActivationsLog()); //print fired rules and how many times
}
因此,总是会显示此警告。这怎么可能?正如我所说,我有一个包含单个规则和 no-loop true
属性的包,我希望规则本身不会因其 RHS 而被激活。但它是。那是一个错误吗?
此外,在添加其他未激活的包规则(包含的规则的条件不匹配)之后,我总是将这些规则记录为已触发 1000 次(循环)。
我正在使用 DRools 5.0.1 并且不允许升级它。
不,这不是错误。这就是该功能的工作原理。
调用 update
在功能上等同于调用 'fireRules'。就好像我们退出了当前的 'fire rules' 流程,然后使用新数据重新运行所有规则。由于是新的 运行,没有以前的执行,所以 no-loop
不适用。
这是与 insert
(例如)的对比。当您在规则的 RHS 中调用 insert
时,引擎只会重新评估 当前 运行 中的后续规则。在这种情况下,'no-loop'确实适用,因为我们仍然处于相同的运行,并且之前的执行仍然存在。
no-loop
旨在防止同一规则在一次规则执行中多次触发。它并不是为了防止规则在多次执行中触发。
要使您的规则不在更新时触发,您需要修改左侧以排除右侧设置的条件。由于您省略了 setIsolateCSIFlag
函数的定义,因此我将编写一个简单的示例:
rule "EXAMPLE"
no-loop
when
Address( $locality: locality )
$purchase: Purchase( sum > 0, tax == null )
then
$purchase.calcualteTaxForLocality($locality); // sets 'tax' to some value
update( $purchase );
end
由于 Purchase 实例现在有一个非空 tax
值,因此在 update
之后规则不会再次触发。在您的情况下,您应该根据 setIsolateCSIFlag
方法实际执行的任何操作更新条件 (LHS) 以不触发。或者,也不要调用 update
.