在Drools 6中执行成功规则后退出

时间:2015-04-06 22:01:02

标签: drools

我有一个如下对象:

class License{
    private field1;
    private field2;
    private boolean active;
    private String activeMessage;
    private boolean processed = false;

    //Getter and setter methods
}

我要做的是,基于field1和field2的值,我需要设置isActive标志和相应的消息。但是,如果触发了field1或field2的规则,我需要停止规则处理。也就是说,我只需要执行一条成功的规则。

我在帖子上看到做ksession.fireAllRules(1)会解决这个问题。但是Drools 6中没有fireAllRules()方法。我也尝试过返回;每条规则末尾的陈述。这也没有帮助我。

最后,我最终在我的对象中添加了一个名为processed的字段。所以每当我执行任何规则时,我都会将处理后的标志设置为true。如果标志已经设置,那么我不执行任何规则。这是我的规则文件:

rule "Check field1"
    when
        $obj : License(getField1() == "abc" && isProcessed() == false)
    then
        System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
        $obj.setActive(true);
        $order.setActiveMessage("...");
        $order.setProcessed(true);
end


rule "Check field2"
    when
        $obj : License(getField2() == "def" && isProcessed() == false)
    then
        System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
        $obj.setActive(true);
        $order.setActiveMessage("...");
        $order.setProcessed(true);
end

然而,我发现即使现在我的规则都被解雇了。当我尝试打印isProcessed()的值时,它表示为true,即使我只在isProcessed()为false时输入规则。

这就是我调用drools引擎的方式:

kieService = KieServices.Factory.get();
kContainer = kieService.getKieClasspathContainer();
kSession = kContainer.newStatelessKieSession();
kSession.execute(licenseObj);

这不仅仅是两个规则,我有很多规则,因此通过更改drl文件中规则的顺序来控制规则执行不是一种选择。这里发生了什么?我怎么解决这个问题?我对Drools来说有点新鲜,所以我可能会在这里遗漏一些东西。

感谢。

1 个答案:

答案 0 :(得分:4)

您的问题包含许多错误。

在Drools 6中fireAllRules已经消失,这绝对不是真的。您可能已经查看了javadoc索引,在包org.kie.api.runtime.rule中查找此方法的四个(4!)重载版本界面StatefulRuleSession

通过组合触发约束,您可以轻松避免触发两个规则中的一个的问题:

rule "Check field1 and field2"
when
    $lic: License(getField1() == "abc" || getField2() == "def" )
    //...
then
    $lic.setXxx(...);
end

您抱怨说,尽管在事实中设置了processed标志,但您的两条规则都会触发。在这里,您缺少基本点(Drools参考手册中介绍),即每当您更改事实数据时通知引擎的必要性。您应该在规则的右侧使用modify

但即使这样也不够好。每当由于某些属性而进行更新时,都应添加约束以避免一次又一次地运行更新。你可能写过:

rule "Check field1 and field2"
when
    $lic: License(getField1() == "abc" || getField2() == "def",
                  ! active )
    //...
then
    modify( $lic ){ setActive( true ) }
end

你甚至可以用两个不同的规则来写这个,每个字段一个,只有其中一个规则会触发...