You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:26:05