【问题标题】:Passing multiple objects in Drools not working在 Drools 中传递多个对象不起作用
【发布时间】:2015-07-01 14:31:03
【问题描述】:

我创建了一个全状态知识会话,我用它在会话中插入多个对象。

StatefulKnowledgeSession ksession = initializeDrools(runtimeDrlFile.getFilePath());

private StatefulKnowledgeSession initializeDrools(String filePath) throws Exception {
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newFileResource("E:\\drools\\" + filePath), ResourceType.DRL);
    KnowledgeBase kbase = kbuilder.newKnowledgeBase();
    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
    return kbase.newStatefulKnowledgeSession();
}

假设我有两张地图,比如

Map<String, Object> map  = new HashMap<String, Object>();  // Assume somthing is stored in it
Map<String, Object> maps = new HashMap<String, Object>();  //   ""

现在我已经将两个对象都插入了 ksession 并触发了所有规则。

ksession.insert(maps);
ksession.insert(map);
ksession.fireAllRules();

这是我的 drools 文件。

import java.util.Map;

rule "Category Level"

when
    $map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
then
    $map.put("Discount", String.valueOf("10.00"));
    System.out.println($map);
    System.out.println($maps);
end 

它显示我是

Caused by: java.lang.IllegalArgumentException: Could not parse knowledge.

如果我删除System.out.println($maps);,它就可以正常工作。如果我在 drl 文件中用$maps 替换所有出现的$map,它也可以正常工作,但现在我无法访问$map,反之亦然。

我将多个对象传递到口水的逻辑有什么问题吗?

更新:

清除非法参数例外后,

import java.util.Map;

rule "Category Level"

when
    $maps: Map()
    $map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
then
    $map.put("Discount", String.valueOf("10.00"));
    System.out.println($map);
    System.out.println($maps);
end 

现在的问题是sysout 正在打印$map 的值。为什么$maps值被$map替换?

【问题讨论】:

  • 一个声明一次只能代表一个事实,因此 $map 只是一个事实。也没有 $maps 的声明,因此当您尝试打印它时,您实际上是在打印一些不存在的东西。
  • @ConMan,是的..现在我明白了..
  • @ConMan,我已经更正了声明部分,但奇怪的是,无论我在 java 中存储在 $maps 中并传递到流口水,当我输入 System.out.println($map); System.out.println($maps); 时,两者都在打印存储在$map 中的值。知道为什么会这样吗?

标签: java drools rule-engine


【解决方案1】:

类似的模式

$mx: Map()

能够绑定作为事实插入的任何 Map。所以,如果你有几个模式

$mx: Map()
$my: Map()

单个地图将绑定为 $mx 和 $my。如果你有两张地图,a 和 b,它们将以四种方式绑定:a-a、a-b、b-a、b-b。

为模式添加约束,例如,

$mx: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )

限制可能的匹配和绑定,但添加另一个模式:

$mx: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
$my: Map()

仍然会产生多个匹配,例如,将两个映射作为事实,其中一个映射匹配第一个模式,您仍然会得到 a-a、a-b。

java.util.Map 和其他“匿名”容器类(地图和所有集合)在匹配方面是出了名的棘手。如果地图表示某个“现实世界”实体,它应该有一个条目提供唯一标识。在所有模式中使用它。

最好将 Java bean 用作事实,并带有一些提供标识的字段。

【讨论】:

    【解决方案2】:

    你没有在任何地方定义$maps。您需要声明它并为其赋值。

    你想要这样的东西:

    $map: Map( this["CategoryCode"] == "10" && this["CategoryAmount"] >= 1000 )
    $maps: Map()
    

    【讨论】:

    • 你能解释一下...something...是什么吗?因为我已经尝试过$maps: Map,但它不起作用.. 更新:$maps: Map() 正在工作.. 谢谢
    • 甜蜜!流口水会让你对这些东西发疯
    • 奇怪的是,无论我在 java 中存储在 $maps 中并传递到口水,当我输入 System.out.println($map); System.out.println($maps); 时,两者都在打印存储在 $map 中的值。知道为什么会这样吗?
    • 它们设置为相同的值,您需要在 Map() 中放置一些条件来区分它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 2016-04-19
    • 2020-09-14
    相关资源
    最近更新 更多