[id='execution-control-con_{context}']

= Execution control in the {RULE_ENGINE}

When new rule data enters the working memory of the {RULE_ENGINE}, rules may become fully matched and eligible for execution. A single working memory action can result in multiple eligible rule executions. When a rule is fully matched, the {RULE_ENGINE} creates an internalMatch instance, referencing the rule and the matched facts, and adds the internalMatch onto the {RULE_ENGINE} agenda. The agenda controls the execution order of these rule internalMatches using a conflict resolution strategy.

After the first call of `fireAllRules()` in the Java application, the {RULE_ENGINE} cycles repeatedly through two phases:

* *Agenda evaluation.* In this phase, the {RULE_ENGINE} selects all rules that can be executed. If no executable rules exist, the execution cycle ends. If an executable rule is found, the {RULE_ENGINE} registers the internalMatch in the agenda and then moves on to the working memory actions phase to perform rule consequence actions.
* *Working memory actions.* In this phase, the {RULE_ENGINE} performs the rule consequence actions (the `then` portion of each rule) for all activated rules previously registered in the agenda. After all the consequence actions are complete or the main Java application process calls `fireAllRules()` again, the {RULE_ENGINE} returns to the agenda evaluation phase to reassess rules.

.Two-phase execution process in the {RULE_ENGINE}
ifdef::DROOLS,JBPM,OP[]
image::rule-engine/Two_Phase.png[align="center"]
endif::[]
ifdef::DM,PAM[]
image::rule-engine/Two_Phase_enterprise.png[align="center"]
endif::[]

When multiple rules exist on the agenda, the execution of one rule may cause another rule to be removed from the agenda. To avoid this, you can define how and when rules are executed in the {RULE_ENGINE}. Some common methods for defining rule execution order are by using rule salience, agenda groups, or internalMatch groups.

== Salience for rules

Each rule has an integer `salience` attribute that determines the order of execution. Rules with a higher salience value are given higher priority when ordered in the internalMatch queue. The default salience value for rules is zero, but the salience can be negative or positive.

For example, the following sample DRL rules are listed in the {RULE_ENGINE} stack in the order shown:

[source]
----
rule "RuleA"
salience 95
when
    $fact : MyFact( field1 == true )
then
    System.out.println("Rule2 : " + $fact);
    update($fact);
end

rule "RuleB"
salience 100
when
   $fact : MyFact( field1 == false )
then
   System.out.println("Rule1 : " + $fact);
   $fact.setField1(true);
   update($fact);
end
----

The `RuleB` rule is listed second, but it has a higher salience value than the `RuleA` rule and is therefore executed first.

== Agenda groups for rules

An agenda group is a set of rules bound together by the same `agenda-group` rule attribute. Agenda groups partition rules on the {RULE_ENGINE} agenda. At any one time, only one group has a _focus_ that gives that group of rules priority for execution before rules in other agenda groups. You determine the focus with a `setFocus()` call for the agenda group. You can also define rules with an `auto-focus` attribute so that the next time the rule is activated, the focus is automatically given to the entire agenda group to which the rule is assigned.

Each time the `setFocus()` call is made in a Java application, the {RULE_ENGINE} adds the specified agenda group to the top of the rule stack. The default agenda group `"MAIN"` contains all rules that do not belong to a specified agenda group and is executed first in the stack unless another group has the focus.

For example, the following sample DRL rules belong to specified agenda groups and are listed in the {RULE_ENGINE} stack in the order shown:

.Sample DRL rules for banking application
[source]
----
rule "Increase balance for credits"
  agenda-group "calculation"
when
  ap : AccountPeriod()
  acc : Account( $accountNo : accountNo )
  CashFlow( type == CREDIT,
            accountNo == $accountNo,
            date >= ap.start && <= ap.end,
            $amount : amount )
then
  acc.balance  += $amount;
end
----

[source]
----
rule "Print balance for AccountPeriod"
  agenda-group "report"
when
  ap : AccountPeriod()
  acc : Account()
then
  System.out.println( acc.accountNo +
                      " : " + acc.balance );
end
----

For this example, the rules in the `"report"` agenda group must always be executed first and the rules in the `"calculation"` agenda group must always be executed second. Any remaining rules in other agenda groups can then be executed. Therefore, the `"report"` and `"calculation"` groups must receive the focus to be executed in that order, before other rules can be executed:

.Set the focus for the order of agenda group execution
[source,java]
----
Agenda agenda = ksession.getAgenda();
agenda.getAgendaGroup( "report" ).setFocus();
agenda.getAgendaGroup( "calculation" ).setFocus();
ksession.fireAllRules();
----

You can also use the `clear()` method to cancel all the internalMatches generated by the rules belonging to a given agenda group before each has had a chance to be executed:

.Cancel all other rule internalMatches
[source,java]
----
ksession.getAgenda().getAgendaGroup( "Group A" ).clear();
----

== Activation groups for rules

An internalMatch group is a set of rules bound together by the same `activation-group` rule attribute. In this group, only one rule can be executed. After conditions are met for a rule in that group to be executed, all other pending rule executions from that internalMatch group are removed from the agenda.

For example, the following sample DRL rules belong to the specified internalMatch group and are listed in the {RULE_ENGINE} stack in the order shown:

.Sample DRL rules for banking
[source]
----
rule "Print balance for AccountPeriod1"
  activation-group "report"
when
  ap : AccountPeriod1()
  acc : Account()
then
  System.out.println( acc.accountNo +
                      " : " + acc.balance );
end
----

[source]
----
rule "Print balance for AccountPeriod2"
  activation-group "report"
when
  ap : AccountPeriod2()
  acc : Account()
then
  System.out.println( acc.accountNo +
                      " : " + acc.balance );
end
----

For this example, if the first rule in the `"report"` internalMatch group is executed, the second rule in the group and all other executable rules on the agenda are removed from the agenda.
