从v7.20到v7.21版本更改后drools中的无限递归

从v7.20到v7.21版本更改后drools中的无限递归,drools,Drools,当drools编译器的版本从7.20.0.Final更改为7.21.0.Final时,一些规则会递归循环。 github中的代码: 更多详细信息 当我触发其部分的规则时,当部分: rule "rule 1.1" when $sampleDomain: SampleDomain(instanceVariable2 == "Value of instance variable") then System.out.println("Rule 1.1 fired");

当drools编译器的版本从
7.20.0.Final
更改为
7.21.0.Final
时,一些规则会递归循环。

github中的代码:

更多详细信息

当我触发其
部分的规则时,当
部分:

rule "rule 1.1"
  when
    $sampleDomain: SampleDomain(instanceVariable2 == "Value of instance variable")
  then
    System.out.println("Rule 1.1 fired");
    modify($sampleDomain){
            setInstanceVariable1(3)
    }
end
它不会递归地循环

但是当我调用另一个规则,从另一个类调用静态函数时:

rule "rule 1.2"
  when
    $sampleDomain: SampleDomain(CoreUtils.anotherFunction())
  then
    System.out.println("Rule 1.2 fired");
    modify($sampleDomain){
            setInstanceVariable1(3)
    }
end
它递归地循环

具有静态函数的类是

import com.drool_issue.domain.SampleDomain;

public class CoreUtils {

    public static boolean anotherFunction() {
        System.out.println("anotherFunction() inside CoreUtils");
        return true;
    }

    public static boolean anotherFunction(SampleDomain sampleDomain) {
        System.out.println("anotherFunction(SampleDomain sampleDomain) inside CoreUtils");
        return true;
    }

}
我的域文件是:

public class SampleDomain {
    private int instanceVariable1;
    private String instanceVariable2;
    private int instanceVariable3;


    public int getInstanceVariable1() {
        return instanceVariable1;
    }
    public void setInstanceVariable1(int instanceVariable1) {
        this.instanceVariable1 = instanceVariable1;
    }
    public String getInstanceVariable2() {
        return instanceVariable2;
    }
    public void setInstanceVariable2(String instanceVariable2) {
        this.instanceVariable2 = instanceVariable2;
    }
    public int getInstanceVariable3() {
        return instanceVariable3;
    }
    public void setInstanceVariable3(int instanceVariable3) {
        this.instanceVariable3 = instanceVariable3;
    }



}
这仅在版本从
7.20.0.Final
更改为
7.21.0.Final
后才会发生。猜猜问题出在哪里

当我进一步研究这个问题时,我也看到了这一点

当我们将两个函数添加到
SampleDomain
类ie中时

    public boolean anotherFunction() {
        return true;
    }

    public boolean anotherFunction(SampleDomain sampleDomain) {
        return true;
    }
并在规则中使用此选项,如:

rule "rule 1.4"
  when
    $sampleDomain: SampleDomain(anotherFunction())
  then
    System.out.println("Rule 1.4 fired");
    modify($sampleDomain){
            setInstanceVariable1(3)
    }
end

这些循环也是递归的

github中的代码:

此外,当任何静态方法变为非静态时,则调用域类中的方法,即使规则中指定了静态方法

此处需要注意的代码部分是:

github中的代码:


所有这些都是由
7.20.0.Final
之后的版本引起的,即
7.21.0.Final
7.22.0.Final
7.23.0.Final
基于属性反应性的过滤不能应用于外部功能,因为我们不知道外部功能(静态方法)在内部做什么

要详细说明这一点: 让我们从属性反应性开始;每当我们在规则的结果中使用modify或update关键字时,我们都会通知引擎,过滤类似对象类型的规则应该再次重新计算该对象。默认情况下,此重新计算发生在整个对象上。只要对象的一个属性改变,规则就会认为它是一个匹配的新对象。当我们不希望为某些更改重新评估规则时,这可能会导致一些问题。在这些情况下,循环控制机制(如无循环和锁定启用)可能会有所帮助。但是,如果我们希望规则仅控制某些属性的更改,则需要编写非常复杂的条件。此外,如果模型在将来因大型规则库而发生更改,则可能必须修改大量规则以避免意外的规则重新执行。幸运的是,Drools提供了一个允许引擎解决此问题的功能。它允许规则编写者定义bean的属性,如果这些属性在工作内存中被更新,则应该对其进行监视。该特性可以在规则中使用的数据模型(Java类或声明的类型)中定义,称为属性反应bean

要使用此功能,我们首先需要使用属性被动注释标记规则中要使用的类型。此注释允许引擎知道,每当将此类型的对象添加到工作内存时,都需要对其更改进行特殊筛选。此注释可以添加到Java类(在类级别)或声明的类型(在第一行之后,定义类型名称),如下所示, 在Java类中:

@PropertyReactive public class Customer {     ... }
在声明的类型中:

    declare PropertyReactiveOrder        
        @propertyReactive
        discount: Discount
        totalItems: Integer
        total: Double    
    end 
我们还可以通过添加
propertysspecificationcoption.ALWAYS
to builder选项,使所有类型的属性都是被动的

注意:属性更改将仅使用modify关键字通知规则引擎。update关键字将无法区分正在更改的bean属性之间的差异

Drools 5.4中引入了属性反应性,但由于从正确性和性能角度来看,使用此功能被认为是一种良好的实践,因此Drools 7.0中默认启用了此功能

现在再次谈到我们的问题,虽然属性反应性的情况已经发生了巨大的变化,它就像一个细粒度的属性更改侦听器,允许Drools进一步了解规则RHS内部的情况,或者至少在modify()操作内部的情况。函数仍然是它的黑匣子,因此产生了这个问题

    declare PropertyReactiveOrder        
        @propertyReactive
        discount: Discount
        totalItems: Integer
        total: Double    
    end