【问题标题】:Executing multiple Drools rules in chain - Spring Java application在链中执行多个 Drools 规则 - Spring Java 应用程序
【发布时间】:2019-03-01 16:15:53
【问题描述】:

我通过 Maven 依赖项将 Drools 与我的 Java Spring 应用程序集成。我创建了 KieContainer bean:

@Bean
public KieContainer kieContainer (){
    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kieFileSystem = kieServices.newKieFileSystem();

    File dir = new File("src/main/resources/rules");
    File[] directoryListing = dir.listFiles();
    if (directoryListing != null) {
        for (File child : directoryListing) {
            kieFileSystem.write(child.getName(), "UTF-8");
        }
    }

    KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
    kieBuilder.buildAll();

    KieModule kieModule = kieBuilder.getKieModule();
    return kieServices.newKieContainer(kieModule.getReleaseId());

}

调试时,我可以看到 /src/main/resources/rules 位置下的两个 .drl 文件都已成功添加!

此外,我创建了 KieSession:

public String executeRule(FieldCDO field, ContractCDO contract, FieldValueCDO fieldValue){
    KieSession kieSession = kieContainer.newKieSession();
    kieSession.setGlobal("fieldValue", fieldValue);
    kieSession.insert(field);
    kieSession.fireAllRules();
    kieSession.dispose();}

然后,我创建了 jUnit 测试,我从上面调用了 executeRule() 方法,并传递了对象 FieldCDO、ContractCDO、FieldValueCDO。

我的规则如下所示。 Rule1.drl

import com.calliduscloud.clma.domain.FieldCDO;
import com.calliduscloud.clma.domain.ContractCDO;
import com.calliduscloud.clma.domain.FieldValueCDO;

global com.calliduscloud.clma.domain.FieldValueCDO fieldValue;

dialect "mvel"

rule "Change contract field value 1"
     when
          field: FieldCDO(id == 1)
          contract: ContractCDO(id == 1);
     then
         fieldValue.setFieldValue("11111");
end

Rule2.drl

import com.calliduscloud.clma.domain.FieldCDO;
import com.calliduscloud.clma.domain.ContractCDO;
import com.calliduscloud.clma.domain.FieldValueCDO;

global com.calliduscloud.clma.domain.FieldValueCDO fieldValue;

dialect "mvel"

rule "Change contract field value 2"
     when
          field: FieldCDO(id == 1)
          contract: ContractCDO(id == 1);
     then
         fieldValue.setFieldValue("22222");
end

但是,当我调用 executeRule() 方法时,它会在我将全局变量添加到 KieSession 的那一行中断:

kieSession.setGlobal("fieldValue", fieldValue);

错误是:

java.lang.RuntimeException:意外的全局 [fieldValue]

当我通过调用相同的代码只执行一个规则时,一切都会顺利通过,没有任何问题。但是当我将这两个规则串联起来时,就会出现这个问题。

如果有人有什么想法,请有时间写出来。

谢谢, 德让

【问题讨论】:

    标签: java spring drools rule-engine


    【解决方案1】:

    您将drool文件加载到KieFileSystem的过程是错误的。
    将其更改为以下内容以使其正常工作。

    @Bean
        public KieContainer kieContainer() {
            KieServices kieServices = KieServices.Factory.get();
     
            KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
            File dir = new File("src/main/resources/rules");
            File[] directoryListing = dir.listFiles();
            if (directoryListing != null) {
                for (File child : directoryListing) {
                    kieFileSystem.write(ResourceFactory.newFileResource(child));
                }
            }
            KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
            kieBuilder.buildAll();
            KieModule kieModule = kieBuilder.getKieModule();
     
            return kieServices.newKieContainer(kieModule.getReleaseId());
        }
    

    【讨论】:

    • 谢谢。这是最有效的方法吗?
    【解决方案2】:

    问题可能与在两个 DRL 文件中定义全局有关。请注意,KieBuilder 将加载两个 DRL 文件来构建 KieBase。 我会尝试将全局和导入放在单独的 DRL 文件中,以确保它首先被加载。 如果您创建一个复制器并将其放在 GitHub 中,我可以尝试一下。

    【讨论】:

    • 感谢 salaboy,我尝试使用仅导入和全局变量的 DRL 文件,但仍然遇到相同的错误。但是我无法从我拥有的两个现有规则文件中删除该全局变量,因为我在两个文件中都使用了全局变量来设置 fieldValue。所以基本上,我最终得到了 3 个带有导入和全局的 DRL 文件......
    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 2019-04-08
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多