Lesson 2 : binding
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
public static KieSession getStatefulKnowledgeSessionWithCallback(
KieContainer kieContainer, String sessionName) {
KieSession session = getStatefulKnowledgeSession(kieContainer, sessionName);
session.addEventListener(new RuleRuntimeEventListener() {
public void objectInserted(ObjectInsertedEvent event) {
System.out.println("Object inserted \n"
+ event.getObject().toString());
}
public void objectUpdated(ObjectUpdatedEvent event) {
System.out.println("Object was updated \n"
+ "new Content \n" + event.getObject().toString());
}
public void objectDeleted(ObjectDeletedEvent event) {
System.out.println("Object retracted \n"
+ event.getOldObject().toString());
}
});
session.addEventListener(new AgendaEventListener() {
public void matchCreated(MatchCreatedEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " can be fired in agenda");
}
public void matchCancelled(MatchCancelledEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " cannot b in agenda");
}
public void beforeMatchFired(BeforeMatchFiredEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " will be fired");
}
public void afterMatchFired(AfterMatchFiredEvent event) {
System.out.println("The rule "
+ event.getMatch().getRule().getName()
+ " has be fired");
}
public void agendaGroupPopped(AgendaGroupPoppedEvent event) {
}
public void agendaGroupPushed(AgendaGroupPushedEvent event) {
}
public void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
}
public void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent event) {
}
public void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
}
public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {
}
});In the CashFlow class, we should add the following toString method
in the util package, we shall create a DateHelper class that will look like this :
In the kmodule.xml, make it look like that
in the src/test/rules, create a package lesson2 and a rule resource named lesson2.drl and should look like this :
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 we know all is working we can continue our lesson.
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$.
The result should be a balance of 500$ for the accounting period.
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 CashFlow.
Then we add a second constraint of type Account. The question is now how in the then part do the balance update. It is where the fact binding comes in :
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.
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 :
When we run the test case, the test fails :
and in the console, we see that the rule "Credit rule" is running twice :
The rule was fired twice because there are 2 (CashFlow,Account) couples. The first CashFlow mouvement concerns account number 1 and the seconde account number 2. We need to find a way to link the two facts. We shall modify the rule like this :
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 :
In the rule above, we add a constraint so that the mvtDate of the CashFlow is between the startDate and endDate of the AccountinPeriod.
and the test case
As expected, the "Credit Rule" is fired once and the "Debit Rule" is fired once also. The CashFlow movement of April 15 2016 is ignored as it does not fulfill the constraints.
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.
Last updated
Was this helpful?