Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

drools: rules executed more than one time

Tags:

drools

I am trying hands on at the Drools rule engine , I am quite a beginner.

I have the following rules in place in a single rule file:

rule "A stand alone rule" 
salience 2
no-loop
when
    $account : Account()
    Account($account.balance>100)
then
    System.out.println("balance>100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());    
end

rule "A second Rule"
salience 1
no-loop
when
    $account : Account()
    Account($account.balance<100)
then
    System.out.println("balance<100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());
end 

In the StatefulKnowledgeSession I am passing TWO accounts , one with balance 15000 another with balance 15 ,

Account account=new Account(7l,15000l);
        Account account1=new Account(5l,15l);

        Customer customer = new Customer("Samrat", 28, "Sector51", account);
        Customer customer1 = new Customer("Alexi", 28, "Sector50", account1);
        account.setCustomer(customer);
        account1.setCustomer(customer1);
        session.insert(account);
        session.insert(account1);

        session.fireAllRules();

According to me the expected result should be that each rule should be fired only once and the corresponding object should be printed.

But the result I am getting is :

balance>100
15000
Samrat
balance>100
15000
Samrat
balance<100
15
Alexi
balance<100
15
Alexi

I am not able to understand why each rule is running twice ????

like image 480
Samrat Avatar asked Sep 24 '13 13:09

Samrat


1 Answers

Using multiple patterns (and not specifying any relation between them) will create a full Cartesian product (just like a select on multiple tables without a join clause). So, the rule:

rule A
when
    Account()
    Account()
then
    ...
end

will be activated N^2 times for N objects of type Account. One solution could be to use the magic field 'this' to specify that the second account is the same as the first one:

rule A
when
    $a: Account()
    Account(this == $a)
then
    ...
end

But, going back to your example, I think you don't even need to use 2 different patterns. You could rewrite your rules as following:

rule "A stand alone rule" 
salience 2
no-loop
when
    $account: Account(balance>100)
then
    System.out.println("balance>100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());    
end

rule "A second Rule"
salience 1
no-loop
when
    $account: Account(balance<100)
then
    System.out.println("balance<100");
    System.out.println($account.getBalance());
    System.out.println($account.getCustomer().getName());
end

Hope it helps,

like image 85
Esteban Aliverti Avatar answered Sep 30 '22 13:09

Esteban Aliverti