Академический Документы
Профессиональный Документы
Культура Документы
of Contents
1. Introduction 1.1
2. Technical Materials 1.2
3. Overview 1.3
4. Drools tutorial 1.4
1. Installing Drools Tooling 1.4.1
2. Data Model used in the tutorial 1.4.2
3. Lesson 1 : Core concepts 1.4.3
4. Lesson 2 : binding 1.4.4
5. lesson 3 : Some more drools languages 1.4.5
6. lesson 4 : ruleflow 1.4.6
7. lesson 5 : Exercise 1.4.7
1. Requirements 1.4.7.1
5. BRMS tutorial 1.5
1. Organizational Unit And repository 1.5.1
2. Data Model 1.5.2
3. Business Requirements 1.5.3
4. Design 1.5.4
5. Implementing the Process Flow 1.5.5
6. Implementation technical parts 1.5.6
7. Implementing the initial step 1.5.7
8. Implementing standard price step 1.5.8
9. Implementing the Child over 3 years old is free promotion step 1.5.9
10. Implementing the Birthday promotion step 1.5.10
11. Implementing the Zurich reduction step 1.5.11
12. Implementing the final step 1.5.12
13. Conclusion 1.5.13
6. BRMS Runtime tutorial 1.6
1. Install needed tools to run the workbench 1.6.1
1
Introduction
Introduction
Intended audience
This book as its title suggest is for newcomers to drools. As explained in the drools tutorial, when
using drools you will change the classical development paradigm you are using going from
procedurale to declarative programming. The shift is not complex to accomplish but there is a need
for a onboarding set of tutorials that will help you to jump into implementing algorith/business rules
wiht drools with no difficulty. As a regular trainer of drools, I can only encourage you to do the
exercices completely by yourself and try not to go the solutions directly. By doing so, the learning
curve will be a little longer but so much easier at the end. By going directly to the solution, you will
miss 50% of the training content.
drools On Boarding
You can find here all the materials that goes with this book. The book is also on github here .
2
Technical Materials
Technical Materials
Technical Materials
Here is the list of all source code available for the drools onboarding book
3
Overview
Overview
Overview
Software programmers are used to a procedural approach when it comes to implement Business
requirements. The consequence is that the business rule implementation solely depends on the
competence and understanding the software developer has of the Business Rules he has to implement.
This limitation was already seen and identified by researches. Object oriented programming may be
seen as "the solution" to business implementation and agility and many developers rely on this
paradigm. At the end, Object oriented approach ends up with the classical "Spaghetti code". To avoid
this ending, a new approach was taken called "declarative programming". This is a big shift and we
shall try to focus on that before learning the tooling around drools.
the first set of tutorials called "drools tutorials" start from the base concepts (there are few and
is concentrated on the the core engine) up to more language concepts
the second set of tutorials called "BRMS tutorial" will introduce the the management tooling
(called workbench) around the lifecycle of the rule artifact. but the workbench also introduces
more artifacts type like decision table, rule templates, etc.. that will help when modeling
business requirements.
the third set of tutorials called "BRMS runtime tutorials" start to introduce possible software
architectures in a real project. In the examples parts, we will use ideas that we describe in that
part.
4
Drools tutorial
Drools tutorial
When working with drools, there are things you have to define :
1) The data model on which the rules applies. As we are working in the java language, a data model is
a set of java classes.
2) Rules which are going on one side (called left side or LHS) express constraints on the data model,
which here class name and their attributes and on the other side (called right side or RHS) which will
act on the facts which are in he working memory.
When you want to apply some rules on some data, you will instantiate a java class and give it to the
rule engine. This instance is called a Fact object.
To work with the rule engine, we have to instantiate a KieContainer. We will see later how to program
it. This kieContainer contains a set of rules. The KieContainer allows also to contain other types of
artifacts are is common to other components like jbpm and optoplanner.
When you want to work with drools, you have to get a KieSession from the KieContainer. This
KieSession will allow you to give facts to the rule engine and to ask to fire rules.
5
Installing Drools Tooling
6
Installing Drools Tooling
7
Installing Drools Tooling
8
Installing Drools Tooling
Enter "FirstProject" as a project name and keep only the "Add a sample Helloworld rule file to this
project". the generated project should look like that:
9
Installing Drools Tooling
If you do with the right mouse on DroolsTest class and run as "java Program", the following should
be displayed on the console view
10
Data Model used in the tutorial
11
Data Model used in the tutorial
and we are going to create 3 java classes : Account, AccountingPeriod and CashFlow by right-
clicking on the new package just created and new Class
12
Data Model used in the tutorial
And the Account class, add two attributes accountno and balance. Right click source/generate
getter/setter and the Account class will have getter/setter.
13
Data Model used in the tutorial
14
Data Model used in the tutorial
15
Data Model used in the tutorial
Click on the Libraries tab and select the "Add library" button.
16
Data Model used in the tutorial
17
Data Model used in the tutorial
18
Data Model used in the tutorial
19
Data Model used in the tutorial
We now have to create some directory. Select the src directory and right click button new Directory.
20
Data Model used in the tutorial
21
Data Model used in the tutorial
Do the same with src/test/rules now the project should look like this :
22
Data Model used in the tutorial
23
Data Model used in the tutorial
24
Data Model used in the tutorial
Push the next Button. In the next screen, enter droolscours as package name and FirstTry as Name
25
Data Model used in the tutorial
26
Data Model used in the tutorial
Select
the open class, Right click and run as JUnit Test :
And the Junit Window should appear as above. (of course no rules were fired).
27
Data Model used in the tutorial
28
Lesson 1 : Core concepts
29
Lesson 1 : Core concepts
Enter a rule name and package and press the Finish Button.
30
Lesson 1 : Core concepts
1. For every java object we are going to use, we need to import classes
2. It is possible to define global variables
3. Unique rule name
4. Rule conditions sometimes called LHS=Left Hand Side as it is on the left side of the RETE
algorithm which is included in drools
5. Rule action that is triggered when the rule conditions are met. It's possible to use pure java
code, this is even known as Right Hand Side (RHS).
31
Lesson 1 : Core concepts
We create a rule the has a condition just a fact of type Account. If the rule is fired, then we shall show
the message "The account exists" in the console. Notice that the then part is just pure java.
32
Lesson 1 : Core concepts
33
Lesson 1 : Core concepts
It is the message that we have put in the rule "Your first rule"
variable is called showResults. This variable can now be used in the them part of the rule as here. To
initialize the global variable, we shall use the method setGlobal on the session we create as shown
here in our test :
When running the junit test, the console should look like this :
36
Lesson 1 : Core concepts
The production memory contains all the rule definition (in our case the drl for the moment). The
working memory which created with the session and we can add facts to it with the method insert.
The agenda which contains all the rules that can be fired. The pattern Matcher which is the algorithm
that is used to match the rules on the facts given. In drools latest version, there are many different
algorithm that are used (The main one is the rete algorithm).
We shall add a toString method to all our pojo classes Account, AccountingPeriod and CashFlow. To
do so we shall let eclipse generate it for us by right clicking in the source code
37
Lesson 1 : Core concepts
38
Lesson 1 : Core concepts
39
Lesson 1 : Core concepts
Then you should add the following unit test to the TestLesson1 java class
And in the
console you should see this :
40
Lesson 1 : Core concepts
The
first line is generated by the first test. To be able to see the difference when a new test is started, we
can add the following code to our JUnit test case :
41
Lesson 1 : Core concepts
The first test is passed and we see the output generated when the rule is fired. The second test first
inserts an objet, then updates it the retract it. To update an object, you first have to memorize the fact
handle :
and then you have to use that facthandle to tell drools the object was updated :
a.setBalance(12.0);
sessionStatefull.update(handlea, a);
and the same applies when you want to retract (now called delete in drools 6) :
sessionStatefull.delete(handlea);
as we call fireAllRules() after we retract the only fact that was in the working memory, the rule "Your
First Rule revisited" is not fired.
We insert an Account, call FireAllRules and then call a second time fireAllRules on the same session.
What shall happen ? How many times the rule "Your First Rule revisited" shall be fired ?
42
Lesson 1 : Core concepts
The rule
is fired only once. May be it is because we did not modify the Account object ? Let us do another
example that modifies the account object we pass to the the session.
The rule is still not fired a second time. Just modifying the object does not do the job.
Let us modify the example like this by telling the rule engine we modified the fact :
Before calling the second fireAllRules, we tell drools that the fact we inserted before was updated. In
our case, we did not modify its data. Here is the result :
43
Lesson 1 : Core concepts
time.
Here is what is happening when the FireAllRules method is called on a statefull session :
drools will look at all rules that can apply and put it in its agenda.
drools will execute the rule that is on top of its agenda
Once fired, the rule will be deactivated
We have to tell drools of a state change in one of facts in the when part (lhs) to make him
reconsidering the rule.
A state change can be an insert, update or delete (retract).
In the last example, we tell drools that a fact has been updated
sessionStatefull.update(handle, a);
So therefore, considering the previously inserted fact has been updated, drools reconsiders the rule.
As in the rule "Your First Rule revisited" there are no condition on the attributes, the rule is then fired.
But we can also do that in the then (RHS) part of a rule : insert, update, retract.
44
Lesson 1 : Core concepts
in
the first rule, in the then part we create a new instance of time AccountingPeriod and we use the
keyword insert to tell drools to create a new fact. As a concequence, the second rule will be executed
as the only condition is there is an AccountingPeriod in the working memory.
We see in
the logs
two first line : an object of type CashFlow was inserted. We did that from the Junit test with the
code FactHandle handlea = sessionStatefull.insert(a);
the third line is generated in the then part of the rule "Your First Rule revisited
AccountingPeriod".
The fourth and fifth line : an object of type AccountingPeriod was inserted. This was done in
the then part of the rule "Your First Rule revisited AccountingPeriod"
the last line is coming from the then part of the rule "Rule on AccountingPeriod that are
inserting". Meaning the insered object AccountingPeriod we inserted in the previous rule
triggered the second rule.
Summary
This ends the first lesson where we learned the core concepts needed when working with drools :
1. What is a rule
2. A rule with a simple condition
3. How to log what is happening in the rule engine
4. What triggers a rule execution and how to interact with the rule engine for fact handling.
45
Lesson 1 : Core concepts
46
Lesson 2 : binding
Lesson 2 : binding
Relating facts and attributes to each other in a
rule
Adding callback initialization and more
To be able to see what is happening in the rule engine, we shall add to the KnowledgeSessionHelper
this method
47
Lesson 2 : binding
import java.text.DateFormat;
@Override
public String toString() {
// TODO Auto-generated method stub
StringBuffer buff = new StringBuffer();
buff.append("-----CashFlow-----)\n");
buff.append("Account no=" + this.accountNo + "\n");
if (this.mvtDate != null) {
buff.append("Mouvement Date= "
+ DateFormat.getDateInstance().format(this.mvtDate)
+ "\n");
} else {
buff.append("No Mouvement date was set\n");
}
buff.append("Mouvement Amount=" + this.amount + "\n");
buff.append("-----CashFlow end--)");
return buff.toString();
}
in the util package, we shall create a DateHelper class that will look like this :
package util;
import java.text.SimpleDateFormat;
import java.util.Date;
in the src/test/rules, create a package lesson2 and a rule resource named lesson2.drl and should look
like this :
package droolscours
//list any import classes here.
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.Account;
import util.OutputDisplay;
global OutputDisplay showResults;
when
Account( )
then
showResults.showText("The account exists");
end
package droolscours;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kie.api.event.rule.ObjectDeletedEvent;
import org.kie.api.event.rule.ObjectInsertedEvent;
import org.kie.api.event.rule.ObjectUpdatedEvent;
import org.kie.api.event.rule.RuleRuntimeEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
49
Lesson 2 : binding
import org.kie.api.runtime.rule.FactHandle;
import util.KnowledgeSessionHelper;
@SuppressWarnings("restriction")
public class TestLesson2 {
static KieContainer kieContainer;
StatelessKieSession sessionStateless = null;
KieSession sessionStatefull = null;
@BeforeClass
public static void beforeClass(){
kieContainer=KnowledgeSessionHelper.createRuleBase();
}
@Before
public void setUp() throws Exception{
System.out.println("------------Before------------");
}
@After
public void tearDown() throws Exception{
System.out.println("------------After------------");
}
@Test
public void testdeuxFait1() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksessio
To see if it runs, select the TestLesson2 class, right click and run as Junit Test and the console should
look like this :
So now
50
Lesson 2 : binding
Test Case
We are going to implement a test case with the following data : 1) Account with accountno=1 2) an
Accounting period going from January first 2016 to march 31th 2016 3) 3 Cash Flow movements,
credit 1000$ January 15th 2016, debit 500$ February 15th 2016 and a credit movement April 15th
2016 of 1000$.
Fact binding
We want to update the account balance for each CashFlow. We first put the CashFlow and select all
CashFlow of type CREDIT. To do so, we add a constraint on the type attribute of java class
package droolscours
//list any import classes here.
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.Account;
import util.OutputDisplay;
when
$cash :CashFlow(type == CashFlow.CREDIT )
$acc : Account( )
then
$acc.setBalance($acc.getBalance()+$cash.getAmount());
showResults.showText("Account no "+$acc.getAccountNo()+ " has now a
end
In front of the fact, we declare variables $cash and $acc like shown above and then those variables
can be used in the then part as normal java variables. As shown above we can then update the balance.
51
Lesson 2 : binding
package droolscours;
import util.OutputDisplay;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.StatelessKieSession;
import org.junit.Assert;
import util.DateHelper;
import util.KnowledgeSessionHelper;
@SuppressWarnings("restriction")
public class TestLesson2 {
static KieContainer kieContainer;
StatelessKieSession sessionStateless = null;
KieSession sessionStatefull = null;
@BeforeClass
public static void beforeClass(){
kieContainer=KnowledgeSessionHelper.createRuleBase();
}
@Before
public void setUp() throws Exception{
System.out.println("------------Before------------");
}
@After
public void tearDown() throws Exception{
System.out.println("------------After------------");
}
@Test
public void testTwoFacts() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"kse
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlow cash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
sessionStatefull.fireAllRules();
Assert.assertEquals(a.getBalance(), 1000,0);
52
Lesson 2 : binding
}
}
In the TestTwoFacts test we insert an object of type Account and CashFlow mouvement of type
credit. At the end, the balance should be 1000$. the console should look like this when running the
test :
Attribute binding
Let us make now an example with a second CashFlow movement. Here is the test case :
@Test
public void testTwofactsTwocashFlowMovement() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer,"ksessio
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlow cash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setMvtDate(DateHelper.getDate("2010-01-15"));
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
CashFlow cash2 = new CashFlow();
cash2.setAccountNo(2);
cash2.setAmount(1000);
cash2.setMvtDate(DateHelper.getDate("2010-01-15"));
cash2.setType(CashFlow.CREDIT);
53
Lesson 2 : binding
sessionStatefull.insert(cash2);
sessionStatefull.fireAllRules();
Assert.assertEquals(a.getBalance(), 1000,0);
}
and in the console, we see that the rule "Credit rule" is running twice :
package droolscours
//list any import classes here.
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.Account;
import util.OutputDisplay;
54
Lesson 2 : binding
The rule above uses a binding variable. We create an attribute variable called $accno on the attribute
accountNo. We can define now a binding on the attribute accountNo of fact Account.
Now the
rule "Credit Rule" is only fired once and the balance is corret.
Calculating balance
Now we know how to link facts and use attribute variable via binding attributes to use them as
constraint, we shall modify the credit rule and create a debit rule :
package cours
import droolscours.Account;
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import droolscours.util.OutputDisplay;
when
$cash :CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlo
$acc : Account(accountNo ==$no )
$period : AccountingPeriod( startDate <= $aDate && endDate >= $aDa
then
$acc.setBalance($acc.getBalance()+$cash.getAmount());
showResults.showText("Account no "+$acc.getAccountNo()+ " has now a
end
55
Lesson 2 : binding
when
$cash :CashFlow( $aDate : mvtDate, $no : accountNo ,type == CashFlow.D
$acc : Account(accountNo ==$no )
$period : AccountingPeriod( startDate <= $aDate && endDate >= $aDate)
then
$acc.setBalance($acc.getBalance()-$cash.getAmount());
showResults.showText("Account no "+$acc.getAccountNo()
+ " has now a balance of "+$acc.getBalance());
end
In the rule above, we add a constraint so that the mvtDate of the CashFlow is between the startDate
and endDate of the AccountinPeriod.
@Test
public void testcalculateBalance() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResults", display);
Account a = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlow cash1 = new CashFlow();
cash1.setAccountNo(1);
cash1.setAmount(1000);
cash1.setMvtDate(DateHelper.getDate("2016-01-15"));
cash1.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash1);
CashFlow cash2 = new CashFlow();
cash2.setAccountNo(1);
cash2.setAmount(500);
cash2.setMvtDate(DateHelper.getDate("2016-02-15"));
cash2.setType(CashFlow.DEBIT);
sessionStatefull.insert(cash2);
CashFlow cash3 = new CashFlow();
cash3.setAccountNo(1);
cash3.setAmount(1000);
cash3.setMvtDate(DateHelper.getDate("2016-04-15"));
cash3.setType(CashFlow.CREDIT);
sessionStatefull.insert(cash3);
AccountingPeriod period = new AccountingPeriod();
period.setStartDate(DateHelper.getDate("2016-01-01"));
period.setEndDate(DateHelper.getDate("2016-03-31"));
sessionStatefull.insert(period);
sessionStatefull.fireAllRules();
Assert.assertTrue(a.getBalance()==500);
}
56
Lesson 2 : binding
Summary
In lesson 1, we learned the dynamic of the rule engine : how and when are the rules fired. In the
current lesson, we started to link together conditions between facts and how to interact with the facts
in the rule execution. In the next lesson, we will see how to express more complex constraints.
57
lesson 3 : Some more drools languages
While building the examples, you will see more rules fired than the shown examples. As drools is a
declarative language, as soon as the constraint are satisfied, the rule can fire.
package droolscours;
public Customer() {
super();
// TODO Auto-generated constructor stub
}
return name;
}
@Override
public String toString() {
StringBuffer buff = new StringBuffer();
buff.append("-----Customer-----)\n");
buff.append("Name=" + this.name + "\n");
buff.append("Surname Name=" + this.surname + "\n");
buff.append("Country=" + this.country + "\n");
buff.append("-----Customer end-)");
return buff.toString();
}
package droolscours;
@Override
public String toString() {
StringBuffer buff = new StringBuffer();
buff.append("-----Private Account-)");
buff.append(super.toString());
if (this.owner != null) {
buff.append(this.owner.toString());
}
buff.append("-----Private Account end-)");
return buff.toString();
}
}
59
lesson 3 : Some more drools languages
In Constraint
This allows to validate an attribute is a list of values
package cours
when
$cash :CashFlow(type in ( CashFlow.DEBIT,CashFlow.CREDIT) )
then
showResult.showText("The cashFlow is a credit or a debit");
end
@Test
public void testInConstrait() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
CashFlow cashFlow = new CashFlow();
cashFlow.setType(CashFlow.CREDIT);
sessionStatefull.insert(cashFlow);
sessionStatefull.fireAllRules();
} }
Nested Accessor
This allows to add a constraint to a attribute class without the need to add the linked object to the
session.
60
lesson 3 : Some more drools languages
rule "Accessor"
when
$cash :PrivateAccount( owner.name =="Hron" )
then
showResult.showText("Account is owned by Hron");
end
@Test
public void testNestedAccessor() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Customer customer = new Customer();
customer.setName("Hron");
customer.setSurname("Nicolas");
PrivateAccount pAccount = new PrivateAccount();
pAccount.setOwner(customer);
sessionStatefull.insert(pAccount);
sessionStatefull.fireAllRules();
}
As seen here, we do not add the customer instance to the drools session.
The rule
has been fired.
And/or
It is possible to do constraints on attribute like in java.
rule "infixAnd"
when
( $c1 : Customer ( country=="GB") and PrivateAccount( owner==$c1))
or
( $c1 : Customer (country=="US") and PrivateAccount( owner==$c1))
then
showResult.showText("Person lives in GB or US");
end
@Test
public void testInOrFact() throws Exception {
61
lesson 3 : Some more drools languages
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Customer customer = new Customer();
customer.setCountry("GB");
sessionStatefull.insert(customer);
PrivateAccount pAccount = new PrivateAccount();
pAccount.setOwner(customer);
sessionStatefull.insert(pAccount);
sessionStatefull.fireAllRules();
}
not
This allows to test if no fact of a type is in the session.
@Test
public void testNotCondition() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
sessionStatefull.fireAllRules();
}
62
lesson 3 : Some more drools languages
exist
On the contrary of previous syntax, this allows to test if there at least one fact type is in the session.
rule "Exists"
when
exists Account( )
then
showResult.showText("Account exists");
end
@Test
public void testExistsCondition() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account pAccount = new Account();
sessionStatefull.insert(pAccount);
Customer c = new Customer();
sessionStatefull.insert(c);
sessionStatefull.fireAllRules();
}
ForAll
We would like to verify that every cashflow instance is linked to an Account instance.
63
lesson 3 : Some more drools languages
rule "ForAll"
when
forall ( Account( $no : accountNo )
CashFlow( accountNo == $no)
)
then
showResult.showText("All cashflows are related to an Account ");
end
In this rule, in the forall condition, we link the CashFLow instance to the Account instance. We are
goint to do a test case where all objects are related
@Test
public void testForALl() throws Exception {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionWithCallback(kieContainer, "ksessi
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
CashFlow cash1 = new CashFlow();
cash1.setAccountNo(1);
sessionStatefull.insert(cash1);
CashFlow cash2 = new CashFlow();
cash2.setAccountNo(1);
sessionStatefull.insert(cash2);
Account a2 = new Account();
a2.setAccountNo(2);
a2.setBalance(0);
sessionStatefull.insert(a2);
CashFlow cash3 = new CashFlow();
cash3.setAccountNo(2);
sessionStatefull.insert(cash3);
sessionStatefull.fireAllRules();
}
When running the test, you should see the following logging.
sessionStatefull.insert(cash2);
Account a2 = new Account();
a2.setAccountNo(2);
a2.setBalance(0);
sessionStatefull.insert(a2);
64
lesson 3 : Some more drools languages
When you run the test case, the rule ForAll will not be fired.
From
It is sometimes needed to access data from outside the drools session. As it is not possible to insert all
objects in the session, we can use the from instruction in the when part.
package droolscours.service;
import droolscours.Customer;
import java.util.ArrayList;
import java.util.List;
rule "FromCondition"
when
$c : Customer()
$cc : Customer(name ==$c.name,surname==$c.surname,country !=$c.country
then
showResult.showText("Found same customer in 2 countries");
end
@Test
public void testFromLHS() throws Exception {
sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionW
"ksession-lesson3");
65
lesson 3 : Some more drools languages
The rule is fired twice as in the service there are two customers with the same name and with a
different country.
Collecting
The purpose is to collect a set of fact and constraint if the constraints are true. Let us see the following
example int the rule "More then 2 CashFlow Line". in this rule, we want to collect all CashFlow that
are in the correct time period and the good account number. The "from collect" syntax returns an
arrayList. It is possible to add a condition as in the first rule where we add a constraint that we expect
at least 2 items. In the second rule, we do not add this constraint.
then
showResult.showText("Found more than 2 CashFlow Lines");
showResult.showText("<<<<<<<<<<");
for (Object ff : $number){
showResult.showText(ff.toString());
}
showResult.showText(">>>>>>>>>>>>>>>>");
end
then
showResult.showText("Found "+$number+" more than 2 CashFlow Lines");
end
66
lesson 3 : Some more drools languages
You may need to add constructors in the CashFlow and AccountingPeriod classes :
public AccountingPeriod() {
}
public CashFlow() {
super();
}
public CashFlow(Date mvtDate, double amount, int type, long accountNo) {
super();
this.mvtDate = mvtDate;
this.amount = amount;
this.type = type;
this.accountNo = accountNo;
}
@Test
public void testCollecting() throws Exception {
sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionW
"lesson34-session");
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a = new Account();
a.setAccountNo(1);
a.setBalance(0);
sessionStatefull.insert(a);
sessionStatefull.insert(new CashFlow(DateHelper.getDate("2010-01-15"),
sessionStatefull.insert(new CashFlow(DateHelper.getDate("2010-02-15"),
sessionStatefull.insert(new CashFlow(DateHelper.getDate("2010-04-15"),
sessionStatefull
.insert(new AccountingPeriod(DateHelper.getDate("2010-01-01"),
sessionStatefull.fireAllRules();
}
67
lesson 3 : Some more drools languages
Accumulating
In the previous section, we collect data. There is an "from accumulate" that allows us to sum data in
one command. the "from collect" instruction takes 5 parameters : 1) a fact constraint expression 2) an
init condition 3) the instruction when the rule applies to the fact constraint expression 4) the reverse
action when the fact constraint expression is not true anymore 5) The result of the accumulate
then
showResult.showText(" Found "+$totalCredit+" as a credit");
showResult.showText(" Found "+$totalDebit+" as a debit");
end
The constraint here is on a fact type CashFlow with the constraints that we already used before (good
account number and the good date period and it should be a credit or a debit) Then the initial
condition, we initialize a double value we call total. Then in the action/reverse, we add to the total the
amount in the CashFlow that we get by using an attribute binding. In the result action we put the total
we calculated.
@Test
public void testAccumulate() throws Exception {
sessionStatefull = KnowledgeSessionHelper.getStatefulKnowledgeSessionW
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
sessionStatefull.insert(new Account(1,0));
Summary
This lesson was an introduction to the main drools language syntax that are needed for starting a
drools project. In the next lesson, we will start learning the ruleflow concept that we encourage to use
in drools projects.
69
lesson 4 : ruleflow
lesson 4 : ruleflow
Organizing rule execution for bigger projects
Why do we need a Ruleflow ?
When capturing business requirements, most users express the rules by dividing the problem to
resolve in steps. As this, it is very convenient to be able to implement it the same way. In the
drools/jbpm technology, we are going to use a jbpm process by using rule steps, it is then called a rule
flow. But in reality, we can mix jbpm/drools together.
70
lesson 4 : ruleflow
Then select each of the Rule set and set the properties as follows :
Select the workflow in the rear, and in the properties file, change as follows :
71
lesson 4 : ruleflow
package cours
import droolscours.Account;
import droolscours.AccountingPeriod;
import droolscours.CashFlow;
import util.OutputDisplay;
Look at the keyword "ruleflow-group". Here the first rule we give it the name "Group1" and the
second "Group2". they have the same name as the Rule-flow items we defined in the process
definition above. Therefor, the first rule can only be fired when the rule-flow group "Group1" is
activated and the same for the second rule and rule-flow group "Group2". Before running a test case,
we will add a new callback to know the activities around the jbpm process.
@Override
public void beforeVariableChanged(ProcessVariableChangedEvent ar
// TODO Auto-generated method stub
72
lesson 4 : ruleflow
@Override
public void beforeProcessStarted(ProcessStartedEvent arg0) {
System.out.println("Process Name "+arg0.getProcessInstance()
@Override
public void beforeProcessCompleted(ProcessCompletedEvent arg0) {
// TODO Auto-generated method stub
@Override
public void beforeNodeTriggered(ProcessNodeTriggeredEvent arg0)
// TODO Auto-generated method stub
@Override
public void beforeNodeLeft(ProcessNodeLeftEvent arg0) {
if (arg0.getNodeInstance() instanceof RuleSetNodeInstance){
System.out.println("Node Name "+ arg0.getNodeInstance().
}
@Override
public void afterVariableChanged(ProcessVariableChangedEvent arg
// TODO Auto-generated method stub
@Override
public void afterProcessStarted(ProcessStartedEvent arg0) {
@Override
public void afterProcessCompleted(ProcessCompletedEvent arg0) {
System.out.println("Process Name "+arg0.getProcessInstance()
@Override
public void afterNodeTriggered(ProcessNodeTriggeredEvent arg0) {
if (arg0.getNodeInstance() instanceof RuleSetNodeInstance){
System.out.println("Node Name "+ arg0.getNodeInstance().
}
73
lesson 4 : ruleflow
@Override
public void afterNodeLeft(ProcessNodeLeftEvent arg0) {
}
});
return session;
}
Note that we are only looking for Node of type Rule Step called RuleSetNodeInstance. And the test
case looks like this :
package droolscours;
import util.OutputDisplay;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import util.KnowledgeSessionHelper;
@SuppressWarnings("restriction")
public class TestLesson4 {
static KieContainer kieContainer;
KieSession sessionStatefull = null;
@BeforeClass
public static void beforeClass() {
kieContainer = KnowledgeSessionHelper.createRuleBase();
}
@Before
public void setUp() throws Exception {
System.out.println("------------Before------------");
}
@After
public void tearDown() throws Exception {
System.out.println("------------After ------------");
}
@Test
public void testRuleFlow1() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionForJBPM(kieContainer, "ksession-le
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a = new Account();
sessionStatefull.insert(a);
sessionStatefull.startProcess("RF1");
sessionStatefull.fireAllRules();
}
}
74
lesson 4 : ruleflow
Before calling the fireAllRules method, we call a startProcess method with the "RF1" parameter
which is the ID we gave to the process above.
A rule flow group works like a separate group of rules. Those who are setting the focus when the rule
step is called with the same node id as the ruleflow-group. When no more rules can be fired, the
process can continue to the next node.
We can go further
@Test
public void testRuleFlow2() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSessionForJBPM(kieContainer, "ksession-le
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a = new Account();
sessionStatefull.insert(a);
sessionStatefull.fireAllRules();
}
75
lesson 4 : ruleflow
Create a new package in src/test/rule and calle it lesson4a. Create a new process file that you can call
demo-ruleflow2.bpmn2 and a rule file demo-ruleflow2.drl.
The bpmn process should look like this and give it the id "RF3":
The left split should be a "diverge Gateway" and the right one a "converge Gateway". The calculate1
should have a ruleflow called "group1" and the calculate2 "group2".
When clicking on the "diverge gateway", you should select the "OR" type and for the the "converge
Gateway" the "XOR".
76
lesson 4 : ruleflow
Now we have to edit each connection Here is for "to Node Calculate1". Do not forget to click the
"Imports" button to add the Account class.
77
lesson 4 : ruleflow
package cours
end
rule "Account group2"
ruleflow-group "Group2"
when
78
lesson 4 : ruleflow
Account( )
then
showResult.showText("Account in Group2 < 1000");
end
@Test
public void testRuleFlow3() {
sessionStatefull = KnowledgeSessionHelper
.getStatefulKnowledgeSession(kieContainer, "ksession-lesson4a"
OutputDisplay display = new OutputDisplay();
sessionStatefull.setGlobal("showResult", display);
Account a = new Account();
a.setBalance(2500);
sessionStatefull.insert(a);
AccountingPeriod period = new AccountingPeriod();
sessionStatefull.insert(period);
sessionStatefull.fireAllRules();
79
lesson 5 : Exercise
lesson 5 : Exercise
Cost transport calculator
The purpose of the exercise is to go through all steps of a real project when using a rule engine like
drools. The use case is simple enough to be realize withing one or two working days. We first expose
the business requirements like they may be expressed by users. Then we are going to design the
implementation we shall use. Feel free to modify the implementation if you think it is not how you
would have done. The only point of view you should keep is to use declarative programming versus
procedural code. It is very common for new comers to write a few rules and implement huge then part
of rules. It works. But you should remember that the implemented algorithms that are behind drools
will work best if you express a lot a pattern expressions (constraints) on java facts and if you insert
new fact that are the result of a rule. For example, in a loyalty system in retail industry, if a customer
is comming more than twice per month on the web site or in the shop, than he is a gold customer. this
is a fact that can be used in other rules as input. This is how the rule engine was thought to be used
and when you see business requirements it is how it is expressed naturally.
80
Requirements
Requirements
Requirements
We are working for a retail company that buys its products from different places in Asian mostly. each
shop can go to the buying web site and say what he wants and put an order.
Up to now, the transport cost was a estimated but not calculated on the content of the order.
The purpose is to implement such a calculator.
Data model
A customer puts an order that contains products. An order contains a lot of products with a number.
A product has
a name
a height,
a width,
a depth,
transport type : if the product can be put with other products in a pallet, individual(alone) or
bulk (like sand for example)
a weight
A product can be put on a pallet. a pallet 120 cm width and and 80 cm depth. It can be maximum 2
meters height and the weight should not exceed 1400 kg. We should use a simple algorithm to fill
each pallet. It will be not optimized but we should used that as a margin of the costs. a product that is
bigger than 60 cm in width or depth or higher than 1m should be put alone in a pallet.
All products start from the same city and go to the same city in an order. A trip is composed f steps.
Each step can be done by train, boat or truck.
81
Requirements
Transport Cost
Boat 0,2\/km
Train 0,5\/km
Truck 1\/km
Taxes
City Cost
Shangai 0,02\/kg
Rotterdam 0,05\/kg and 1 per handling person
Tournai 2 per handling person
Lille 30 per handling person
handling
City Cost
Shangai 20\/hour and a person can handle 13 pallets\/hour
Rotterdam 45\/hour and a person can handle 60 pallets\/hour
Tournai 67\/hour and a person can handle 40 pallets\/hour
Lille 79\/hour and a person can handle 30 pallets\/hour
The handling should not take more than 12 hours per city.
82
BRMS tutorial
BRMS tutorial
BRMS Tutorial
In the previous part, we learned the basic of drools concepts. We did that by using a java developer
tooling eclipse. We can not expect a Business User to use eclipse as a User interface to implement
rules. Since version 5 of drools, there is a dedicated User interface for that was called Guvnor in all
versions 5.X, called kie Workbench in versions 6.x till 6.3 and is is now called Business central
starting with version 6.4. Historically, Guvnor is a BRMS=Business Rule Management System. It
allowed to handle all lifecyle of a rule :
All was stored in a CMS (Content Management System) Component from the apache fundation called
Jackrabbit. The application Guvnor itself was a monolithic application which features was only
extensible by calling its rest API. The user interface was developed using the Google Web Toolkit
(GWT) from google to develop the application in java and generate the javascript to run as a native
javascript application on the browser. All jbpm components were separated application like jbpm-
console.
A new framework based on GWT but with features that helps to build a Modern business
application on HTML5 : Errai
a new framework was defined to define plugins to add new features : Uberfire
Use of standard build system widely used in the java ecosystem : Apache Maven
Use of a file base repository versus the CMS used before : git We will explain all this in next
part.
There are now two flavors of business central : the BRMS (Business Rule Management System) and
the BPMS (Business Process Management System).
The BPMS contains the BRMS with all jbpm specific components :
The drools core part itself now implements a new algorithm : PHREAK algorith (see 5.4 part of
documentation).
Before starting the tutorial, we shall go through a few concepts that will help to understand how to
use and integrate the BRMS in a real project.
As shown in the next picture, the steps when using version 5 were the following :
The java developer produces the pojo model (working with the business analyst). You could in
guvnor define a pojo model but with simple attributes. Most of the time, this feature was used
for temporary data produces by rules and consumes by others. Therefor, no java pojo model
was needed for that.
The java archive (jar) shall be uploaded to the Guvnor (BRMS) application. On this pojo mode,
the business analyst can write rules.
The java developer produces the final application that contains the drools runtime and deploys
it with the pojo model inside.
Now the application and Guvnor must have a synchronized version of the pojo model. There a few
other points that should be taken care :
when upgrading a pojo model version, the two parts must be synchronized.
It is not possible to work in parallel. There are workarounds like duplicating the package in
guvnor, etc..
As modern java development is using a maven approach in dependency and configuration
management, using Guvnor 5.x forces to have a specific build and deploy approach for it.
Guvnor is a nice tool very useful where most user interface about writing rules was kept in the
Business Central (enhanced of course) but all the wrapping was redesigned.
1. The BRMS can retrieve maven artifact from its local repository as well as from remote maven
repositories.
2. The BRMS can act as a remote Maven repository and can be access from external maven
builds.
84
BRMS tutorial
1. The java developer makes the pojo/entity model and pushes the code commits on the SCM
repository (like a git repository). There is here an alternative where this can be done in Business
Central. In this case, the maven build that concerns the final application will retrieve the
pojo/entity model from the business Central repository.
2. A maven build is then started (in jenkins for example) and the pojo model is deployed on the
maven repository. The maven artifact has a groupid, an artifactid and a version.
3. The business Analyst creates a new project on the Business Central application, and in the
dependency list user interface, he just enters the groupid, artifactid and the version the java
developer gave him for the pojo/entity model. Maven "magic" now will come in place as
Business Central will automatically retrieves from all remote maven repositories that were
defined to him the pojo/entity model artifact as well as all its dependencies.
4. When building the final application, the rule package is retrieve by its groupid, artifactid and
version. Indeed, when creating a project in Business Central, you have to give it those element.
In the dependency file of the application (pom.xml), just add those identification elements as
well as the url of the business central maven repository, and it works. The maven build of the
application will retrieve the good version of the rule package.
In Guvnor 5.X, if a pojo model had dependencies, you had to upload them one by one with the good
version. It could lead to errors and when an update was needed in the dependencies, you had to
upload them one by one. Someone may ask : why is there a need for handling dependencies ? Just
make a java entity model with no dependencies. This is true and when using guvnor 5.x, we did like
this as good practice because of the limit Guvnor had. But in modern application, the entity model is
stored in databases using JPA or Hibernate annotations (or other framework when using nosql
databases for example). Now with the maven dependency and configuration handled by business
central, it is possible to use this entity model with no need to duplicate the model and then do
85
BRMS tutorial
mapping. It is no more needed. Also, in Guvnor 5.x, we had to build package versions (called
snapshot) and then somehow reference that name in the application to retrieve at runtime the good
package version. We can now do both even if we only show the example the deployment of the rule
package at build time of the application.
The case presented here is one use case. But using other parts of the tooling like the kie server may go
to other architecture. We will present later other scenarios.
There is no mystery in this feature. It is just a way to have a good dependency and configuration
management in the business Central. In the past, we had to handle all that manually with possible
human errors. The process is now automated and complies to an enterprise standard Apache Maven.
Another advantage of using maven build is that the Drools community will not need to maintain a
specific build process and concentrate on other feat
All this should be setup by IT and is no concern of the business analyst except the version of the rule
package to use in development , integration or production environments.
Guvnor 5.x was base on a Content Management System (CMS) library Apache Jackrabbit.
To be able to communicate with the repository, a webdav interface was provided. This remote
interface was very near to subversion approach. it was also possible to access the content of a guvnor
project through its eclipse plugin.
This approach works very well when documents are handled. When it comes to source code, there is a
need of more complex content :
Indeed, when big companies were using guvnor, more than one instance of guvnor were used (one per
department for example). There was a need to be able to centralize all the business rules knowledge
and to allow to many department/organization to access it. A "Organizational Unit" concept was
created in the 6.x version which allow to link one or more repository.
As drools is an open source project and uses itself git as a source code management repository, git
was chosen to store the content of the new Guvnor version. In version 5.x, the storage was only
readable by the CMS library. Now the low level storage can be directly read with a normal file
explorer. There is no more need of Eclipse Plugin to access the rule project. In version 5.x all this
plombing around Developer tooling took a lot of time to the drools community. With this new tooling
choice, all this exists by default and the community can concentrate on other features.
As the new Guvnor version allows to store all elements of a company, it was called Business Central.
Version 6 tooling
86
BRMS tutorial
As seen in the previous part, the drools community redesigned completely the BRMS tooling :
A new build system of the rules to make them usabale in an application (maven)
A new repository content manager (git) to make it easier to integrate with java development
tooling and minimize development needs for that by using software industry standard
Business Central concept
New Rule design pattern
An open architecture to add new features with the plugin architecture
An execution server called kie server that simplifies the deployment of rule packages and is
totally integrated in Business Central.
In previous tutorial, we have learned how to write rules using the Drools Rule Language (DRL)
We cannot expect a Business User to write rules using DRL. So Business Central offers editors that
will simplify writing rules. We are going to quickly present some of them.
Guided Rule
This editor allows to build a rule just by clicking and it will guide the user through all the syntax.
87
BRMS tutorial
88
BRMS tutorial
TODO
Test scenario
89
BRMS tutorial
90
Organizational Unit And repository
91
Organizational Unit And repository
And the click on the +Add Button in the middle and the following screen should be displayed. Enter
the data as displayed here and click on the OK button.
92
Organizational Unit And repository
We Shall give him a name a select the "Managed Repository" selector as shown below. We shall
create the repository for the Organizational Unit we created before.
After clicking the "Next button" the following screen will appear. Enter as shown here. We want it to
be a multi-project repository, we want to use 3 branches and give a default groupID and version. Then
click on the "Finish" button.
93
Organizational Unit And repository
94
Organizational Unit And repository
95
Data Model
Data Model
Data Model
In the previous step we create a Organization Unit and a repository nautic. We are now going to create
project called swimmingpool.
96
Data Model
Enter the data as shown above. The Project general settings view is then displayed.
We want to add a dependency on the pojo/entity java model. So we click as shown below on the
"dependencies" menu item.
97
Data Model
This is a
community project we shall speak later about. Then as in our runtime we configured all necessary
settings for maven, all is retrieved. The project we use is on maven central. The following screen is
then displayed.
98
Data Model
Note that in the 6.4.0 version there is a bug. If the workbench is restarted or you quit the editor
and re-open it, the list is then empty when you log again. But it is only a display problem as in
the repository the dependency is kept. the JIRA is here. It is corrected in version 6.5.0.
Now we have to say which java entity/classes we want to use in our rules. This is then done as
follows.
99
Data Model
100
Data Model
Click on the pom.xml file. In the dependency part of the file, you should see what we entered before.
101
Data Model
And in the file package-names-white-list the package we defined allowed to be used in the guided
editors.
102
Data Model
103
Business Requirements
Business Requirements
Business Requirements
A new web site has been developed to sell ticket for the city Olympic Swimming pool of Zurich. The
purpose is to build a web service by giving him the customer quote request and in response the
proposed quoting.
* an address,
* A list of person,
* a desired period.
As a response, we shall receive the same quote but filled with standard Price per person, the list of
reduction per person and the total price. Here are the price per age and desired period.
104
Business Requirements
11 18 spring 48
18 60 spring 60
60 spring 50
3 11 autumn 30
11 18 autumn 48
18 60 autumn 60
60 autumn 50
3 11 full Year 80
11 18 full Year 110
18 60 full Year 150
60 full Year 120
In a quote with a group of at least 4 people, the youngest person between 3 and 11 years old
years has a free ticket
if a person has his birtday the day the ticket is quoted, then a 10% applies to that person. This
applies only for a day ticket
105
Design
Design
Design
We are going to divide our rules in 5 steps and do a rule-flow which mean a process :
1. init step : we shall determine the age of each person and the person has his birthday based on
the quoting date.
2. standard price : as we have the table with all prices, we shall make a decision table of it.
3. Promotion : if there are more that 4 persons and the youngest is between 3 and 18 years old
4. Reduction : birthday and If people are living in Zurich
5. Calculate the total
106
Implementing the Process Flow
107
Implementing the Process Flow
Clock on the "<<" on the right part and the properties will appear. Enter the Name and Ruleflow
group name as follows :
108
Implementing the Process Flow
109
Implementation technical parts
Create functions
We will need some java functions to help us writing rules Go to new Items/DRL FIle and create a rule
called "function" and put in the rule content the following code :
import java.util.Calendar;
import java.util.Date;
110
Implementation technical parts
111
Implementation technical parts
112
Implementing the initial step
113
Implementing the initial step
114
Implementing the initial step
115
Implementing the initial step
116
Implementing the initial step
117
Implementing the initial step
Then you shall obtain the rule as follows. Notice that the stringValue of the calculatedAttribute as a
formula. So you should select the formula not a litteral. And also that we had to create a binding
varialble "bd" for attribute birthdate of call Person.
118
Implementing the initial step
Notice that we test there is not already a calculated attribute for that person with the same key
Notice that we have to add to the list of calculated attribute of the person and then tell the rule engine
the list was updated.
119
Implementing the initial step
120
Implementing the initial step
As the attribute is of type date, you can select a date with the date picker.
121
Implementing the initial step
Select
literal value.
And select a date as for the quote date but on same day (here June 30th?
122
Implementing the initial step
and Click on the "A fact of type... " Then chose the StringValue field
And as the rule we want to test is in ruleflow group init. Click on the cross near the "Given" cross and
enter "init" in the activate rule flow group part.
123
Implementing the initial step
Then click the "Run scenario" button twice and you should see the screeen as follows
124
Implementing the initial step
125
Implementing the initial step
126
Implementing standard price step
127
Implementing standard price step
128
Implementing standard price step
129
Implementing standard price step
130
Implementing standard price step
131
Implementing standard price step
132
Implementing standard price step
133
Implementing standard price step
134
Implementing standard price step
135
Implementing standard price step
136
Implementing standard price step
137
Implementing standard price step
138
Implementing standard price step
139
Implementing the Child over 3 years old is free promotion step
Select the List class. Click on the "There is a list.." and the click on the Expression Builder button
on the first "Choose" select the size() function and on the second "greater than"
140
Implementing the Child over 3 years old is free promotion step
Then click on the "All Person with" link an dselect the age attribute and add the following constraint.
And select the Number type from the add a pattern link.
141
Implementing the Child over 3 years old is free promotion step
142
Implementing the Child over 3 years old is free promotion step
Then we shall create a guided rule called StartProcessRule as follows. In the Then add free form drl
143
Implementing the Child over 3 years old is free promotion step
144
Implementing the Birthday promotion step
If the person has his Birthday on the quote day and a day ticket is asked, then a 10% reduction shall
be applied for the person.
145
Implementing the Birthday promotion step
Instead of ROUND_HALF_DOWN you can put ROUND_HALF_UP which will put higher reduction
amount.
146
Implementing the Birthday promotion step
147
Implementing the Zurich reduction step
148
Implementing the Zurich reduction step
Instead of ROUND_HALF_DOWN you can put ROUND_HALF_UP which will put higher reduction
amount.
149
Implementing the Zurich reduction step
150
Implementing the final step
In the rule above, we have to use custom code as when working with java Bigdecimal class (which we
shall use when working with financial amounts) the standard functions do not work.
151
Implementing the final step
In the second rule, we use the definitive price we create before. in the picture shown below, we can
see an example of the test server we shall present in the next tutorial
152
Implementing the final step
153
Implementing the final step
154
Conclusion
Conclusion
What we did up to now
In the first tutorial we have learned the core drools concepts that are needed to start implementing
business rules. The course example was simply there to demonstrate and help the user to understand
the concepts. The exercise then starts to show a more complex case where we have to separate in
steps to get the final result. In those two first examples on the drools tutorial, how to interface with a
real application was not in the scope of the exercise. In the BRMS tutorial, we took the same
approach on how to express the rules and how to test them. But it is never express how we should
interface our rule engine implementation with our real application. In the next tutorial, we shall
propose an architecture of a drools application.
155
BRMS Runtime tutorial
as the business central is a maven repository, rebuild the runtime (or application if the runtime
is embedded) with the new package version.
In the runtime dynamically add to the java classpath the new jar of the rules package each time
there is a new version.
Out of the box, the new drools tooling in version 6.4 offers us an authoring tool with a runtime ready
to work\/deploy a drools set of rules in a maven package.
Which is even better is that as well the authoring tool (kie-wb) or the execution server (kie-server) can
be extended. You can see that at the end of the book.
For now on, we shall use the standard tooling and interface available out of the box.
157
BRMS Runtime tutorial
158
Install needed tools to run the workbench
Java runtime
Bundle that installs all needed component
Then you run a shell script to make all run. What if you have another version of java ?
This technology allows us to use pre-build images that run on all supported platform of docker :
nearly all linux flavors, Mac Os and windows and this in native way for windows or for MacOS. You
can use this way of using but we shall use the toolbox instead.
This will avoid spolling your operating system, we are going to use virtual machines on your host.
Click in the download page on the Docker ToolBox Setup. The security system will ask you if you
allow this program to execute, answer yes.
159
Install needed tools to run the workbench
160
Install needed tools to run the workbench
161
Install needed tools to run the workbench
162
Install needed tools to run the workbench
Now double click on the "Docker quickstart terminal" and all should start :
163
Install needed tools to run the workbench
The command may need to download the image from the docker hub.
To know if if is running, we shall connect to the drools workbench, we shall first look on which ip the
docker machine is running :
164
Install needed tools to run the workbench
you can now access the workbench at the following address : http:\/\/192.168.99.100:8080\/drools-wb
Login in the workbench and go the deploy\/rule deployment and you should see this.
165
Install needed tools to run the workbench
166