如何在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是动态生成的。 请建议我解决这个问题。 感谢。
答案 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");
}