2
votes

I'm trying to test for the length of a list of objects. I'm following the pattern that I used in older versions of Drools (7.44 and earlier), but it doesn't appear to be working anymore.

This is my rule:

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

The Person instance I'm passing into the rules has 3 items:

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

... and the BookEvent type is 'BORROW'. I've confirmed both with a debug session in the IDE.

The rule doesn't trigger, however.

I'm using Drools 7.59.0.Final, specifically the drools-engine-classic dependency (because I prefer mvel.) Also Java 17 (openjdk). Observed the same behavior in 7.50.0.Final and 7.47.0.Final; can't test 45 or 46 because of what looks like JDK incompatibility. 47 seems to be a bit iffy JDK-wise as well.

I also retested on 7.59 with JDK 11 (Eclipse Temurin AdoptOpenJDKHotspot) with the same results.

I've used this same pattern extensively over the years; this is the first time it has failed me. Have the newest versions of drools introduced some form of non-backwards compatibility here? How am I supposed to check for list length now?


Just for giggles, I added these two test rules to see what is going on:

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

The first test rule printed Book size: 3 and java.util.ArrayList. The second test rule didn't fire at all.

Playing one final hunch, I added this test rule:

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

The rule doesn't fire at all. I tried with both java.util.List and java.util.ArrayList.

2

2 Answers

0
votes

I looked around and found some working use cases with 'size' and '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

But I think your expectation is wrong because statement from <collection> is designed to iterate through collection, and there is no ArrayList element inside. Also I've tried downgrade drools down to 7.5.0.Final and behavior seems to be consistent.

0
votes

I've create a reproducer here your rule seems to be working correclty in both 7.59.0.Final and 7.44.0.Final.

I'm probably missing something in my reproducer, please create a PR against it or fork it in your repo accordingly.