在链中执行多个Drools规则-Spring Java Application

时间:2019-03-01 16:15:54

标签: java spring drools rule-engine

我通过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]

当我通过调用相同的代码仅执行一条规则时,所有规则都通过了而没有问题。但是当我将这两个规则连在一起时,就会出现此问题。

如果有人有什么主意,请有空请写信。

谢谢, 德扬

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

您将流口水文件加载到 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());
    }