DROOLS DRL 规则单元与 RuleUnitData 声明不起作用

问题描述 投票:0回答:1

我已将 DROOLS 8 引擎嵌入到一个简单的独立应用程序中进行测试。

到目前为止,我能够实例化 KIE 会话,从磁盘加载并构建 DRL 文件。

如果 DRL 是一个简单的规则文件,当我尝试通过 DRL 文件实现 RuleUnit 时,它可以开箱即用(如指南中所示)https://docs.drools.org/8.44.0.Final/drools -docs/drools/language-reference/index.html#con-drl-rule-units_drl-rules

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
  persons: DataStream<Person>
end

rule "Using a rule unit with a declared type"
  when
    $p : /persons[ name == "James" ]
  then   // Insert Mark, who is a customer of James.
    Person mark = new Person();
    mark.setName( "Mark" );
    persons.append( mark );
end

然后我有一个错误,当它到达

persons.append
的部分时,错误是:

java.lang.NullPointerException: Cannot invoke "org.drools.ruleunits.api.DataStream.append(Object)" because "persons" is null

如果同一个类

MortgageRules
是由java类实现提供的(手写代码)

public class MortgageRules implements RuleUnitData {
    @Getter
    private final DataStream<Person> persons = DataSource.createStream();
}

它有效!似乎

buildAll
没有生成/实例化 RuleUnitData 代码。

主要是

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(); // kieModule is automatically deployed to KieRepository if successfully built.
if (kb.getResults().hasMessages(Message.Level.ERROR)) {
    throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
}

KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
KieSession kSession = kContainer.newKieSession();

var eps = kSession.getEntryPoints();
var eventsStream = kSession.getEntryPoint("DEFAULT");

// Thread pushing Person instances in eventsStream

kSession.fireUntilHalt();
drools rule-engine
1个回答
0
投票

首先,如果你想使用RuleUnit,你需要使用RuleUnit API,你可以从原型示例开始https://docs.drools.org/8.44.0.Final/drools-docs/drools/getting-开始/index.html#first-rule-project_getting-started

您的 Main 类使用传统的 API,因此您需要使用传统的 DRL 语法而不是 RuleUnit。不幸的是,Drools 8 文档没有“传统 DRL 语法”一章,但它是完全支持的。要学习传统的 DRL 语法,请参阅 Drools 7 文档 (https://docs.drools.org/7.74.1.Final/drools-docs/html_single/#drl-rules-con_drl-rules)。我们计划将传统的 DRL 语法章节带回到新版本文档中。很抱歉给您带来不便。

其次,DRL 声明的规则单元有点棘手。事实上,Drools 8 具有通过“声明”生成 RuleUnit java 类的功能,但只有当您还自动生成应用程序 java 代码以使用生成的 RuleUnit 时,它才有意义,因为该类在项目构建之前不存在行家。这样的用例可以在 drools-quarkus 集成中找到,它也生成 REST 端点(https://github.com/apache/incubator-kie-drools/blob/main/drools-quarkus-extension/drools-quarkus-ruleunit -integration-test/src/main/resources/org/drools/quarkus/ruleunit/test/AlertingService.drl)。我提出了一个问题来改进文档:https://github.com/apache/incubator-kie-drools/issues/5752

话虽如此,指导意见是

A) 如果您想将 RuleUnit 与 Quarkus 一起使用并依赖自动生成的 REST 端点,请遵循 drools-quarkus 集成方法。

B) 如果您想在没有 Quarkus 的情况下使用 RuleUnit 或不依赖自动生成的 REST 端点,请编写 Rule Unit java 类而不是“声明”。另请确保使用 RuleUnit API。

C) 如果您习惯传统的 DRL 语法,请使用传统的 DRL 语法而不是规则单元。在这种情况下,您可以继续使用传统的 API,例如 Main 代码。

© www.soinside.com 2019 - 2024. All rights reserved.