salience in drools:Part VII
One thing is pretty clear to us that How Drools works?
Let's summarize How it works.
Rules are written on the drl files. And facts or POJOs are inserted in Knowledge Base, Rules are applied on each fact, If When part of this rule satisfies with a fact, Then part will execute.
Having said that One question is just pop up my mind
If multiple rules are matched on a fact then which order those rules will be fired ?
The Answer is they will fire arbitrary, There is no sequence for Rules execution. So if we need a sequence or we want that a rule will fire at first, how we can achieve this?
In Drools we can achieve it through Salience, Salience is a keyword in the .drl file and we can assign a positive or negative number to salience.
This number denotes the priority, Higher number means higher priority, Rule with higher salience number will be executed first by Drools engine.
So If Rule 1 has salience 10 ,Rule 2 has 1 and Rule 3 has 5. Order of execution should be
Rule 1>Rule 3>Rule 2.
By default, the value of salience is 0. So if we do not mention the salience, all rules got the default salience 0.
If multiple rules have same salience , the there will be no order among them but Drools guarantee that they will execute at the same level.
So
So If Rule 1 has salience 10 ,Rule 2 has 10 and Rule 3 has 5. Then
Rule 1 or 2 will be executed first then Rule 3. We can not say which sequence Rule 1 or Rule 2 will be executed as they have same salience value but we can say that they will execute before Rule 3.
So Execution order will be
Either
Rule 1>Rule 2>Rule 3
Or
Rule 2>Rule 1>Rule 3
It is possible to assign negative value in Salience. But the question is why and when we use a negative value.
The answer is very simple if we want a rule will be fired at last we provide a negative value as a default value of salience is 0. If salience only accepts positive value then to execute a rule, at last, we have to provide the least value and we know default value of salience is 0. So in this case we have to change salience of all rules, think if a .drl file has 500 entries then we have to provide positive salience for each rule. But as negative value is accepted we just define the rule with negative salience in order to execute at last.
Let see How to use Salience in a problem context.
Say we will give a laptop to that manager who belongs to IT department?
One way to approach this problem is to write Rule in when part check if the department is IT and designation is Manager the give him a laptop. But this is not efficient as every fact execute this irrespective of the department. So if there is a huge number of facts it will execute for each fact .
But we can view this problem in another way, we can filter out fact based on department first then based on designation then give a laptop to remaining facts .
Example:
- Drools file employeeSalience.drlpackage com.rulesimport com.example.droolsExample.pojo.Employeeimport com.example.droolsExample.pojo.Departmentimport com.example.droolsExample.pojo.ITManagerrule "Not IT" salience 10lock-on-activewhen$emp: Employee("IT" != dept.getName());thenSystem.out.println("filter Dept ::" + $emp.getName());$emp.setFilter(true);update($emp);endrule "Not Manager" salience 5lock-on-activewhen$emp: Employee(manager==false);thenSystem.out.println("filter Manger ::" + $emp.getName());$emp.setFilter(true);update($emp);endrule "give Manager Laptop"when$emp: Employee(filter==false);then$emp.setMessage("Give Laptop");System.out.println($emp.getName()+ ": "+$emp.getDept().getName()+ ":"+$emp.getMessage());end2. Employee Object.package com.example.droolsExample.pojo;public class Employee {String name;boolean manager;String message;Department dept;boolean filter;public String getName() {return name;}public void setName(String name) {this.name = name;}public boolean isManager() {return manager;}public void setManager(boolean manager) {this.manager = manager;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Department getDept() {return dept;}public void setDept(Department dept) {this.dept = dept;}public boolean isFilter() {return filter;}public void setFilter(boolean filter) {this.filter = filter;}@Overridepublic String toString() {return "Employee [name=" + name + ", manager=" + manager + ", message="+ message + ", dept=" + dept + "]";}}3. Department Object:package com.example.droolsExample.pojo;public class Department {String name;public String getName() {return name;}public void setName(String name) {this.name = name;}}4. DroolsTest.javapackage com.example.droolsExample;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.Reader;import java.util.List;import org.drools.compiler.compiler.DroolsParserException;import org.drools.compiler.compiler.PackageBuilder;import org.drools.core.RuleBase;import org.drools.core.RuleBaseFactory;import org.drools.core.WorkingMemory;import org.drools.core.event.AgendaEventListener;import com.example.drools.listener.TrackingRuleFiredEventListener;import com.example.droolsExample.pojo.Department;import com.example.droolsExample.pojo.Employee;public class DroolsTest {public static void main(String[] args) throws DroolsParserException,IOException {DroolsTest droolsTest = new DroolsTest();//droolsTest.executeDrools();droolsTest.executeDroolsEmployee("/com/rules/employeeSalience.drl");}public void executeDroolsEmployee(String ruleFile) throws DroolsParserException, IOException {PackageBuilder packageBuilder = new PackageBuilder();//String ruleFile = "/com/rules/employee.drl";InputStream resourceAsStream = getClass().getResourceAsStream(ruleFile);Reader reader = new InputStreamReader(resourceAsStream);packageBuilder.addPackageFromDrl(reader);org.drools.core.rule.Package rulesPackage = packageBuilder.getPackage();RuleBase ruleBase = RuleBaseFactory.newRuleBase();ruleBase.addPackage(rulesPackage);WorkingMemory workingMemory = ruleBase.newStatefulSession();Department dep = new Department();dep.setName("Civil");Department dep1 = new Department();dep1.setName("IT");Employee emp = new Employee();emp.setName("Shamik Mitra");emp.setManager(true);emp.setDept(dep1);Employee emp2 = new Employee();emp2.setName("Swastika Mitra");emp2.setManager(false);emp2.setDept(dep1);Employee emp1 = new Employee();emp1.setName("Samir Mitra");emp1.setManager(true);emp1.setDept(dep);workingMemory.insert(dep);workingMemory.insert(dep1);workingMemory.insert(emp);workingMemory.insert(emp1);workingMemory.insert(emp2);workingMemory.fireAllRules();}}5. Output:filter Dept ::Samir Mitrafilter Manager ::Swastika MitraShamik Mitra: IT:Give Laptop