我们可以在Drools中动态设置事实类型和事实字段

时间:2016-02-03 09:04:21

标签: java json drools pojo

如何在drl文件中动态设置事实类型和事实字段?我正在读取一个包含记录的json文件。我正在映射到pojo类的记录,它是从json模式动态生成的,我用json2pojo maven plugin ! 。现在我想要对那个班级发布一些规则。但是我不能把drl文件中的那个类作为字段的fact.same。 以下是drl rule。

rule "not null"

when 

  obj:Class(fieldName==null)
then
  //take action
end

此Class和fieldName是动态生成的。 请建议我解决这个问题。 感谢。

4 个答案:

答案 0 :(得分:2)

我已成功实施了类似的问题陈述。快点看看吧。 我本来应该在用户在Web应用程序的运行时选择的sql表上动态生成规则。这里需要注意的是,pojo类也应该在运行时生成。 Drools 6有一个内置的API(类似于JAVA反射API),您可以在其中动态生成类,因此也可以生成factTypes。 首先是.drl文件: -

declare {insert tablename as chosen by the user}
{columnname} : {columntype}  
{columnname} : {columntype}  
end

这会生成一个pojo类以及可以在规则中直接访问的属性的getter和setter。 现在,java文件: -

生成的类可以在java应用程序中访问,如下所示:

//获取声明的FactType

FactType  tableType = kbase.getFactType({packagename},{tablename});

//创建实例:

Object obj = tableType.newInstance();

现在,通过hibernate实现了从所选表中对应的sql插入的事实。如果规则做出任何修改,这也会使表格保持更新。

随意提出任何问题。 很高兴帮助.. :)

答案 1 :(得分:0)

JSON适合通过线路等发送数据。但是,您应该将其转换为POJO并根据Java对象编写验证规则。我认为没有理由说你为什么不能这样做。

然而......如果你想花费大量的时间和精力......

您可能已经使用XML完成了什么,XML是数据集的另一个(文本)表示("记录")。查看JSON结构定义,您可以看到有#34;对象"和"阵列"。这些将是你的事实类型。 (JS-)对象可以由包含Map的POJO表示,(JS-)数组可以由带有java.util.List字段的POJO实现。

您可以编写选择JS-Object的规则并执行字段检查。

答案 2 :(得分:0)

我根据我的要求找到了一个解决方案。这是一种不同的方法,我动态删除了生成的POJO。我创建了一个POJO作为"参数"它将用作事件类型。我有字段作为fieldName(Json字段路径),rulesToFire(规则)和json记录列表。在drl文件中我可以获取这些值。使用com.jayway.jsonpath.JsonPath我可以阅读所谓的值。

答案 3 :(得分:0)

FactType 界面中有一个选项为 setFromMap。如果您能够在 Map 集合(可能是 JSON,或 JSON 到 Map)中提供您的输入,那么您可以从此 Map 设置声明类型的所有属性。下面是这种方法的测试用例。我希望它会有所帮助。

   @Test
    void test_StatelessKieSession_DynamicRuleNestedObjects_DeclaredVariables_Standalone() throws Exception{
        Map<String,Object> fields =
                Stream.of(new Object[][] {
                        {"name","server001"},
                        {"processors",4},
                        {"memory",8192},
                        {"diskSpace",128},
                        {"cpuUsage",3},
                        {"virtualizations"
                                ,Stream.of(
                                new HashMap<String,Object>(){{
                                    put("name","virtualization - 1");
                                    put("diskSpace",4);
                                    put("memory",1024);}},
                                new HashMap<String,Object>(){{
                                    put("name","virtualization - 2");
                                    put("diskSpace",8);
                                    put("memory",2048);}}
                        ).collect(Collectors.toList())}
                }).collect(Collectors.toMap(key -> (String)key[0], val -> val[1]));

        String packageName = "com.genericrule";
        String mainObjectName = "Server";

        String ruleStr = "package com.genericrule import java.util.List; declare Server name : String processors : int memory : int diskSpace : int virtualizations : List cpuUsage : int ruleMessage : String end; declare Virtualization name : String diskSpace : int memory : int end; rule \"check minimum server configuration\" dialect \"mvel\" when $server : Server(processors < 2 || memory <= 1024 || diskSpace <= 250 ) then $server.ruleMessage = $server.name + \" was rejected by don't apply the minimum configuration.\"; end;";

        KieServices kieServices = KieServices.Factory.get();

        KieRepository kr = kieServices.getRepository();
        KieFileSystem kfs = kieServices.newKieFileSystem();

        kfs.write("src/main/resources/genericRule.drl", ruleStr);

        KieBuilder kb = kieServices.newKieBuilder(kfs);
        kb.buildAll();

        KieContainer kContainer = kieServices.newKieContainer(kr.getDefaultReleaseId());

        StatelessKieSession sks = kContainer.newStatelessKieSession();

        FactType mainObjectFact = sks.getKieBase().getFactType(packageName,mainObjectName);

        Object mainObject = mainObjectFact.newInstance();

        mainObjectFact.setFromMap(mainObject,fields);
        sks.execute(mainObject);

        assertThat((String) mainObjectFact.get(mainObject,"ruleMessage")).contains("rejected");
    }