Drools执行DRL规则retract fact时出现NullPointerException问题咨询
问题结论
这是Drools 7.53.0.Final及更早7.x版本的已知缺陷。
问题根源
retract操作的核心逻辑是根据传入的实例找到工作内存中对应的Fact句柄,再执行删除。你直接传入新创建的、未插入过工作内存的实例时,Drools内部获取Fact句柄的逻辑返回null,旧版本未做空值校验直接操作该空对象就会触发NullPointerException。
两种模式下的表现差异由匹配逻辑决定:
- 标识模式下:通过对象引用匹配,新创建的
String实例从来没有插入过工作内存,永远匹配不到对应句柄,必然触发异常 - 相等模式下:通过对象
equals结果匹配,只要之前插入过值为"myString"的String实例,就能匹配到有效句柄,因此不会报错
规避方案
- 方案1:优先在规则条件段(when)匹配目标Fact,绑定变量后再执行删除,这是最符合Drools规则设计规范的写法,正确示例如下:
rule "retract_correct" no-loop when $s: String(this == "myString") then retract($s) end
- 方案2:如果确实需要在后果段(then)动态删除不确定是否存在的Fact,先校验Fact句柄是否存在再执行操作,示例如下:
rule "retract_with_check" no-loop when then Object toDel = new String("myString"); FactHandle handle = kcontext.getKieRuntime().getFactHandle(toDel); if (handle != null) { retract(handle); } end
- 方案3:升级Drools版本到7.57.0.Final及以上,该空指针问题已在后续版本修复,对不存在的Fact执行
retract时会抛出语义更明确的异常而非空指针。
内容的提问来源于stack exchange,提问作者Savers80
相关产品推荐
相关产品推荐

