如何解决DRools:无循环 true 属性不适用于 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
是一个 vlass,它实现了 AgendaEventListener
接口,在方法 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”。就好像我们退出了当前的“火规则”流程,然后用新数据重新运行所有规则。由于是新运行,没有以前的执行,因此 no-loop
不适用。
这与 insert
相比(例如)。当您在规则的 RHS 中调用 insert
时,引擎只会重新评估当前运行中的后续规则。在这种情况下,“无循环”确实适用,因为我们仍在同一运行中,并且之前的执行仍然存在。
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
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。