0

When defining Drools rules, what is the best way to accommodate object graphs?

Say I have the following Entity object graph with a many-to-many relationship:

User <- Group -> Value

and I have the following contrived rule:

rule "hasPurpleValue"
    $u : User()
    $g : Group() from $u.groups
    $v : Value(color == 'Purple') from $g.values
then
    //...
end

I can insert a user into the ksession as follows:

//build user...
User user = new User();
Group group = new Group();
Value value = new Value("Purple");
group.setValue(value);
user.addGroup(group);

ksession.insert(user);

then update them:

ksession.update(ksession.getFactHandle(user), user);

But what if I change the Value object directly to "Orange", the Value does not have a FactHandle as it was inserted with the user as the root. Is there a better way to define the rules and insert the entities such that I can independently alter the Entities and Drools will evaluate the outcome?

John Ericksen
  • 10,995
  • 4
  • 45
  • 75

1 Answers1

1

You have to make your own choice. As you mentioned in your post, you can't update something that is not a Fact. Every object you insert() is a Fact, but that is not true for nested objects. One way to deal with nested objects is to do what you just did: use the from pattern. The problem of this pattern, as you have described, is that you always have to update() the Fact object related to the real object you are modifying. If you can live with that, then go for it. Another way to deal with this is to insert each object as a Fact: User, Group and Value. This could make your insertion code dirtier, but you will gain in flexibility, readability and, in a way, performance in your rules. So, there is no magic recipe here. You must use what is more convenient for your scenario.

Hope it helps,

Esteban Aliverti
  • 6,259
  • 2
  • 19
  • 31
  • Is there a way of defining the "from" rule differently, so I can insert the user, group and value independently and have drools make the associations? – John Ericksen Feb 05 '13 at 16:01
  • The relation between entities must exist in some way: by reference (object) or by value (id) in your code. Then, you can insert each User, Group and Value as individual facts and write your rules without using the 'from' but writing the constraints regarding the relations of your facts: when $u: User() $g: Group(this memberof $u.groups) $v: Value(this memberof $g.values) end – Esteban Aliverti Feb 06 '13 at 08:27
  • The indentation in my previous message is a mess. Here you have the same rule in a more friendly format: http://pastebin.com/7FPNi0XG – Esteban Aliverti Feb 06 '13 at 08:29
  • Im beginning to think I should set up the rules to follow the "ownership" side of the relation, like if Group owned the reference to User and Value: http://pastebin.com/gqwJk88V . Is this on the right track? – John Ericksen Feb 06 '13 at 16:50
  • '==' is typically more efficient than 'memberof' so, if the relationships in your model are bidirectional, I would go ahead with your approach. – Esteban Aliverti Feb 07 '13 at 08:39