RHDM版本升级后,Drools eval事实过滤中布尔值带引号失效问题
问题概述
我使用带布尔条件列的引导式决策表,谓词为"$param" == "NA" ? true : "$param" == boolFlag,该逻辑在RHDM 7.52.0.Final-redhat-00008环境中可正常生成并运行DRL规则,但在本地RHDM 7.59.0.Final-redhat-00009环境中失效。
关键现象:
- 仅当
eval用于事实过滤(如f : Foo(eval(...)))时,带引号的布尔值表达式(如"true" == copy)失效,移除引号写成true == copy才能正常工作; - 若移除
eval直接写事实条件(如f : Foo("true" == copy)),或把eval放在事实过滤外部(如单独的eval("true" == true)),带引号的布尔值表达式均能正常运行。
复现代码
DRL规则代码
package com.myspace.test; rule "init" salience 100 dialect "mvel" when eval(true) then drools.setFocus("AG1"); end rule "test" salience 99 agenda-group "AG1" activation-group "AVG1" dialect "mvel" when // f : Foo(eval("true" == "NA" ? true : "true" == copy)) // 本地不生效 // f : Foo(eval("true" == "NA" ? true : true == copy)) // 本地生效 // f : Foo("true" == copy) // 本地生效 // eval("true" == true) // 本地生效 f : Foo() then System.out.println("Name = " + f.getName()); // copy name to Bar Bar b = new Bar(); b.setName(f.getName()); insert(b); end
Foo实体类
package com.myspace.test; public class Foo implements java.io.Serializable { static final long serialVersionUID = 1L; @org.kie.api.definition.type.Label("Name") private java.lang.String name; @org.kie.api.definition.type.Label(value = "Copy") private boolean copy; // 构造方法、getter/setter省略 }
Bar实体类
package com.myspace.test; public class Bar implements java.io.Serializable { static final long serialVersionUID = 1L; private java.lang.String name; // 构造方法、getter/setter省略 }
根因排查指导
核对MVEL版本差异
RHDM不同版本依赖的MVEL版本可能存在变更,MVEL对字符串与布尔值的比较逻辑可能调整。查看两个RHDM版本的依赖树,确认MVEL版本号,对比MVEL官方版本变更日志,重点关注类型比较规则的修改——比如旧版本可能自动将字符串"true"转为布尔值再比较,新版本严格按类型匹配,导致字符串与布尔值直接比较永远返回false。检查RHDM版本变更记录
查阅RHDM 7.52.0到7.59.0的官方Release Notes,重点关注DRL解析、eval表达式处理、事实过滤逻辑相关的更新,确认是否有对类型严格性的提升,比如限制了不同类型值的隐式转换比较。调试表达式执行细节
在本地环境开启Drools调试日志(设置org.drools日志级别为DEBUG),查看eval表达式在事实过滤中的执行过程,观察字符串"true"与布尔变量copy比较时的实际类型转换结果,确认是否因类型不匹配导致返回false。单独验证MVEL表达式行为
在不同MVEL版本的测试环境中,单独执行"true" == true和"true" == 布尔变量这类表达式,对比结果差异,验证是否是MVEL的类型比较规则变化导致问题。检查决策表生成DRL的逻辑
确认决策表生成DRL的工具/代码在新版本中是否有变化,是否应该自动移除布尔值的引号,或者生成显式类型转换的代码(比如Boolean.parseBoolean("$param") == boolFlag)。
内容的提问来源于stack exchange,提问作者yoon wai

