[rules-users] Unexpected behavior of accumulate() and insertLogical() when the result() goes from matching a constraint to not matching

Davide Sottara dsotty at gmail.com
Sat Oct 26 21:46:08 EDT 2013


The reason why you experience this behavior is rooted in the difference
between rule evaluation and rule firing.
The custom accumulate is reevaluated, in your case, for each Long you
insert: since you only have the accumulate,
the result of the accumulate will be used to generate a tuple for the
RuleTerminalNode, which will result in
an activation, to be fired later when you call fireAllRules. By
(somewhat debatable) design, activations from
the same accumulate will override each other if not fired in between.

This said, we have two scenarios here:
1) 5 first, 15 second :
when you insert 5, 5 is now the highest. It is also < 10, so an
activation is generated on the agenda.
now you insert 15: it becomes the new highest value, but it is NOT < 10,
so the accumulate returns
null. Unfortunately, null does NOT match "Long() from accumulate ..." so
there will be no new activation
to override the preexisting one. That will fire and you will see
"inserted 5" in the working memory.

2) 15 first, 5 second
when you insert 15, it becomes the highest. The result is null, and for
the same reason above NO
activation will be generated. You now insert 5, but this value won't
change highest, so you will
not see any activations either.

Under the premises, the behavior is correct. You may want to replace the
result:
    result( (highest < 10) ? highest : -1L; )
you should see a more coherent behavior :)

Let me know if you need more clarifications
Best,
Davide

On 10/26/2013 01:32 PM, mikerod wrote:
> This is a follow up from my original post @
> http://drools.46999.n3.nabble.com/rules-users-Question-about-custom-accumulation-functions-tp3280838p4026505.html
>
> Using Drools version 5.5.0.Final
>
> I am experiencing behavior I did not expect, regarding Drools accumulate
> functionality.
> The following demonstrates:
>
> With an example (contrived) rule such as:
>
> file <<example.drl>>
>
> package drools
>
> rule "testing"
> 	dialect "mvel"
> 	when
> 		$res : Long() from accumulate( $l : Long(),
> 							    init( Long highest = null; ),
> 							    action( highest = ((null == highest) || ($l > highest)) ? $l :
> highest; ),
> 							    result( (highest < 10) ? highest : null; )) 
> 	then
> 		insertLogical( new String("inserted " + $res.toString()) );
> 	
> end
>
> endfile <<example.drl>>
>
> I have the following, simple test case:
>
> file <<ExampleDroolsTest.java>>
>
> package drools;
>
> import java.io.IOException;
>
> import org.drools.KnowledgeBase;
> import org.drools.builder.KnowledgeBuilder;
> import org.drools.builder.KnowledgeBuilderFactory;
> import org.drools.builder.ResourceType;
> import org.drools.io.ResourceFactory;
> import org.drools.runtime.StatefulKnowledgeSession;
> import org.junit.Test;
>
> public class ExampleDroolsTest {
>
>     @Test
>     public void test() throws IOException {
>         final KnowledgeBuilder kbuilder =
> KnowledgeBuilderFactory.newKnowledgeBuilder();
>        
> kbuilder.add(ResourceFactory.newClassPathResource("drools/example.drl"),
> ResourceType.DRL);
>         final KnowledgeBase kbase = kbuilder.newKnowledgeBase();
>
>         final StatefulKnowledgeSession ksession =
> kbase.newStatefulKnowledgeSession();
>
>         /** HERE the insertion order of these two facts, will result in
> different outcomes for 
>          * the rule "testing" in example.drl .
>          * In this order, I will get the RHS logic to insert the new
> String("inserted" + $res.toString())
>          * The accumulate should be getting the max valued Long, in the end
> and then the `result` of the
>          * `accumulate` should yield a null value.
>          *
>          * If I flip the inserts, no fact is inserted into the session.
>          */
>         ksession.insert(new Long(5));
>         ksession.insert(new Long(15));
>
>         final int rulesFired = ksession.fireAllRules();
>
>         System.out.println("Rules fired: " + rulesFired);
>
>         System.out.println("Session objs:");
>         for (final Object o : ksession.getObjects()) {
>             System.out.println(o);
>         }
>         ksession.dispose();
>     }
> }
>
> endfile <<ExampleDroolsTest.java>>
>
> As I note in the Java source comment above, the order of the insertions of
> the Long's into the session, change the results of the rule execution.  My
> initial understanding of accumulate, would be that the LHS would be
> invalidated once the highest Long value
> was found to be 15 > 10, as the `result` portion of the `accumulate` tests. 
> Since the String object is inserted logically, I'd 
> expect the fact to be retracted from the working memory once the LHS of the
> rule "testing" was found to be false.
> If this were the case, the order of insertions above in the test case, would
> result in the same working memory after rule execution.
>
> Is this intended behavior of the accumulate node along with the
> `insertLogical` operation?  
>
> Thanks!
>
>
>
> --
> View this message in context: http://drools.46999.n3.nabble.com/Unexpected-behavior-of-accumulate-and-insertLogical-when-the-result-goes-from-matching-a-constraint-g-tp4026507.html
> Sent from the Drools: User forum mailing list archive at Nabble.com.
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>



More information about the rules-users mailing list