事实数据更改时,Drools会规定解雇顺序 [英] Drools Rules Fireing Order when Fact data changes
问题描述
我是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()$ c $之间的连接的方法c>和
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屋!