Drools Agenda Group setFocus - Java @ Desk

Tuesday, March 4, 2014

Drools Agenda Group setFocus

Drools Agenda Group setFocus

Agenda Group in Drools is special feature in Drools which contains a set of rules or a single rule within a group and it makes the knowledge session understand the activation of rules.

At a single moment of time, only one agenda group has focus that means only the rules in that group will be activated and fired.

By default every rule is associated with the MAIN agenda group.

Agenda group are useful to differentiate the set of rules from the rest of the rules in a knowledge session that apply to particular sub-process within a large process.

Agenda group can be changes using the focus either from java code or from rule API. Each time a focus is called it push that Agenda Group on top of a stack and execution starts. When the stack becomes empty, the agenda group focus shifts to MAIN. A Single agenda group can be focussed multiple times. The default Agenda Group is MAIN, all rules which do not specify an Agenda Group are placed there, it is also always the first group on the stack and given focus as default.

When the focus is set to some agenda group that is not available in the knowledge session it does not complaint anything it finishes the execution in a normally.

When the focus is set to some particular agenda group and if there exists a rule in the MAIN stack with higher salience, the activation will give preference to the agenda group's rule only and once agenda group finishes execution and if no more agenda's are available in the stack then the agenda MAIN will be preferred as shown below:

rule "Group One Agenda Group"
agenda-group "Group One"
salience 100

rule "Group Without Agenda Group"
salience 200
when

 
In this case if the agenda is set to "Group One" then this "Group One Agenda Group" will be fired first and then the agenda will shift to MAIN and "Group Without Agenda Group" will be fired.

How to set focus to agenda group from Java file

knowledgeSession.getAgenda().getAgendaGroup("Group One").setFocus();

 
How to set focus to agenda group from DRL file

kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup("Insufficient Balance").setFocus();

 
Sample Implementation : This implementation is to check if the account holder has already done the EMI payment for the loan amount for the month. For this the processing involves :
1) Check if bank balance is less than monthly installment. For this, the agenda group will be focussed to the rule to check this condition
2) If above rule fires successfully, set the agenda group to the rule which needs to send reminder email and halth the processing
3) If above rule fires fails, go the the rule with MAIN agenda group and fire that rule



AgendaGroupClient.java

package com.client;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;

import com.pojo.LoanAmount;

public class AgendaGroupClient {

    public static void main(String args[]) throws Exception {

        KnowledgeBase kbase = readKnowledgeBase();
        StatefulKnowledgeSession knowledgeSession = kbase.newStatefulKnowledgeSession();
        try {
            LoanAmount loanAmount = new LoanAmount();
            loanAmount.setBankBalance(10000);
            loanAmount.setMonthlyInstallment(8000);
            loanAmount.setAccountId("ACC013867");
            
            knowledgeSession.insert(loanAmount);
            knowledgeSession.getAgenda().getAgendaGroup("Check Balance").setFocus();
            knowledgeSession.fireAllRules();
        } finally {
            knowledgeSession.dispose();
        }
    }

    private static KnowledgeBase readKnowledgeBase() throws Exception {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newClassPathResource("AgendaGroup.drl"), ResourceType.DRL);
        KnowledgeBuilderErrors errors = kbuilder.getErrors();
        if (errors.size() > 0) {
            for (KnowledgeBuilderError error : errors) {
                System.err.println(error);
            }
            throw new IllegalArgumentException("Could not parse knowledge.");
        }

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
        return kbase;
    }
}
LoanAmount.java - Pojo File

package com.pojo;

public class LoanAmount {

    private String accountId;

    private Integer bankBalance;

    private Integer monthlyInstallment;

    private boolean insufficientBalance;

    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public Integer getBankBalance() {
        return bankBalance;
    }

    public void setBankBalance(Integer bankBalance) {
        this.bankBalance = bankBalance;
    }

    public Integer getMonthlyInstallment() {
        return monthlyInstallment;
    }

    public void setMonthlyInstallment(Integer monthlyInstallment) {
        this.monthlyInstallment = monthlyInstallment;
    }

    public boolean isInsufficientBalance() {
        return insufficientBalance;
    }

    public void setInsufficientBalance(boolean insufficientBalance) {
        this.insufficientBalance = insufficientBalance;
    }
}
AgendaGroup.drl

import com.pojo.*;

rule "Check Bank Balance"
agenda-group "Check Balance"
salience 100
when
    $loanAmount : LoanAmount(monthlyInstallment > bankBalance)
then
    System.out.println(drools.getRule().getName());
    kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup("Insufficient Balance").setFocus();
end

rule "Rule Insufficient Balance"
agenda-group "Insufficient Balance"
when
    $loanAmount : LoanAmount();
then
    $loanAmount.setInsufficientBalance(true);
    System.out.println("Insufficient Funds to perform operation. Send Reminder Email");
    drools.halt();
end

rule "Send Thanks Email"
salience 200
when
    $loanAmount : LoanAmount()
then
    System.out.println("EMI payment already done for account - " +$loanAmount.getAccountId());
end






2 comments:

  1. In this case, let's assume bank balance is greater than monthly installment, will the rule with agenda-group "Insufficient Balance" still execute??

    ReplyDelete
    Replies
    1. No that rule will not execute since the agenda group I am updating in the then part of this rule - kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup("Insufficient Balance").setFocus();

      which will only get executed when bank balance is less than monthly installment

      Delete