Drools lock-on-active vs no-loop - Java @ Desk

Saturday, December 14, 2013

Drools lock-on-active vs no-loop

Drools difference between lock-on-active and no-loop

no-loop & lock-on-active are the two most important features in drools. If oyu are writing complex rules within the application, these two features would be of high use.

Both these features comes into picture when any rule uses either the update or modify in the consequence of the rule.

When update or modify are used in the consequence part, the rule engine re-activates all the rules within the agenda-group that uses the fact that is being updated or modified. This results in an rule execution in an infinite loop. To avoid this, lock-on-active & no-loop are getting used.

Refer to below rule:
rule "Rule One"
agenda-group "Name Field"
salience 90
    when
  $pojo : Pojo(name == "Kumar" || address=="Mumbai")
    then
        System.out.println("Rules Name is - " + drools.getRule().getName());
        $pojo.setAddress("Mumbai CST");
        update($pojo);
end

rule "Rule Two"
lock-on-active 
agenda-group "Name Field"
salience 85
    when
  $pojo : Pojo(name == "Bhatia")
    then
        System.out.println("Rules Name is - " + drools.getRule().getName());
        $pojo.setName("Kumar");
        update($pojo);
end

If the above rule gets fired successfully, then as soon as update on the $pojo gets called in consequence of "Rule One", it will re-activate the "Rule One" and thus it enters in an infinite loop.

To avoid this, use either lock-on-active or no-loop. But both have the very important difference:
1) no-loop will avoid the re-activation of a rule caused by the RHS of that SAME rule within the agenda group. where as lock-on-active avoid the re-activation of a any rule NO MATTER what the cause is within that agenda-group.
2) If no-loop is used, the updated values gets reflected in the LHS of other rules within the same agenda whereas if lock-on-active is used, the updated values does not gets reflected in the LHS of other rules of same agenda-group but updated values gets reflected once the current agenda-group execution gets over.

In the above example, if no-loop is used then once "Rule One" got fired, it will not re-activate itself but will go for "Rule Two" execution where the updated value for "name" field would be visible in the LHS part. But as soon as it enters the consequence of "Rule Two" it will re-activate "Rule One" and so on, thus entering an infinite loop execution. So, in cae of no-loop, updated values of the fields gets reflected in other rules within the agenda.

In the above example, if lock-on-active is used then once "Rule One" got fired, it will not re-activate itself but will move to "Rule Two" execution. But the updated value from "Rule One" will not be visible to LHS part of "Rule Two" since both the rules are within the same agenda-group. As shown in below rules, updated value from "Rule One" will only be visible to "Rule Three"
rule "Rule One"
lock-on-active 
agenda-group "Name Field"
salience 90
    when
  $pojo : Pojo(name == "Kumar" || address=="Mumbai")
    then
        System.out.println("Rules Name is - " + drools.getRule().getName());
        $pojo.setAddress("Mumbai CST");
        $pojo.setName("Bhatia");
        update($pojo);
end



rule "Rule Two"
lock-on-active 
agenda-group "Name Field"
salience 85
    when
  $pojo : Pojo(name == "Bhatia")
    then
        System.out.println("Rules Name is - " + drools.getRule().getName());
        $pojo.setName("Kumar");
        update($pojo);
end

rule "Rule Three"
lock-on-active 
agenda-group "Name Field Update Check"
salience 70
    when
  $pojo : Pojo(name == "Bhatia")
    then
        System.out.println("Rules Name is - " + drools.getRule().getName());
        $pojo.setName("Kumar");
        update($pojo);
end








2 comments:

  1. After rules 1 and 2 get executed. Then rule 3 will execute. Inside the Rule 3, you are again updating the Object. Would it will again execute the Rule 1 and 2? Because Update will re-evaluate all the rules.

    ReplyDelete
    Replies
    1. I am using agenda groups while firing the rules

      ksession.getAgenda().getAgendaGroup("Name Field Update Check").setFocus();
      ksession.getAgenda().getAgendaGroup("Name Field").setFocus();

      First "Rule Three" will be executed. Once its done, agenda group focus will be shifted from "Name Field Update Check" to "Name Field". The Agenda group "Name Field Update Check" is removed from the stack now.

      Now the rest of 2 rules will be executed.

      Update will re-evaluate all the rules - Its true, but since no agenda group is available now in the stack, no rules will be triggered.

      Delete