Drools查询结果受agenda-group及条件顺序影响异常求助
Drools 7.52.0.Final 查询结果受agenda-group与条件顺序影响的原因分析
问题背景
我使用Drools 7.52.0.Final版本,有一段自动生成的规则,其中calculateValue查询包含三个核心步骤:
- 获取OrderItem的price并转为Optional
- 若Optional非空,计算后赋值给$calculatedValue
- 若Optional为空,直接赋值
实际测试中发现查询结果受两个因素影响:
- agenda-group的使用
- 查询中or条件的顺序
具体表现:
- 非空分支在前的查询,无论是否使用agenda-group均能正常执行;
- 空值分支在前的查询,仅在不使用agenda-group时正常;结合agenda-group使用时(案例2),规则的then部分完全不执行,其余案例(1、3、4)均正常。
规则代码示例
rule "Rule Filter" agenda-group "Rule-ag" when checkOrderItem( ) then drools.setFocus("Action-ag"); end query "checkOrderItem" ( calculateValue( $calculatedValue, $orderItem; ) and Optional( $calculatedValue.orElse(null) > 10.0 ) from Optional.empty() ) end query "calculateValue" ( Optional $calculatedValue, OrderItem $oi ) ( OrderItem( $optionalPrice := Optional.of(price) ) from $oi and ( ( Optional( !this.isEmpty(), $optionalPriceVal : this.get() ) from $optionalPrice and Double( $modifiedPrice : (this *3) ) from $optionalPriceVal and Optional( $calculatedValue := this ) from Optional.ofNullable($modifiedPrice) ) or ( Optional( this.isEmpty() ) from $optionalPrice and Optional( $calculatedValue := this ) from $optionalPrice ) ) ) end rule "Rule Action" agenda-group "Action-ag" when then insert(new Result(true, "rule-with-agenda-group1.drl")); end
原因分析
1. Or条件顺序的短路匹配逻辑
Drools查询中的or分支遵循从左到右的短路匹配逻辑:一旦某条分支匹配成功,就会停止后续分支的尝试。
- 非空分支在前时:只要OrderItem的price非空,就会优先执行计算分支,正确绑定$calculatedValue,上层
checkOrderItem查询能顺利匹配。 - 空值分支在前时:若price非空,空值分支会先尝试匹配(
Optional(this.isEmpty())不成立),此时Drools会回溯到or分支尝试下一条,但这个过程中可能残留无效的变量绑定状态——空值分支虽然匹配失败,但可能已经对$calculatedValue做了无效赋值,导致后续非空分支的正确绑定被覆盖,最终上层查询无法匹配。
2. Agenda-group焦点机制的叠加影响
Agenda-group通过setFocus控制规则执行的优先级和时机,当结合使用时,会改变工作内存的状态跟踪逻辑:
- 不使用agenda-group时,规则和查询在工作内存初始化后立即执行,变量绑定的回溯逻辑能正常清理无效状态,空值分支在前的查询仍能通过后续分支完成匹配。
- 使用agenda-group时,
Rule Filter先触发并切换焦点到Action-ag,查询的执行时机被延后,此时Drools的状态清理机制可能出现异常——空值分支匹配失败后留下的无效变量绑定未被彻底清理,导致非空分支的匹配结果无法正确传递到上层查询,最终checkOrderItem查询匹配失败,Rule Action的then部分自然不会执行。
另外,Drools 7.x版本在处理查询嵌套or分支的变量绑定时,本身存在回溯逻辑的边界缺陷,尤其是结合agenda-group的焦点切换时,变量状态的一致性无法保证,这是导致该现象的底层诱因。
内容的提问来源于stack exchange,提问作者Julia Strahova
相关产品推荐
相关产品推荐

