简体   繁体   English

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

[英]Can we set fact type and fact field dynamically in Drools

How do I set fact type and fact field dynamically in drl file?I am reading a json file which having the records.that records I am mapping to pojo class which is generating dynamically from json schema I used json2pojo maven plugin !如何在 drl 文件中动态设置事实类型和事实字段?我正在读取一个包含记录的 json 文件。我正在映射到 pojo 类,该类从 json 模式动态生成我使用了json2pojo maven 插件 .now I want to fire some rules on that class. .现在我想在该课程上制定一些规则。 but I am not able to fech that class in drl file as a fact.same for fields.但我无法将 drl 文件中的该类作为字段的事实.相同。 below is drl rule.下面是drl规则。

rule "not null"

when 

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

this Class and fieldName is generating dynamically.这个 Class 和 fieldName 是动态生成的。 please suggest me solution regarding this.请建议我解决这个问题。 Thanks.谢谢。

I have successfully implemented a similar kind of problem statement.我已经成功实施了类似的问题陈述。 Have a quick look at it.快速浏览一下。 I was supposed to dynamically generate rules on a sql table selected by the user on runtime in a web application.我应该在用户在 Web 应用程序中运行时选择的 sql 表上动态生成规则。 Point to be noted here is that the pojo class too should be generated at runtime.这里要注意的一点是 pojo 类也应该在运行时生成。 Drools 6 has an inbuilt API (similar to JAVA reflection API) where you can dynamically generate a class and hence the factTypes too. Drools 6 有一个内置的 API(类似于 JAVA 反射 API),您可以在其中动态生成一个类,因此也可以动态生成 factTypes。 So first the .drl file :-所以首先是 .drl 文件:-

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

This generates a pojo class alongwith the getters and setters of the attributes which can be directly accessed in the rules.这将生成一个 pojo 类以及可以在规则中直接访问的属性的 getter 和 setter。 Now, the java file :-现在,java文件:-

The generated class can be accessed in java application like this:生成的类可以在 java 应用程序中访问,如下所示:

//get the declared FactType //获取声明的FactType

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

//create instances: //创建实例:

Object obj = tableType.newInstance();

Now, facts were inserted from sql corresponding to the selected table was implemented via hibernate.现在,从与所选表对应的 sql 插入的事实是通过 hibernate 实现的。 This also kept the table updated if any modifications were made by the rules.如果规则进行了任何修改,这也会使表格保持更新。

Feel free to ask any questions.随意问任何问题。 Happy to help..:)乐于帮助..:)

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

JSON is good for sending data over the line, etc. But then you should convert it to a POJO and write your validation rules in terms of Java object. JSON 适用于通过线路发送数据等。但是您应该将其转换为 POJO 并根据 Java 对象编写验证规则。 I see no good reason why you shouldn't be able to do so.我看不出你为什么不能这样做的充分理由。

However... If you want to spend a lot of time and effort...但是...如果你想花费大量的时间和精力...

What you might do has been done using XML, which is another (textual) representation for data sets ("records").您可能使用 XML 完成的操作是数据集(“记录”)的另一种(文本)表示。 Looking at the JSON structure definition, you can see that you have "objects" and "arrays".查看 JSON 结构定义,您可以看到您有“对象”和“数组”。 These will be your fact types.这些将是您的事实类型。 A (JS-)Object can be represented by a POJO containing a Map, a (JS-)Array might be implemented by a POJO with a java.util.List field. (JS-)Object 可以由包含 Map 的 POJO 表示,(JS-)Array 可以由具有 java.util.List 字段的 POJO 实现。

You can write rules that select a JS-Object and perform field checks.您可以编写选择 JS 对象并执行字段检查的规则。

There is an option in FactType interface as setFromMap . FactType接口中有一个选项为setFromMap If you are able to provide your input in a Map collection (may be JSON, or JSON to Map ) then you can set all of the properties of your declared type from this Map .如果你能够提供你在输入Map集合(可能是JSON或JSON到Map ),那么你可以设置所有从这个声明的类型的属性的Map Below is a test case for this approach.下面是这种方法的测试用例。 I hope it is gonna be helpful.我希望它会有所帮助。

   @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");
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM