I have been playing around with JBoss Drools(Version 4.0.7) – the open source rules engine. JBoss supports business rules implementation using three techniques:
Decision Tables
Writing DRL file
Defining business flow using rules flow rf file
This post is going to cover the first technique for business rules definition using Drools Decision table.
Business users regularly crib about the fact that they need IT involvement to make changes to business rules. One of the typical business rules implementation requirement is a decision table. Business rules can be laid out in tabular fashion and association between conditions and actions clearly defined.
JBoss Drools simplifies the decision table implementation approach by supporting defining decision tables in Microsoft Excel spreadsheets. For better understanding, I am going to use a simple insurance quick quote example.
The first thing to get started is installing Eclipse on your machine. I had Eclipse Europa version installed on my machine, hence I have to pick up the appropriate Drools Engine, Eclipse plug-in download. Next comes the procedure for setting up Drools Engine, IDE et al is available here.
If the Drools Eclipse plug-in setup is working fine, you should be able to use the Eclipse File –> New menu to create a new Rule Project. In the newly created project named say “BusinessRules”, you will see the following folder structures:
The src/main/java folder will hold the java class file source code and the rules files (.xls, .drl, .rf) wil be housed in src/main/rules. To create a new Decision table, select File –> New –> New Decision Table. The excel spreadsheet created will have the same features of a normal MS Excel spreadsheet except the rows 1 to 10 which have been created with information specific to Drools.
Please find below a screen shot of the decision table I prepared for an insurance quoting engine. The table decides based on the following if the applicant is eligible for insurance cover or not.
Applicant’s gender
Applicant’s age
Face Amount applied for
Policy Issue State
Smoker Status
Whether the applicant is suffering from any adverse disease.
In case the screen shot is not completely visible, click here to enlarge. Now that we have a sample decision tables done let’s set up the java source.
package com.insure.qq;
public class QuickQuoteInputProfile {
private String state = null;
private String gender = null;
private int age = 0;
private Double faceAmount = null;
private boolean adverseDiagnosis = false;
private SmokerProfile smokingProf = null;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Double getFaceAmount() {
return faceAmount;
}
public void setFaceAmount(Double faceAmount) {
this.faceAmount = faceAmount;
}
public boolean isAdverseDiagnosis() {
return adverseDiagnosis;
}
public void setAdverseDiagnosis(boolean adverseDiagnosis) {
this.adverseDiagnosis = adverseDiagnosis;
}
public SmokerProfile getSmokingProf() {
return smokingProf;
}
public void setSmokingProf(SmokerProfile smokingProf) {
this.smokingProf = smokingProf;
}
}
package com.insure.qq;
public class SmokerProfile {
private String smokerStatus = null;
public String getSmokerStatus() {
return smokerStatus;
}
public void setSmokerStatus(String smokerStatus) {
this.smokerStatus = smokerStatus;
}
}
Now that we have all the code we need, let’s try and understand what have done.
First things first the decision table. The rows C2, C3 and C4 store specific tag information, They specify that their adjoining columns D2, D3 and D4 signify the name of the ruleset, the java class import statements and notes regarding the rules if any. A developer should not add any information in these columns besides the ones specified. The excel spread sheet does allow the developer the flexibility of defining two rule tables. We will limit ourselves to using one. Rows C6 to C10 have their own significances. C6 is used to name the rules table, C7 by itself has not information but the subsequent columns can hold two values “CONDITION” or “ACTION”. Note that the rules will not be valid unless the value in the column is one or the other. In D8 and subsequent columns, we specify the actual java class referenced in the business rule. In our case it is QuickQuoteInputProfile. Note the notation used is <variable name>: <Java Class name>. There should always be a space after the colon or else you would end up debugging some weird Drools error messages. In D9 and the following columns we specify the class attribute and the condition in which it is analyzed. D10 and following columns can be used to give business friendly names to each evaluation parameter.
Now let us understand how each parameter is evaluated. Note that $param is a standard used to specify the value mentioned in the excel spreadsheet cell.
state in ($param) – It checks if the state requested for is part of the eligible states. Here state is an attribute of the QuickQuoteInputProfile class. Drools implicitly uses the getter method. The ‘in’ operator usage signifies list comparison. As we want multiple String value comparisons, they are defined in the cell using a comma separator. The ” ” around the value specifies that the value is evaluated as a string.
gender == $param – String or any other primitive data type can be compared using the == operator. Putting the apostrophes around the param “$param” converts the evaluation values i.e. MALE/FEMALE into string values.
age >= $1, age <=$2 – In case we need to do a range comparison like an applicant’s a
ge is within a given range, we can use the greater than, less than operators and use $1 and $2 as place holders. You can also use $param1 etc as the name. Also note that the comma separator between the age >= $1, age <= $2 is an implicit AND condition. This can be changed. To make the condition an OR condition instead of age >= $1, age <= $2 put the condition age >= $1 || age <= $2 and to make the condition more explicit with respect to the other conditions, enclose this condition in brackets like (age >= $1 || age <= $2).
quickQuoteProfile.smokingProf.smokerStatus == “$param” – It is possible that we are evaluating an object composed of objects. Drools makes it possible to navigate the entire hierarchy, using the dot(.) notation. Just ensure that all the objects are instantiated(otherwise you will get NullPointerExceptions) and that the getters will appropriate access modifiers provided.
Sometimes we need to write rules that will be triggered by the mere presence or absence of an object. For example, if SmokerProfile object exists within QuickQuoteInputProfile, then take certain action. In DRL this can be done by exists quickQuoteProfile.smokingProf(), unfortunately this fails in Excel based decision tables as a param is expected. Therefore the work around is to define the condition as exists (quickQuoteProfile.smokingProf.smokerStatus == $param) and in the rule cell write smokerStatus. The rule achieves the same effect as required.
Note that all rules are evaluated with an implicit AND condition between them. For example, rule 1 translates to the following condition:
The policy issue state should be one of the US states “VA”, “PA”, “NY” AND applicant gender should be MALE AND applicant age is greater than 20 and less than 65 ANDfaceamount greater than 50K and less than 250K AND applicant is a non-smoker AND applicant does not suffer from any disease which could lead to an adverse rating.
I will cover the ACTION using the following screenshot.
A typical rule will have a condition, which is evaluated and based on the evaluation an action taken. The decision/action arrived at by rules engine is conveyed to rules engine invoking client via a java object. Drools has a concept of a global variable. It can be defined as specified in row 25. In cell D25, we store the complete class name and the variable name. In our current example it is “com.insure.qq.ro.QuickQuoteResult result” where result is the variable name. The structure of the Java class QuickQuoteResult is as below:
package com.insure.qq.ro;
public class QuickQuoteResult {
private boolean eligible = false;
public boolean isEligible() {
return eligible;
}
public void setEligible(boolean eligible) {
this.eligible = eligible;
}
}
How does the decision table know that this is the class to instantiate? In cell J9, we say result.setEligible($param) and in cell C25 and D25 we specify the Variable and variable class name. Note that J9 is a cell defined under the “ACTION” column, thus translating to an action condition.(Hope this write-up is satisfactory “Novice”. Thanks for the rap on the head, must have become lazy.)
Now how do we run the rules engine. Create the following test class:
package com.insure.qq.test;
import java.io.StringReader;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.audit.WorkingMemoryFileLogger;
import org.drools.compiler.PackageBuilder;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.drools.rule.Package;
import com.insure.qq.QuickQuoteInputProfile;
import com.insure.qq.SmokerProfile;
import com.insure.qq.ro.QuickQuoteResult;
public class QQBRETest {
public static void main(String[] args) {
try {
//load up the rulebase
RuleBase ruleBase = readDecisionTable();
WorkingMemory workingMemory = ruleBase.newStatefulSession();
WorkingMemoryFileLogger logger = new WorkingMemoryFileLogger(workingMemory);
logger.setFileName("C:/drools-audit");
QuickQuoteInputProfile input = new QuickQuoteInputProfile();
input.setAge(21);
input.setFaceAmount(Double.valueOf(200000));
input.setState("VA");
input.setGender("MALE");
input.setAdverseDiagnosis(false);
SmokerProfile prof = new SmokerProfile();
prof.setSmokerStatus("Y");
input.setSmokingProf(prof);
QuickQuoteResult result = new QuickQuoteResult();
workingMemory.insert(input);
workingMemory.setGlobal("result", result);
workingMemory.fireAllRules();
logger.writeToDisk();
System.out.println(result.isEligible());
} catch (Throwable t) {
t.printStackTrace();
}
}
private static RuleBase readDecisionTable() throws Exception {
//read in the source
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final String drl = converter.compile( "/QuickQuoteExample.xls", InputType.XLS );
System.out.println(drl);
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new StringReader( drl ) );
Package pkg = builder.getPackage();
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( pkg );
return ruleBase;
}
}
Note the usage of the WorkingMemoryFileLogger. This will create an audit file named drools-audit.log in C: drive. You can view the contents using the audit view within the Drools Eclipse perspective. In the readDecisionTable method, there is an implementation of converting the decision table spreadsheet into Drools DRL file.
Update(16th December 2009):
My previous decision table example considered only one input object. In case there are more than one input objects, the decision table has no problem in supporting them. Please refer the decision table excel sheet below and for better viewing refer here.
The rest of the structure remains the same except the addition of a new column J with rule name header “Driving Violations” in the excel sheet and addition of a new row Rule-14.
Please find below the new test code for the updated decision table.
package com.insure.qq.test;
import java.io.StringReader;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.audit.WorkingMemoryFileLogger;
import org.drools.compiler.PackageBuilder;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.drools.rule.Package;
import com.insure.qq.DrivingViolations;
import com.insure.qq.QuickQuoteInputProfile;
import com.insure.qq.SmokerProfile;
import com.insure.qq.ro.QuickQuoteResult;
public class QQBRETest {
public static void main(String[] args) {
try {
//load up the rulebase
RuleBase ruleBase = readDecisionTable();
WorkingMemory workingMemory = ruleBase.newStatefulSession();
WorkingMemoryFileLogger logger = new WorkingMemoryFileLogger(workingMemory);
logger.setFileName("C:/drools-audit");
QuickQuoteInputProfile input = new QuickQuoteInputProfile();
input.setAge(21);
input.setFaceAmount(Double.valueOf(200000));
input.setState("VA");
input.setGender("MALE");
input.setAdverseDiagnosis(false);
SmokerProfile prof = new SmokerProfile();
prof.setSmokerStatus("Y");
input.setSmokingProf(prof);
QuickQuoteResult result = new QuickQuoteResult();
DrivingViolations vol = new DrivingViolations();
workingMemory.insert(input);
workingMemory.insert(vol);
workingMemory.setGlobal("result", result);
workingMemory.fireAllRules();
logger.writeToDisk();
System.out.println(result.isEligible());
} catch (Throwable t) {
t.printStackTrace();
}
}
private static RuleBase readDecisionTable() throws Exception {
//read in the source
final SpreadsheetCompiler converter = new SpreadsheetCompiler();
final String drl = converter.compile( "/QuickQuoteExample.xls", InputType.XLS );
System.out.println(drl);
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new StringReader( drl ) );
Package pkg = builder.getPackage();
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( pkg );
return ruleBase;
}
}
This portion of the post is in response to Jagadeesh’s query regarding accessing object variables. My assumption is that he is interested is ascertaining the possibility of accessing input object variables within the ACTION column. Here’s how you can set the input variable’s value in the action column. I have made the following modifications to the updated decision table. In cell L9, the cell below the ACTION header cell, I have replaced result.setEligible($param); with quickQuoteProfile.setFlag($param); In the QuickQuoteInputProfile class I have added a boolean property flag with its accessors and modifiers. The cell corresponding to the ACTION column for Rule-14 has been left blank. This is necessary as the new decision table has two objects as input. Rule-14 does not require the QuickQuoteInputProfile, therefore there is no variable reference to this class’s instance in rule-14’s when clause. If a value was put in the ACTION column cell for rule-14, we would get a exception. Refer the decision table below:
Finally, In case you need to explicitly set some values directly in the ACTION column or use some values from the input object, do as shown in the diagram. The value in the ACTION cell for the individual rules is semi-colon (;). It works! Refer the decision table below:
Hi,
Thanks for updating the already well-written article to make it Perfect :-).
I have a small query. I have a set of rules each one almost like-
rule “Rule 1”
salience 1
no-loop true
when
ruleReq : ArrayList()
k : Key(keyName == “Form1”, keyValue == “101” || keyValue == “102” || keyValue == “103” )
then
ruleReq.add(new Key(k.getKeyName(), k.getKeyValue()));
end
The action part of this rule is not working fine in the decision table. Can you suggest how can I write the Then part of this rule in Decision table?
Thanks for your response. Actually I tried with the global variable but could not get the desired results by adding values to result Array List using decision table. If you have any more clues for this, please post them here.
Also, If possible, can you explain how to use functions in Decision tables? I’m struggling to get a few functions working with decision tables.
Thanks in advance,
Novice
Here’s something to try out. I have used the code as per my Drools post titled “Defining business Rules”. I have added the following rule in the sample DRL:
rule “Check a variation in code”
salience 88
when
$policy : Policy()
$list: ArrayList()
from accumulate ( $coverage : Coverage(faceAmount > 25000) from $policy.coverages,
init (ArrayList list = new ArrayList();),
action (list.add($coverage);),
reverse(;),
result(list)
)
then
result.setCoverages($list);
end
Added the following line of code in the PolicyRuleResult class with its appropriate getter and setter.
private List coverages = new ArrayList();
I think you will need a similar approach to tackle your key related problem. Hope this helps. As regards using functions in Decision tables, frankly I have not tried and I believe it will be a waste of effort. There is nothing in Drools documentation to suggest ways in implementing the same. IMHO better to code it in DRL.
I have updated the post today with some more samples which should address your query. In case that is not adequate please reply back with specific information about what your requirement is.
null checks should be easy. Please refer my decision table example. Let’s look at a specific condition, gender. Presently the condition is put in as gender == $param. Replace it as follows:
I wish there was something like that available. However I am not aware of any way in which it is possible to create a decision table from a rules file.
Thanks President. Your responses are helpful. Can we sequence conditions and actions in decision tables? I tried to do an example but it looks like all conditions and actions are grouped seperately so that conditions are evaluated first and then the actions (all of them) are evaluated next. Is it possible to have a sequence. I know agenda-group is an option with drl…is the same possible with decision tables?
So basically i am checking to see if i can have 2 conditions then do an action and then do few more conditions and then do action…and so…
Yea, I have this yesterday. But how about >> So basically i am checking to see if i can have 2 conditions then do an action and then do few more conditions and then do action…and so…
I think we are stretching it out quite a bit. Whatever I will be recommending next is purely speculation from my end. I think you will need to use agendagroup and setFocus together.
Refer setFocus links 1 and 2. drools.setFocus is available in 4.0.7 and not in 5.0. For 5.0 use the option specified in link 2.
Here’s what I recommend. Put in CONDITION 1 and in ACTION 1 do your actionable activities and then setFocus to agendagroup2. This should trigger the relevant rules(s) causing action 2 to get invoked.
I have an xml file and have generated java objects using jaxb. There are multiple elements in the xml with multiple attributes. How do I write a rule which tests all the elements of a particular type ie., which is of list type ?
As I understand it your requirement is to verify that elements/attributes defined within a XML conform to a specific type.
I am not sure why you are trying to implement this functionality in a rules engine. It would be more appropriate to define an xml schema and verify the xml file compliance to the schema.
I am sorry, that is not my requirement. May be , I havent putforth my thoughts clearly. Let me explain.
We are developing an application which process loan application. The front end is done and the values are stored . Next step, we are calling a webservice which gives me a loan application stored values for a particular “id” in xml format and that is fed to jaxb , thereby obtaining java objects. Next step, we are integrating these objects with Drools rule engine wherein some rules are fed.
Now, my problem is, the objects that I have obtained is of list type and I need to iterate through the rule engine.How do I do that ? Please help me…
I understand your requirement. I am cannot think how this can be implemented in decision tables. However if you are interested in a normal DRL it is possible. Check out how I have used collection of coverages in my other Drools post.
Hi,
Is the following possible with Drools, if yes, how?-
Say I define 5 rules and my input criteria fails for all 5.
Can I specify a 6th rule which can be used as a default, like if the first 5 fail to get an action, use the 6th for getting the action?
I think you are looking for something like the switch operator in programming languages. If all cases fail, use default. Unfortunately it does not apply in BRMS. Based on the input data, BRMS are programmed to identify the applicable rules and execute only the applicable rules. This is unlike programming languages where each condition is evaluated at runtime. Therefore in your case you will have to write a business rule covering the failure of all the earlier five conditions to get rule no. 6 to execute.
Dear Sir,
I have another query with Drools, it would be great if you could spare some time to reply to it-
How is it possible to force the rule matching to exit once a match has been found?
I mean if I have 50 rules and the 5th rules matches, I want the system to exit with the result of 5th rule and not process the remaining 45 rules.
Is there a way to achieve that?
Thanks
Ankit
Actually, THis is possible. If you have a column called XOR-GROUP and have a common name for all the 50 rules, then Drools will exit from the agenda as soon as the first rule is executed.
Also, you can use a PRIORITY column to indicate the salience of the rules, and this way the most apt rule will get fired first and exit
Thanks pointing out my oversight and for the information pvm.
I have question, for your rule-3, if state=”CA”, Gender=”MALE”,is the result still false? what empty condition mean?
Yes in case of rule-3, the state=”CA” will be evaluated and the result will be false. I am not sure what you mean by an empty condition, please elaborate.
I am new to decision tables. I just started working on an existing project. They have defined the condition as
currentEnrollmentStatus==”$1″ ||currentEnrollmentStatus==”$2″ ||currentEnrollmentStatus==”$3″
and action as m.addNextAvailableStatus(“$param”);
There is a record having condition as LM10 and the action as LM2.
But if the input is LM1, the application is giving LM2. The reason is that LM1 is a substring of LM10. Basically, it is evaluating a condition by doing startswith instead of equals. Any idea how to fix this?
Its been some time since I worked on this. Here’s a wild guess use “/CheckAccepted.xls” instead of “CheckAccepted.xls”. I am assuming that the xls file is in the classpath.
I am also getting an error when using more than 9 parameters like $10 in decision table. When the param has two digits like in the case of $10, $11, etc, Drools is replacing it with the value for $1 and adding the next digit (‘0’ for 10, ‘1’ for 11, ‘2’ for 12, etc) to it rather than using the 10th value.
The selection between decision table or DRL is purely driven by whether the rule can be set up in decision table or not. If yes, decision table is the way to go. If not, use DRL to model. From a runtime standpoint there is no difference as decision tables are converted in drl files.
Generally complex business rules cannot be modeled in decision table, therefore you will naturely use DRL.
Hi, how do i do in java to get al matched rules?,
i use
session.insert(someobject);
int rulesMatch = session.fireAllRules();
rulesMatch counts 2 rules, in the variable someobject has the result of the first matche rules, buy how i do get the other matched rules?
I have tried the above example.when i try to run the class QQBERTest.java.
i am getting the following error.
WARNING: Wasn’t able to correctly close stream for decision table. nulljava.lang.NullPointerException
at jxl.read.biff.File.(File.java:91)
at jxl.Workbook.getWorkbook(Workbook.java:268)
at org.drools.decisiontable.parser.xls.ExcelParser.parseFile(ExcelParser.java:75)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:89)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:68)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:110)
at com.insure.qq.test.QQBRETest.readDecisionTable(QQBRETest.java:58)
at com.insure.qq.test.QQBRETest.main(QQBRETest.java:24)
I am using drools5.3 version.Please help me in resolving the issue.
My take is that the xls file is not available in the classpath. Ensure that the xls file is present in your classpath. Alternatively use the overloaded version of the compile method which accepts InputStream. Use the absolute file path to pass the xls input stream.
Facing following issues with decision tables on drools 5.3.
1.Not able to specify the dialect for the rule inside the decision table.when i specify the dialect on the decision table after the condition column,Getting error saying only one Duration cell will be allowed.
2. Not able to specify the auto-focus attribute for rules inside the decision tables.
3.will it be possible to use drools fusion concepts inside the decision tables.
for example i want to see if there any two events(with same attributes) with in 5 seconds or using over the window of 5 seconds.Basically i want to use the fusion 14 keywords(after,before etc) inside the decision tables.
Great Article Mr.President… Can you please throw more light on NAME keyword and can we just invoke a particular Rule usign the entities under NAME keyword. My requirement is something like i need to check for e.g. the age and the policy number length. My age Check should only execute when i give the ageCheckRule and same for policy number. Can we invoke a rule separately based on Rule Name under NAME keyword?
Thanks for your response…
It has been a long time since I looked up Drools so my knowledge would be rusty. However I doubt that you can invoke a specific rule directly using a name. Only if the conditions are satisfied will the rule be invoked.
Hi President,
I tried decision table example.In that i need to use more than one class attributes in single condition.How to resolve this?
Thanks in Advance
Suppose the users want to write only the rule which set to true when all the coditions true. Because creating rules per combination of conditions lead to a huge number of business rules. But if the rule was failed, they need to know which all conditions failed. Would that be possible?
how to add the following rule in decision table.
rule “Check a variation in code”
salience 88
when
$policy : Policy()
$list: ArrayList()
from accumulate ( $coverage : Coverage(faceAmount > 25000) from $policy.coverages,
init (ArrayList list = new ArrayList();),
action (list.add($coverage);),
reverse(;),
result(list)
Hi,
The article was really good, but i am facing some problem:
I have a class:
class Client
{
int id;
Sting name;
// getters and setters
}
class user
{
int id;
Client client;
// getters and setters
}
// In the code:
Client client = new Client ( 1, “Client1” );
User user = new User(1, client);
FactHandle userFact = (FactHandle) knowledgeSession.insert ( user );
How do i access the client id in the decision table?
i am using excel
Thanks a lot for writing such a wonderful article. I want to integrate Drools Decision Table but want to provide Users capability to create tables in a CSV Format. Due you have a sample CSV file that accomplishes same goals as above mentioned example?
I have a comma separated string as value of an action column which I would like to set in a string array parameter of an action method if the condition is met. However, I am just getting the first string with $1…how can I get comma separated string as string array?
The calculation done in Action is as below : Corresponding to amount 80, corresponding to percentage 80 and corresponding to addition 60. So 240 is calculate as 80+80+60
Now in future if business decided to change the value of amount from 80 to 20. In that case i have to update each and every combination. Right now I have 200 such combinations.
Can any one let me know how i can specify the values of amount, percentage and addition in another condition column that way instead of hardcoding the 220 i can use the value from that conditions in my action and then i can write the formula like
condition4+ condition5+condition6
Hi, I’m working on agenda-group in decision table in which I have two coditions, Action and agenda-group. When I fire the rule it is considering only one condition and ignoring other condition. Can someone please let me know?
Hello Mr. President,
I wanted to know if any API exists which can add one rule to decision table and as soon as a change is detected in the file, the updated decision table is added to the working memory.
The article is good but the action part has not been described clearly.
Hi,
Thanks for updating the already well-written article to make it Perfect :-).
I have a small query. I have a set of rules each one almost like-
rule “Rule 1”
salience 1
no-loop true
when
ruleReq : ArrayList()
k : Key(keyName == “Form1”, keyValue == “101” || keyValue == “102” || keyValue == “103” )
then
ruleReq.add(new Key(k.getKeyName(), k.getKeyValue()));
end
The action part of this rule is not working fine in the decision table. Can you suggest how can I write the Then part of this rule in Decision table?
Thanks in advance,
FanduMax
I do not have a ready codebase available to validate, but my first suggestion would be to make ruleReq a global variable.
Hi Mr. President,
Thanks for your response. Actually I tried with the global variable but could not get the desired results by adding values to result Array List using decision table. If you have any more clues for this, please post them here.
Also, If possible, can you explain how to use functions in Decision tables? I’m struggling to get a few functions working with decision tables.
Thanks in advance,
Novice
Here’s something to try out. I have used the code as per my Drools post titled “Defining business Rules”. I have added the following rule in the sample DRL:
rule “Check a variation in code”
salience 88
when
$policy : Policy()
$list: ArrayList()
from accumulate ( $coverage : Coverage(faceAmount > 25000) from $policy.coverages,
init (ArrayList list = new ArrayList();),
action (list.add($coverage);),
reverse(;),
result(list)
)
then
result.setCoverages($list);
end
Added the following line of code in the PolicyRuleResult class with its appropriate getter and setter.
private List coverages = new ArrayList();
I think you will need a similar approach to tackle your key related problem. Hope this helps. As regards using functions in Decision tables, frankly I have not tried and I believe it will be a waste of effort. There is nothing in Drools documentation to suggest ways in implementing the same. IMHO better to code it in DRL.
If a function is invoked from action column, does it pick the attributes that were assigned from the condition columns?
Adding Drools functions is very difficult to implement using decision tables. My recommendation is to use a DRL.
How can I access object variables and their values in decision tables?
I have updated the post today with some more samples which should address your query. In case that is not adequate please reply back with specific information about what your requirement is.
Woh…that is very helpful.
I have another question…how do I check for not null condition through decision table. Is it possible.
Thanks
null checks should be easy. Please refer my decision table example. Let’s look at a specific condition, gender. Presently the condition is put in as gender == $param. Replace it as follows:
gender !=null && gender == $param
This will evaluate as per your requirement.
Also is there a way to generate decision table from rules file?
I wish there was something like that available. However I am not aware of any way in which it is possible to create a decision table from a rules file.
😉
Thanks President. Your responses are helpful. Can we sequence conditions and actions in decision tables? I tried to do an example but it looks like all conditions and actions are grouped seperately so that conditions are evaluated first and then the actions (all of them) are evaluated next. Is it possible to have a sequence. I know agenda-group is an option with drl…is the same possible with decision tables?
So basically i am checking to see if i can have 2 conditions then do an action and then do few more conditions and then do action…and so…
JM,
I found a reference to agenda group here. I have not tried it myself. You can take a shot and let me know.
Do note that my code has been tested with Drools 4.0.7 and not 5.0. So I am not sure if this feature is available in 4.0.7.
Yea, I have this yesterday. But how about >> So basically i am checking to see if i can have 2 conditions then do an action and then do few more conditions and then do action…and so…
Is this possible?
Jagadeesh,
I think we are stretching it out quite a bit. Whatever I will be recommending next is purely speculation from my end. I think you will need to use agendagroup and setFocus together.
Refer setFocus links 1 and 2. drools.setFocus is available in 4.0.7 and not in 5.0. For 5.0 use the option specified in link 2.
Here’s what I recommend. Put in CONDITION 1 and in ACTION 1 do your actionable activities and then setFocus to agendagroup2. This should trigger the relevant rules(s) causing action 2 to get invoked.
Let me know if this works.
Thanks for the info. One thing that’s left out is how to query an object from working memory? You had that covered in the DRL example.
If your question is how to implement QueryResults in decision tables, I am not sure either. Sorry about that. 🙂
how many rule can write in excel Decision table…any one know..
Upul,
I do not believe there should be any specific limits except for the ones defined within EXCEL.
Hi, great article.
Do you know how can I check conditions using values from 2 variables? I Tried to do something like (Column G):
http://img269.imageshack.us/i/drool1.png/
But I always get errors, although it works when a I use the variable in the ACTION Column I.
I Also tried thos approach: http://img94.imageshack.us/i/drool2.png/
This way I get no errors but the condition always returns true.
UPDATE
Already fix the problem. I had to define the get/set for the variable calcEsp.
Hi,
I have an xml file and have generated java objects using jaxb. There are multiple elements in the xml with multiple attributes. How do I write a rule which tests all the elements of a particular type ie., which is of list type ?
Thanks and regards,
Anitha
Anitha,
As I understand it your requirement is to verify that elements/attributes defined within a XML conform to a specific type.
I am not sure why you are trying to implement this functionality in a rules engine. It would be more appropriate to define an xml schema and verify the xml file compliance to the schema.
Hi,
I am sorry, that is not my requirement. May be , I havent putforth my thoughts clearly. Let me explain.
We are developing an application which process loan application. The front end is done and the values are stored . Next step, we are calling a webservice which gives me a loan application stored values for a particular “id” in xml format and that is fed to jaxb , thereby obtaining java objects. Next step, we are integrating these objects with Drools rule engine wherein some rules are fed.
Now, my problem is, the objects that I have obtained is of list type and I need to iterate through the rule engine.How do I do that ? Please help me…
Thanks and regards,
Anitha.
I understand your requirement. I am cannot think how this can be implemented in decision tables. However if you are interested in a normal DRL it is possible. Check out how I have used collection of coverages in my other Drools post.
I hope this answers your question.
Mr. President,
Could you please send me the decision table excel sheet?
Sorry Ganesh, I no longer have the source with me.
Hi,
Is the following possible with Drools, if yes, how?-
Say I define 5 rules and my input criteria fails for all 5.
Can I specify a 6th rule which can be used as a default, like if the first 5 fail to get an action, use the 6th for getting the action?
Please try to reply ASAP.
Thanks
Ankit
Hi Ankit,
I think you are looking for something like the switch operator in programming languages. If all cases fail, use default. Unfortunately it does not apply in BRMS. Based on the input data, BRMS are programmed to identify the applicable rules and execute only the applicable rules. This is unlike programming languages where each condition is evaluated at runtime. Therefore in your case you will have to write a business rule covering the failure of all the earlier five conditions to get rule no. 6 to execute.
Thanks for your kind reply.
Dear Sir,
I have another query with Drools, it would be great if you could spare some time to reply to it-
How is it possible to force the rule matching to exit once a match has been found?
I mean if I have 50 rules and the 5th rules matches, I want the system to exit with the result of 5th rule and not process the remaining 45 rules.
Is there a way to achieve that?
Thanks
Ankit
Ankit,
To the best of my knowledge what you are asking for is not supported in Drools.
Actually, THis is possible. If you have a column called XOR-GROUP and have a common name for all the 50 rules, then Drools will exit from the agenda as soon as the first rule is executed.
Also, you can use a PRIORITY column to indicate the salience of the rules, and this way the most apt rule will get fired first and exit
Thanks pointing out my oversight and for the information pvm.
I have question, for your rule-3, if state=”CA”, Gender=”MALE”,is the result still false? what empty condition mean?
Sara,
Yes in case of rule-3, the state=”CA” will be evaluated and the result will be false. I am not sure what you mean by an empty condition, please elaborate.
Mr. President,
I am new to decision tables. I just started working on an existing project. They have defined the condition as
currentEnrollmentStatus==”$1″ ||currentEnrollmentStatus==”$2″ ||currentEnrollmentStatus==”$3″
and action as m.addNextAvailableStatus(“$param”);
There is a record having condition as LM10 and the action as LM2.
But if the input is LM1, the application is giving LM2. The reason is that LM1 is a substring of LM10. Basically, it is evaluating a condition by doing startswith instead of equals. Any idea how to fix this?
Hi Maddy,
Could you please elaborate your issue, I am still not clear around what function/operator are you using to get a substring.
I was following your tutorial and decided to try to create my own decision table.
Only i get some strange errors….
Maybe you have an idea?
See this link for all the info:
http://drools.46999.n3.nabble.com/ERR-101-amp-102-When-parsing-Decision-Table-xls-tc3048185.html#none
Gr. Roy
Roy,
Its been some time since I worked on this. Here’s a wild guess use “/CheckAccepted.xls” instead of “CheckAccepted.xls”. I am assuming that the xls file is in the classpath.
Thank you so much for such clear explaination. It was helped me a lot.
Hi President,
I am getting problem while using more than 9 parameters in Decision Table. Is there any known issue in Drools 5.11 ??
RajCherukuri,
I have not used 5.1.1, so I am not sure if there is an issue. Can you explain what is the exact nature of your problem?
fentastic explanation guru
I am also getting an error when using more than 9 parameters like $10 in decision table. When the param has two digits like in the case of $10, $11, etc, Drools is replacing it with the value for $1 and adding the next digit (‘0’ for 10, ‘1’ for 11, ‘2’ for 12, etc) to it rather than using the 10th value.
Hi All,
Please suggest, when compared to decision table with DRL mechanism which one is better, if the business rules are huge and complicated ??
Thanks,
Kishore
Hi Kishore,
The selection between decision table or DRL is purely driven by whether the rule can be set up in decision table or not. If yes, decision table is the way to go. If not, use DRL to model. From a runtime standpoint there is no difference as decision tables are converted in drl files.
Generally complex business rules cannot be modeled in decision table, therefore you will naturely use DRL.
Hi, how do i do in java to get al matched rules?,
i use
session.insert(someobject);
int rulesMatch = session.fireAllRules();
rulesMatch counts 2 rules, in the variable someobject has the result of the first matche rules, buy how i do get the other matched rules?
i hope you cna help me
thanks
I have tried the above example.when i try to run the class QQBERTest.java.
i am getting the following error.
WARNING: Wasn’t able to correctly close stream for decision table. nulljava.lang.NullPointerException
at jxl.read.biff.File.(File.java:91)
at jxl.Workbook.getWorkbook(Workbook.java:268)
at org.drools.decisiontable.parser.xls.ExcelParser.parseFile(ExcelParser.java:75)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:89)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:68)
at org.drools.decisiontable.SpreadsheetCompiler.compile(SpreadsheetCompiler.java:110)
at com.insure.qq.test.QQBRETest.readDecisionTable(QQBRETest.java:58)
at com.insure.qq.test.QQBRETest.main(QQBRETest.java:24)
I am using drools5.3 version.Please help me in resolving the issue.
Hi Srinivas,
My take is that the xls file is not available in the classpath. Ensure that the xls file is present in your classpath. Alternatively use the overloaded version of the compile method which accepts InputStream. Use the absolute file path to pass the xls input stream.
Hi President,
Thanks a lot .It is working after using InputStream in proper way as you suggested.
Facing following issues with decision tables on drools 5.3.
1.Not able to specify the dialect for the rule inside the decision table.when i specify the dialect on the decision table after the condition column,Getting error saying only one Duration cell will be allowed.
2. Not able to specify the auto-focus attribute for rules inside the decision tables.
3.will it be possible to use drools fusion concepts inside the decision tables.
for example i want to see if there any two events(with same attributes) with in 5 seconds or using over the window of 5 seconds.Basically i want to use the fusion 14 keywords(after,before etc) inside the decision tables.
Please provide me pointers for the same.
Is there any way to specify the stream name in descion table.
for example e:Event() from entry-point “XYZStream”.
Great Article Mr.President… Can you please throw more light on NAME keyword and can we just invoke a particular Rule usign the entities under NAME keyword. My requirement is something like i need to check for e.g. the age and the policy number length. My age Check should only execute when i give the ageCheckRule and same for policy number. Can we invoke a rule separately based on Rule Name under NAME keyword?
Thanks for your response…
Hi Ramanath,
It has been a long time since I looked up Drools so my knowledge would be rusty. However I doubt that you can invoke a specific rule directly using a name. Only if the conditions are satisfied will the rule be invoked.
Hi President,
I tried decision table example.In that i need to use more than one class attributes in single condition.How to resolve this?
Thanks in Advance
Suppose the users want to write only the rule which set to true when all the coditions true. Because creating rules per combination of conditions lead to a huge number of business rules. But if the rule was failed, they need to know which all conditions failed. Would that be possible?
Like to mention that this article has been of great help. Thank you
Thank you Mr President
how to add the following rule in decision table.
rule “Check a variation in code”
salience 88
when
$policy : Policy()
$list: ArrayList()
from accumulate ( $coverage : Coverage(faceAmount > 25000) from $policy.coverages,
init (ArrayList list = new ArrayList();),
action (list.add($coverage);),
reverse(;),
result(list)
)
then
result.setCoverages($list);
end
pls provide me examples , how to use agenta group in decision table
Hi,
The article was really good, but i am facing some problem:
I have a class:
class Client
{
int id;
Sting name;
// getters and setters
}
class user
{
int id;
Client client;
// getters and setters
}
// In the code:
Client client = new Client ( 1, “Client1” );
User user = new User(1, client);
FactHandle userFact = (FactHandle) knowledgeSession.insert ( user );
How do i access the client id in the decision table?
i am using excel
thanks in advance
Mr. President,
Thanks a lot for writing such a wonderful article. I want to integrate Drools Decision Table but want to provide Users capability to create tables in a CSV Format. Due you have a sample CSV file that accomplishes same goals as above mentioned example?
Regards,
Pankaj
I have a comma separated string as value of an action column which I would like to set in a string array parameter of an action method if the condition is met. However, I am just getting the first string with $1…how can I get comma separated string as string array?
Hi Good Article but can You please tell me the same code with Drools 6.0 or above??Will it be different and what will be the difference???Reply soon.
I am sorry, Ankit. This was a POC I did some time back, so I cannot confirm if this will work with Drools 6.0.
hi i have to populate a arraylist in action.Can you explain how to implement it using decsion table
Hi, I am working on a decision table which will do the calculation in the action. Below is the rule set :
Condition Condition Condition Action
$dto.amount $dto.percentage $dto.addition $dto.setFinalValue($param)
Rule-1 Yes Yes Yes 220
Rule-2 Yes NO Yes 140
The calculation done in Action is as below : Corresponding to amount 80, corresponding to percentage 80 and corresponding to addition 60. So 240 is calculate as 80+80+60
Now in future if business decided to change the value of amount from 80 to 20. In that case i have to update each and every combination. Right now I have 200 such combinations.
Can any one let me know how i can specify the values of amount, percentage and addition in another condition column that way instead of hardcoding the 220 i can use the value from that conditions in my action and then i can write the formula like
condition4+ condition5+condition6
Hi, I’m working on agenda-group in decision table in which I have two coditions, Action and agenda-group. When I fire the rule it is considering only one condition and ignoring other condition. Can someone please let me know?
Hi, Can we add ‘OR’ between two CONDITION columns ?
Thanks, Kaushik
Hi Kaushik,
We can add OR between two Condition Columns via merging Columns in decision table.
Thanks,Muthu
Hello Mr. President,
I wanted to know if any API exists which can add one rule to decision table and as soon as a change is detected in the file, the updated decision table is added to the working memory.