事实数据更改时,Drools会规定解雇顺序 [英] Drools Rules Fireing Order when Fact data changes

查看:102
本文介绍了事实数据更改时,Drools会规定解雇顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Drools的新手,或者我误解了Drools可以做什么,或者我错过了一些事情。

I am new to Drools and either I misunderstand what Drools can do or I am missing something.

我有一个简单的Fact类

I have a simple Fact class

public class MeterReadTO {

private String status = "";

public String getStatus() {
  return status;
}

public void setStatus(String status) {
   this.status = status;
}

public boolean isInvalid() {
  return status.equals("invalid");
};

}

符合规则

 rule "Rule Invalid"

 dialect "mvel"
 when
     MeterReadTO( isInvalid());
 then
  System.out.println("Rule Invalid Fired");

end

rule "Rule Not Invalid"

 dialect "mvel"
when
   not MeterReadTO(  isInvalid());
then
   System.out.println("Rule Not Invalid Fired");

end

rule "Set Status"

 dialect "mvel"
 when
    $mr: MeterReadTO()
  then
      System.out.println("Rule Set Status Fires");

     modify($mr) {
      setStatus("invalid")
     }
   end

,然后运行规则

@RunWith(SpringRunner.class)
@SpringBootTest
public class Dependancy {


static KieSession ksession;

Logger logger = LoggerFactory.getLogger(Dependancy.class);


MeterReadTO mr;


@BeforeClass
public static void start() {


      KieContainer kieClasspathContainer = KieServices.Factory.get().getKieClasspathContainer();
        ksession = kieClasspathContainer.newKieSession("DependancyTest");
}

@Test
public void contextLoadsAndRetrievesData() {

    MeterReadTO mr = new MeterReadTO();
    mr.setId(50);

    ksession.insert(mr);

    // when
    ksession.fireAllRules();
    ksession.dispose();

    // Then
    System.out.println("After Drools, status is " + mr.getStatus());

}

}

我得到了结果

Rule Not Invalid Fired
Rule Set Status Fires
After Drools, status is invalid

通过使用有状态会话,我期望看到规则无效火灾在规则设置状态触发后。如果将设置状态规则从规则列表的底部移到顶部,则会得到

By using a stateful session I was expecting to see the "rule Invalid" fire after "rule Set Status" fires. If I move the Set Status rule from the bottom of the list of rules to the top, then I get

Rule Set Status Fires
Rule Not Invalid Fired
After Drools, status is invalid

很显然流口水不了解规则设置状态中的状态更改。我想念什么?

So clearly Drools is not aware of the status change in rule Set Status. What am I missing?

问候

跟进。

现在我真的很困惑。如果我在规则文件中删除对方法isInvalid()的调用并改为引用getStatus()方法,则规则现在看起来像

Now I'm really confused. If I remove the call to the method isInvalid() in my rules file and reference the getStatus() method instead so the rules now look like

rule "Rule Invalid"

dialect "mvel"
when
  MeterReadTO( getStatus() == "ïnvalid");
then
  System.out.println("Rule Invalid Fired");

end

rule "Rule Not Invalid"

 dialect "mvel"
 when
   MeterReadTO( getStatus() == "");
 then
    System.out.println("Rule Not Invalid Fired");

end

rule "Set Status"

dialect "mvel"

when
    $mr: MeterReadTO()
  then
      System.out.println("Rule Set Status Fires");

  modify($mr) {
    setStatus("ïnvalid")
  }

   end

然后我得到了预期的输出结果

Then I get the output that I expected

Rule Not Invalid Fired
Rule Set Status Fires
Rule Invalid Fired
After Drools, status is ïnvalid  

任何人都可以解释发生了什么吗?

Can anyone explain what is happening?

推荐答案

基本上,正在发生的事情是没有办法Drools明白,当您更改事实的状态时,方法 isInvalid()的结果会受到影响。

Basically, what's happening is that there is no way for Drools to understand that when you change the status of your fact, the result of the method isInvalid() is affected.

修改事实时,Drools会尽量减少对规则的重新评估。在您的情况下,Drools无法在 setStatus() isInvalid()方法之间建立连接。

When you modify a fact, Drools will try to minimize the reevaluation of the rules as much as possible. In your case, Drools has no way to make a connection between the setStatus() and isInvalid() methods.

在第二种情况下,您在规则中使用 getStatus()方法,然后Drools能够(通过简单的POJO命名约定)进行连接。

In the second case, you are using the getStatus() method in your rules and Drools is then able to do the connections (by simple POJO naming conventions).

一种确保Drools理解 setStatus() isInvalid()可以在规则中使用 @watch 批注:

One way to make sure Drools understands the connection between setStatus() and isInvalid() could be to use the @watch annotation in your rule:

rule "Rule Invalid"
 dialect "mvel"
 when
   MeterReadTO( isInvalid()) @watch(status)
 then
  System.out.println("Rule Invalid Fired");
end

rule "Rule Not Invalid"
dialect "mvel"
when
  not MeterReadTO(  isInvalid()) @watch(status)
then
  System.out.println("Rule Not Invalid Fired");
end

这种方法的问题在于您的规则与模型紧密相关。如果要检查事实是否无效的方式要修改以涉及更多字段,则必须按规则修改 @watch 批注。

The problem with this approach is that your rules get really tied to your model. If the way you check whether a fact is invalid ahs to be modified to involve more fields, you has to go rule by rule modifying the @watch annotation.

另一种解决方案是使用 @Modify 批注在模型本身中标记关系:

Another solution would be to mark the relationship in the model itself using the @Modifies annotation:

public class MeterReadTO {
  private String status = "";

  public String getStatus() {
    return status;
  }

  @Modifies( { "invalid" } )
  public void setStatus(String status) {
    this.status = status;
  }

  public boolean isInvalid() {
    return status.equals("invalid");
  };

}

您可以在 Drools的官方文档

希望有帮助,

这篇关于事实数据更改时,Drools会规定解雇顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆