事实数据更改时,Drools会规定解雇顺序

时间:2019-03-07 09:52:38

标签: drools

我是Drools的新手,或者我误解了Drools可以做什么,或者我缺少一些东西。

我有一个简单的事实课

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

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

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

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

致谢

跟进。

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

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

然后我得到了期望的输出

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

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

1 个答案:

答案 0 :(得分:0)

基本上,正在发生的事情是Drools无法理解,当您更改事实的status时,方法isInvalid()的结果会受到影响。

当您修改事实时,Drools将尝试尽量减少对规则的重新评估。就您而言,Drools无法在setStatus()isInvalid()方法之间建立联系。

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

确保Drools理解setStatus()isInvalid()之间的联系的一种方法是在规则中使用@watch批注:

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批注。

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

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' official documentation中找到有关此主题的更多信息。

希望有帮助,