如何在 Drools 7.59 中测试列表长度?

How to test list length in Drools 7.59?

我正在尝试测试对象列表的长度。我正在遵循我在旧版 Drools(7.44 及更早版本)中使用的模式,但它似乎不再有效。

这是我的规则:

global BookEventResult result;

rule "Person has 3 or more existing checked out books"
when
  BookEvent( type == BookEventType.BORROW )
  Person( $books: checkedOutBooks )
  ArrayList( size >= 3 ) from $books
then
  result.setSuccess(false);
  result.setReason("User has already checked out 3 books");
end

我传递给规则的 Person 实例有 3 个项目:

class Person {
  List<Book> checkedOutBooks = new ArrayList<>(); // 3 Book instances in here
}

... 并且 BookEvent 类型是 'BORROW'。我已经在 IDE.

中通过调试会话确认了两者

但是,该规则不会触发。

我正在使用 Drools 7.59.0.Final,特别是 drools-engine-classic 依赖项(因为我更喜欢 mvel。)还有 Java 17 (openjdk)。在 7.50.0.Final 和 7.47.0.Final 中观察到相同的行为;由于 JDK 不兼容,无法测试 45 或 46。 47 似乎也有点不确定 JDK-wise。

我也在 7.59 上用 JDK 11 (Eclipse Temurin AdoptOpenJDKHotspot) 重新测试了同样的结果。

这些年来我广泛使用了相同的模式;这是我第一次失败。最新版本的 drools 是否引入了某种形式的非向后兼容性?我现在应该如何检查列表长度?


只是为了笑,我添加了这两个测试规则以查看发生了什么:

rule "Test - No check"
when
  Person( $books: checkedOutBooks )
then
  System.out.println("Book size: " + $books.size());
  System.out.println( $books.getClass().getName() );
end

rule "Test - Exactly 3 books"
when
  Person( $books: checkedOutBooks )
  ArrayList( size == 3 ) from $books
then
  System.out.println("Three books exactly");
end

第一个测试规则打印了 Book size: 3java.util.ArrayList。第二个测试规则根本没有触发。

基于最后的预感,我添加了这条测试规则:

rule "Test - assign to list"
when
  Person( $books: checkedOutBooks )
  $booklist: ArrayList() from $books
then
  System.out.println("booklist size: " + $booklist.size());
end

规则根本没有触发。我尝试了 java.util.Listjava.util.ArrayList.

我环顾四周,发现了一些使用 'size' 和 'List'

的用例
rule "Person has 3 or more existing checked out books"
when
  BookEvent( type == BookEventType.BORROW )
  $person: Person( $books: checkedOutBooks, $books.size >= 3 )
  $book1: Book() from $person.checkedOutBooks.get(0)
  $book3: Book(name == 'book3') from $person.checkedOutBooks
  $bookNames: List(size >= 3) from accumulate (Book($name: name) from $books, collectList($name)) 
then
  System.out.println("First book " + $book1);
  System.out.println("Third book " + $book3);
  System.out.println("Book names " + $bookNames);
  System.out.println("Books " + $books);
end

但我认为你的期望是错误的,因为语句 from <collection> 旨在遍历集合,并且内部没有 ArrayList 元素。我也试过将 drools 降级到 7.5。0.Final 并且行为似乎是一致的。

我创建了一个复制器 here 你的规则似乎在 7.59.0.Final7.44.0.Final 中都有效。

我的复制器中可能遗漏了一些东西,请针对它创建一个 PR 或相应地在你的 repo 中分叉它。