A am new in Drools and have read some docs and tutorials, sure, my question has a trivial solution. I use onle rule file and class Counter, depicted below. The environment is : Wintel JDK 1.7 (71), DROOLS 6.1.0
public class DroolsInsertionTester {
private Logger log = Logger.getLogger(this.getClass().getName());
private KieSession getNewStatefullKIESession (){
KieContainer kContainer = KieServices.Factory.get().getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("test");
return kSession;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DroolsInsertionTester tester = new DroolsInsertionTester();
tester.test();
}
private void test() {
KieSession kSession = getNewStatefullKIESession();
Counter cnt1 = new Counter(1);
Counter cnt2 = new Counter(2);
FactHandle fact1, fact2;
// STEP 1
fact1 = kSession.insert(cnt1);
kSession.fireAllRules();
// STEP 2
fact2 = kSession.insert(cnt2);
kSession.fireAllRules();
}
public class Counter {
public int count;
public Counter (int cnt){
this.count = cnt;
}
there is an rule
rule "Counter shower 1"
when $Counter : Counter()
then
System.out.println("Counter there (1) : " + $Counter.count);
end
rule "Counter shower 2"
when
$Counter : Counter()
accumulate (Counter() ; $cnt : count())
then
System.out.println("Counter there (2) : " + $Counter.count);
end
rule "Counter shower 3"
when
Counter()
then
System.out.println("Counters there (3) : ");
end
rule "Counter creator"
when $Counter : Counter(count == 2)
then
insert (new Counter(3)); // STEP 3
System.out.println("new Counter created ");
end
rule "Counter remover"
when
$Counter : Counter(count == 1)
exists Counter (count == 3)
then
retract ($Counter) ; // STEP 4
System.out.println("retract counter with ID = 1");
end
This is kModule
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="rules" packages="rules">
<ksession name="test" />
</kbase>
</kmodule>
The result of runnings
Counter there (1) : 1
Counter there (2) : 1
Counters there (3) :
Counter there (1) : 2
Counter there (2) : 1
Counter there (2) : 2
Counters there (3) :
new Counter created
Counter there (1) : 3
Counter there (2) : 1
Counter there (2) : 2
Counter there (2) : 3
Counters there (3) :
retract counter with ID = 1
Counter there (2) : 2
Counter there (2) : 3
My questions are:
The program code doesn’t contain any “kSession.delete” all fact are hold in Working memory. So, in my point of view, the rules "Counter shower 1" .. "Counter shower 3" should fire for each Counter object in Working Memory after each fireAllRules calls. One for STEP 1, two times for STEP2, three times for STEP3 e.g. But output listing notes only "Counter shower 2" worked in that way. The "Counter shower 1" and "Counter shower 3" fire only once by one fireAllRules call.
Why rule "Counter shower 1" catches over last inserted facts only? Are any hidden behaviors there?
3.Why after retract object Counter with count == 1 only "Counter shower 2" fires? What about other rules ?
Thank for any help.
Question 1: The program code doesn’t contain any “kSession.delete” all fact are hold in Working memory. So, in my point of view, the rules "Counter shower 1" .. "Counter shower 3" should fire for each Counter object in Working Memory after each fireAllRules calls. One for STEP 1, two times for STEP2, three times for STEP3 e.g. But output listing notes only "Counter shower 2" worked in that way. The "Counter shower 1" and "Counter shower 3" fire only once by one fireAllRules call.
You should understand that fireAllRules
doesn't actually fire all of the rules in your knowledge base. The name is a bit misleading. :)
Instead of talking about rules "firing", it's better to thing of them as "activating". You have a stateful session, so when you first called fireAllRules
, three of your rules activated based on the Counter
you initially inserted. When you call insert
/fireAllRules
again, those rules are still activated for the initial Counter
! They do not need to activate again. Unless the state of the working memory has changed to cause a rule to deactivate and reactivate, you will not see anything happening in your right-hand-sides.
This is actually the whole point of a stateful session. Your knowledge base can incrementally "learn" facts and can evaluate new facts based on existing knowledge.
Evaluating every fact from the assumption of zero knowledge is what stateless sessions are for.
Question 2: Why rule "Counter shower 1" catches over last inserted facts only?
You have a stateful session, so the match for the initial insert of a Counter
activated on the first fireAllRules
. Nothing has changed in working memory since then to impact the initial activation, so it no longer needs to activate when you fireAllRules
again.
Question 3: Why after retract object Counter with count == 1 only "Counter shower 2" fires? What about other rules?
The "Counter shower 2" rule is the only rule affected by the retraction, because it has an accumulator counting your Counter
facts.