Drools, part 1.
Problem statement
The goal of this class is to model an offer process in a small company. The diagram below shows a generalized task flow in the process:
The offer process is initiated via an external document describing the order.
The description takes many different forms, from informal inquiries (contact is the only valuable part), to highly formalized documents describing the order, broken down into several aspects (commercial, formal, etc).
One can distinguish two important features of the query:
formal requirements defining the process, eg. preventing or limiting contact with the ordering party at the offer stage, as well as the commercial terms of joining the offer procedure.
the level of order specification, e.g. from one that barely signals the subject matter and does not allow any analysiks without further inquiries, to a coherent and complete presentation of the item, which should be enough to prepare the offer.
The process that we want to model will support the user in making decisions during the three main stages of processing the offer inquiry:
Formal analysis.
Substantive analysis.
Preparing the right offer.
First of all, a formal/commercial analysis has to performed. One has to check the conditions, whether the company is able to fulfill the order according to the proposed procedure.
At this stage, the conditions are verified, such as having the right permissions, having the required certificates, appropriate company qualifications, etc.
Negative completion of this stage results in automatic termination of the offer process.
Substantive Analysis
If the formal analysis ends with a positive result, the substantive analysis is performed on the query.
Substantive analysis consists of two phases: preliminary substantive analysis and proper substantive analysis.
During the initial analysis, it is determined (based on the available knowledge) whether the order can be completed.
Factors such as availability of teams, project risk, attractiveness of the order etc. are taken into account here.
If the order is feasible, then the proper analysis is performed, during which the cost estimate and the substantive part of the offer are prepared based on the opinions of the experts (e.g. IT department employees).
If it turns out that the specification provided in the inquiry is insufficient, then the customer is contacted (if it is possible) to the get missing data.
If the contact with the customer is impossible, the request is rejected.
The results of the substantive analysis are: the concept of the solution and the initial cost estimates.
Creating the offer
The substantive analysis' results serve as a starting point for preparing the right offer.
This stage, carried out by the sales department, is designed to develop the final valuation.
The final valuation is calculated on the basis of the valuation prepared by the IT department and appropriate modifiers as: commercial attractiveness, substantive attractiveness, how important is the client, etc.
The offer prepared this way has to be approved by the board, and can be sent to the clien only after applying required fixes and changes.
The modeling of the described example will include:
Rule aspect: Defining a rule system supporting a user in the decision-making process at the stages of formal, substantive and offer preparation.
Process aspect: Mmdeling the complete process describing the request processing.
The description you've just read is only meant to introduce into the context.
Details, like sizes, attributes, coefficients and their dependencies describing the problem will be introduced only at the appropriate modeling stage.
The instructions are not binding and you can freely make modifications at your own discretion / invention.
Scope of the 1st part
In first part, we will model the basic components of the knowledge base (or repository as you will see).
We will also learn how to create additional resources (resource files, packages, etc.), required to execute the model
For now we will model only the formal analysis part of the process.
Guvnor - Knowledge Repository
Having the JBoss running, visit the following address:
http://127.0.0.1:8080/drools-guvnor
In case you were asked to log in, enter:
login: admin
password: admin
In the left panel there are several entries:
Browse - just browse the repository
Knowledge Bases - contains definitions of all the knowledge bases, their packages and components. This will interest us at most.
QA - allows user to define and run tests.
Package snapshots - manages the compiled packages
Administration - you can guess ;)
Defining a new package
Every item in the repository has to be placed in the Global Area, or in a package
In order to prevent conflicts between different teams working on the same repository, every user should create his own package (with an unique name).
To create a new package, enter
Knowledge Bases
and choose
Create New
⇒
New Package
:
![](/_media/pl:dydaktyka:rules:lab:labs:createnewpackage.png)
Avoid spaces and special characters (like dash '-') in the name
![:!:](/lib/images/smileys/icon_exclaim.gif)
Compiling the package
Before being used, the package has to be compiled first
We wil compile the package in the beginning, so later we will have only to update it.
To compile the package
click on the name of the package (left panel)
select the Edit
tab,
press Build package
.
Successful compilation is indicated by a green icon and a message similar to:
Package built successfully. Last modified on Wed Oct 24 11:14:10 GMT+200 2012
A good practice is to create snapshots of the package, that will be later delivered to the applications. This way we will avoid version related problems.
In order to create a snapshot, one has to:
press Create snapshot for deployment
first time one has to press NEW
and give it a name, e.g. package_name-pkg — again, avoid spaces at all costs
later, there will be a second option to use the existing name (that we will use)
![](/_media/pl:dydaktyka:rules:lab:labs:buildpackage.png)
Creating resources
Resource database ChangeSet
, this file contains all resources' definition
One can add resource in one of the two ways:
Every resource one by one .
We add a file that contains resources' definitions, so called ChangeSet
.
The second solution is better because:
there is no need to recompile the package after changing the resources (size, amount)
the ChangeSet
can be easily downloaded from the server
To create ChangeSet
one has to:
The file has been created; now we can edit it. For now we add there only a snapshot of our package
we put cursor between the tags <add>…</add>
.
In left part of the windows, we press Package
, in the Add new <resource> Element
section.
One can also add single items from other packages, using the button:Asset
.
In the new dialog we expand the
Packages
tree too find the recently created snapshot.
![](/_media/pl:dydaktyka:rules:lab:labs:editchangeset.png)
If everything has been done correctly, you should get a result similar to
<resource source='http://127.0.0.1:8080/drools-guvnor/org.drools.guvnor.Guvnor/package/package-name/snapshot-name' type='PKG'/>
This file contains a resource in a form of a package snapshot, that should be enough to compile the knowledge base.
In order to give access to the resources from the outside, we have to make it availible. In theresource
tag, we add the three attributes and values:
basicAuthentication='enabled
'
username='admin
'
password='admin
'
Now we save the file: File
⇒ Save and close
.
Defining the facts' model
Before adding rules, we have first to define structure of the knowledge base/facts. Again we can go two ways:
use the guvnor interface
upload the POJO (Plain Old Java Object) classes in a jar.
We will go the first way
We will define two types of facts:
Proper facts - facts/objects containing knownledge obtained during the offer process
Auxiliary facts - facts/objects defining the state of the process.
Defining the facts
At this moment we can define the following facts:
Type 1: facts telling if the offer fulfills certain formal requirements, e.g
Is the aquisition possible?
Do we have a sufficient insurance policy.
Do we have a required certificates.
Do we have sufficient experience?
Does the offer meets the minimal formal expectations?
Is the offer in conflict with the different offers?
Type 2: facts containing decisions took in the formal analysis process
Type 3: auxiliary facts defining the current state of the proccess
Because Type 1. facts are very similar to each other, to we can use the inheritance technique, known from tohe object programming. We will create one base fact and other will inherit from it.
Because facto of Type 1 and Type 2 are on a similar level of abstraction, they will put together in the same group. The Type 3 will be separated.
In order to define a group of facts, one has to:
use
Knowledge bases
⇒
Create New
⇒
New Declarative Model
![](/_media/pl:dydaktyka:rules:lab:labs:createndm.png)
In the new dialog window:
select Create new
choose a name, e.g. factTypes
then Create in Package:
.
We select our package from the list.
The same way one can define the second group, e.g. helperTypes
.
Now we can define the fact types:
Assets
⇒ Model
⇒ factTypes
(your name) ⇒ Open
.
In the new window we press Add new fact type
to add a new type
First, we will create a base type for the all Type 1 facts.
give it a name, e.g. reqsFormal
OK
Now we define fields/properties of the type:
Asked
- [True/False
] - defining if the specific question was asked/answered
Question
- [String
] - the question itself
Answer
- [True/False
] - answer provided by the user
ProceedAnswer
- [True/False
] - correct (positive) answer for the question
To add the field, find the Add Field
button in the edition panel and fill the form:
specify the name, e.g. Question
select the
Text
datatype.
![](/_media/pl:dydaktyka:rules:lab:labs:createnewfactfield.png?w=600&tok=bf96c5)
After creating the base type, we will define the other facts based on it
Our facts will not add any new fields, they will just differ with a type itself
To create a deriverative fact, we proceed almost the same way as before; we have only to select the base type:
![](/_media/pl:dydaktyka:rules:lab:labs:factextend.png)
This way we create at least six new types:
reqsFormalAcquisition
reqsFormalInsurance
reqsFormalCertificates
reqsFormalExperience
reqsFormalMinExpectations
reqsFormalConflicts
Now, the last fact in this group will be tyhe Type 2 fact. It will contain a decision whether the offer passed the formal analysis:
the new fact should be named formalDecision
and have only one boolean field Decision
Resulting list of facts should look similiar to:
![](/_media/pl:dydaktyka:rules:lab:labs:factlist.png)
Don't forget to File
⇒ Save and close
.
Now the second group, the helperTypes
:
Add a new fact type based on:
![](/_media/pl:dydaktyka:rules:lab:labs:helpertypes.png?w=600&tok=7ead33)
This fact will hold info about the current state of the process
The state
field will be of the Text
type and will get values only from a specified list
To add this kind of enumarated type:
Create New
⇒
New Enumeration
.
![](/_media/pl:dydaktyka:rules:lab:labs:newenum.png)
Then:
Create new
,
give it a name, e.g. sthuc-enums
,
Create in Package:
⇒ select our package
upewniamy się że obiekt zostanie utworzony w naszym pakiecie.
In case we were asked to edit the object after creating it, we put in:
'State.state' : ['initial', 'formal']
In case we were asked to fill a simple form, we fill it in a following way:
Then: File
⇒ Save and close
!
Defining simple rules
We will need four following rules:
rule that would initialize the knowledge base
rule that asks user a question and store the answer
rule that checks if we should proceed to the next step of the process
rule that would refuse the offer if didn't pass the formal requirements
Let's start with the first rule:
Create New
⇒ New Rule
.
Create new
,
fill in the name, e.g. initial
,
from Type (format) of rule:
we choose Business Rule (Guided Editor)
,
Create in package
and make sure you select a good package
![](/_media/pl:dydaktyka:rules:lab:labs:createnewrule.png)
Another window…
Because this is an initializing rule, it doesn't need a conditional part. We only define the decisive part of the rule:
THEN
⇒ PLUS
If the new window doesn't contain an action that would satisfy us, we can always add a new action manually by choosing Add free form drl
. In our case however ther will be no need for such a drastic measure. Our rule will just add one instance of fact per every type. To create a fact one should:
Insert fact reqsFormalAcquisition…
(or other name)
OK
.
We fill initial values of the fact's fields:
Asked
= false
because it wasn't asked yet
ProceedAnswer
should a positive value by default.
Question
should have a form of a question specified in natural language (e.g. Is the aquisition possible [true/false]
To put an initial value:
we select the new action
![](/_media/pl:dydaktyka:rules:lab:labs:addfield.png)
we choose a field we want to modify
the Bound variable
field should be left empty
press the pencil button next to the field and choose a Literal value
(so we can put a constant). To use variables or other expressions we would have to select Forumla
After creating all the Type 1 fact, we add a new auxiliary fact State
, with a field state
set to formal
(because it's an initial state of the process).
The rule should look similiar to:
![](/_media/pl:dydaktyka:rules:lab:labs:initialrule.png?w=700&tok=f38fcb)
File
⇒ Save and close
.
Second rule will display questions and gather the answers:
Let's give it a name: reqsFormalFill
.
There are two conditions that have to be meet before firing the rule:
There is a State
fact with a fieldstate
set to formal
,
There are still fact based on reqsFormal
, that user hasn't answered yet (Asked
== false
).
For every fact of this type, the rule should:
display the querstion contained in the fact
get the answer
modify the processed fact
To do this:
We add the first conition: There exists a fact of type State
with field state
set to formal
.
WHEN
⇒ PLUS
In the familiar dialog we choose State…
, then OK.
There should be a new condition now, There is a State:
.
We click on it, then press Add a restriction on a field
⇒ state
.
Name of the field should be now added to the condition
![](/_media/pl:dydaktyka:rules:lab:labs:fieldconstraint.png)
W choose equal to
from the list and define the constraint
In the same way we add condition: There exist facts of type reqsFormal
(or deriverative), that weren't answered yet (Asked
== false
).
In order to have access to the fact that triggered the rule, we put a name into a
Variable name
field:
![](/_media/pl:dydaktyka:rules:lab:labs:boudvariable.png)
The conditional part of the rule should look similiar to
![](/_media/pl:dydaktyka:rules:lab:labs:rulefillcondpart.png)
Now we can define a decisive part.
First action: display question. We will use a terminal to do thatl, so we choose Add free form drl…
.
Now we put the java code:
System.out.println(r.Question + "?");
Notice that we can refer to the fact via the variable r
.
-
Third and the last action will be to update the Asked
field's value.
we add new action: Modify r…
Question: (how does it differ from Change field values of r…
?),
we choose a field a new value.
The complete rule should look like:
![](/_media/pl:dydaktyka:rules:lab:labs:rulefillall.png?w=700&tok=ae3298)
Third and fourth rules are triggered when all the decision have been already made, i.e.
Precisely, the reqsFormalOK
rule is triggered by the following conditions:
There is a fact State
with state
field set to value formal
.
There is no fact of type reqsFormal
(or derived), that:
would have Asked
field equal false
.
Asked
== true
and at the same time Answer
not equalt the ProceedAnswer
.
The reqsFormalFail
is fired if any of those conditions is not met.
The decisive parts of both the rules create a new fact formalDecision
with a corresponding Decision
value
Both rules should also display their results in the terminal. The reqsFormalFail
rule should also display reason, why the offer was rejected.