DRL声明的RuleUnitData无法实例化,调用persons.append时触发空指针
问题分析与解决:DRL声明RuleUnitData子类导致NullPointerException
核心问题
在DRL中通过declare关键字定义继承RuleUnitData的规则单元数据类(如MortgageRules)时,Drools生成的类不会自动初始化其中的DataStream或DataSource字段,直接导致规则执行时调用persons.append()出现NullPointerException。而手写Java类时,你显式通过DataSource.createStream()初始化了DataStream,因此可以正常工作。
解决方案
方案1:在DRL声明中初始化DataStream字段
修改DRL中的MortgageRules声明,为persons字段添加初始化逻辑,确保字段不为null:
package org.mortgages; unit MortgageRules; import org.drools.ruleunits.api.RuleUnitData; import org.drools.ruleunits.api.DataStream; import org.drools.ruleunits.api.DataSource; declare Person name : String dateOfBirth : String address : String end declare MortgageRules extends RuleUnitData // 显式初始化DataStream persons: DataStream<Person> = DataSource.createStream() end rule "Using a rule unit with a declared type" when $p : /persons[ name == "James" ] then Person mark = new Person(); mark.setName( "Mark" ); persons.append( mark ); end
方案2:使用RuleUnit API执行规则(推荐)
RuleUnit设计初衷是通过专用API运行,而非直接在普通KieSession中使用。修改主程序代码,改用RuleUnit执行方式:
KieServices ks = KieServices.Factory.get(); KieRepository kr = ks.getRepository(); KieFileSystem kfs = ks.newKieFileSystem(); drlStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mortgage.drl"); kfs.write("src/main/resources/KBase1/mortgage.drl", ks.getResources().newInputStreamResource(drlStream)); KieBuilder kb = ks.newKieBuilder(kfs); kb.buildAll(); if (kb.getResults().hasMessages(Message.Level.ERROR)) { throw new RuntimeException("Build Errors:\n" + kb.getResults().toString()); } KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId()); // 获取RuleUnit实例并初始化数据 RuleUnitProvider ruleUnitProvider = RuleUnitProvider.get(); MortgageRules ruleUnitData = ruleUnitProvider.createRuleUnitInstance(kContainer, MortgageRules.class); // 向persons流中添加数据 new Thread(() -> { Person james = new Person(); james.setName("James"); ruleUnitData.getPersons().append(james); }).start(); // 启动规则执行 ruleUnitProvider.runUntilHalt(ruleUnitData);
方案3:检查构建配置
确保构建配置中包含Drools代码生成插件,RuleUnit的DRL声明需要编译时生成对应Java类。如果使用Maven,需添加以下插件:
<plugin> <groupId>org.drools</groupId> <artifactId>drools-maven-plugin</artifactId> <version>${drools.version}</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
关键说明
- DRL中声明的
RuleUnitData子类默认不会自动初始化数据源字段,必须显式初始化或通过RuleUnit API管理实例 - 普通
KieSession并不完全适配RuleUnit执行模式,推荐使用RuleUnit专用API运行规则单元
内容的提问来源于stack exchange,提问作者nicola.p
相关产品推荐
相关产品推荐

