0

We have the following situation when setting up a Drools rule execution:

List<Person> persons = List.of(person1, person2, ...); // in essence, it's just a List of something
KieSession kieSession = kieContainer.newKieSession();
kieSession.insert(persons);
kieSession.fireAllRules();

Is it the right/correct/best approach to add all persons using a List? Or should it be done the following way?

Person person1 = Person.builder().name("Fred").build();
Person person2 = Person.builder().name("Mr. Naughty").build();

List<Person> persons = List.of(person1, person2, ...); // in essence, it's just a List of something
KieSession kieSession = kieContainer.newKieSession();

for (Person p : persons) {
  kieSession.insert(p);
}
kieSession.fireAllRules();

i.e. adding the fact one by one? The documentation/samples always just give a couple facts, which are added one by one, I've never seen a sample using the List. But the system I'm talking about is using the List approach and it works. It's just said to be slow. So I'm wondering if the Rete algorithm just doesn't analyze the List's contents, but adds the List itself as a fact.

On the other hand: if the facts (here: Persons) get added in a singular way, is it still possible to perform a count on amount of Persons?

1 Answer 1

0

Neither is "better". Both approaches are equally valid, but your rules will be different depending on your approach.

If you insert a List<Person> into working memory, your rules will need to work against that object:

rule "Example 1: Bob is in the list of people"
when
  $people: List()
  exists( Person( name == "Bob" ) from $people )
then
  System.out.println("Bob exists in the list of people.");
end

Alternatively, if you just have the individual Person records in working memory, you can just search working memory for that Person:

rule "Example 2: Bob is in Working Memory"
when
  exists(Person( name == "Bob" ))
then
  System.out.println("Bob is in working memory.");

So why would you do one or the other?

If you only have one list, it might be simpler to just stick the items into working memory. But if you have multiple collections of different types, things get more complicated. Additionally, if you want to do operations on the list as a whole, it might be easier to have the List in working memory and modify that.

For example, if we have a List<Person> representing all the employees in a company, and we're going to write rules to filter that list down to some subset of employees who will be invited to a certain kind of training, it may be easier to have the List in working memory as an object and then call methods to remove Person instances from it as we identify people who don't meet the criteria.

Alternatively, for the same example, we might instead just put all the Person instances into working memory, along with an empty List. Then our rules can figure out who should go to the training, and populate that List.

So at the end of the day, the answer really is -- both are valid approaches. Pick one based on what your rules are going to be actually doing, and write your rules to match the data that's is in those rules.


There is probably a performance or resource consumption impact if you insert a very large number of items into working memory, but I personally haven't ever noticed anything. I make this assertion because even working memory is, under the covers, some form of collection, and how that collection performs will depend on the quantity of items being stored in it. (Plus the specific type. Once upon a time it was a LinkedList but I don't know if it still is.)


Brief aside because you mentioned you hadn't seen the syntax with List: This syntax is a lot more commonly seen in more complex objects that contain a collection. For example, something like:

class HalloweenParty {
  List<Person> attendees;
  List<Food> treats;
  List<Entertainment> entertainment;
}
rule "Greet attendees"
when
  HalloweenParty( $attendees: attendees )
  Person( $name: name ) from $attendees
then
  System.out.println("Welcome to the party, " + $name + "!");
end
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Roddy-of-the-Peas (sorry, linking doesn't work somehow...). So I assume, that all facts being imported to the working memory, are fully indexed, allowing for quick access. Thanks - answered :)
Image
I mean, they're not indexed in that they're in any kind of order and can be accessed by index. You can't say "get me the third person out of working memory" or change the 'order' or anything like that. But you can add and remove things from working memory, and modify them to a degree, so in that sense it's really no different than working with a standalone List other than some syntax.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.