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

mikerod mjr4184 at gmail.com
Sun Oct 27 12:33:19 EDT 2013


I appreciate your input.  I understand what you are saying regarding the
design of the activations caused by the accumulate.
Unfortunately, this is making it hard to express the logic I'm going for in
a concise manner.

I'll give a bit more of a "real", but similar example here.

With my example rules:

file <<example.drl>>

package drools

rule "testing"
	dialect "mvel"
	when
		$sample : SampleFact() from accumulate( $sf : SampleFact(),
							 	    init( SampleFact temp = null; ),
							 	    action( temp = ((null == temp) || ($sf.version > temp.version))
? $sf : temp; ),
							 	    result( ((null != temp) && (temp.value < 10)) ? temp : null; ))						 	     
	then
		insertLogical( "inserted" + $sample.toString() );
	
end

declare SampleFact
    value : Long
    version : Long
end

endfile <<example.drl>>

And 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.definition.type.FactType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.junit.Test;

public class ExampleDroolsTest {

    @Test
    public void test() throws IOException, InstantiationException,
IllegalAccessException {
        final KnowledgeBuilder kbuilder =
KnowledgeBuilderFactory.newKnowledgeBuilder();
       
kbuilder.add(ResourceFactory.newClassPathResource("drools/example.drl"),
ResourceType.DRL);
        final KnowledgeBase kbase = kbuilder.newKnowledgeBase();

        final StatefulKnowledgeSession ksession =
kbase.newStatefulKnowledgeSession();

        final FactType sampleFactFt = kbase.getFactType("drools",
"SampleFact");

        final Object sampleFact1 = sampleFactFt.newInstance();
        sampleFactFt.set(sampleFact1, "version", 1L);
        sampleFactFt.set(sampleFact1, "value", 5L);
        final Object sampleFact2 = sampleFactFt.newInstance();
        sampleFactFt.set(sampleFact2, "version", 2L);
        sampleFactFt.set(sampleFact2, "value", 15L);
        // final Object sampleFact3 = sampleFactFt.newInstance();
        // sampleFactFt.set(sampleFact3, "version", 3L);
        // sampleFactFt.set(sampleFact3, "value", 9L);

        ksession.insert(sampleFact1);
        ksession.insert(sampleFact2);

        // Changes behavior to what I would expect, the "most recent"
SampleFact does not have
        // a value < 10, so there should be no working memory element
inserted.
        // ksession.insert(sampleFact2);
        // ksession.insert(sampleFact1);

        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>>

My goal is to write a rule that only inserts a new object into working
memory when the
"most recent" SampleFact has value < 10.  Most recent is defined here as the
greatest value for the "version" attribute of SampleFact. 
Ultimately, I do not want to accept any SampleFact other than the most
recent to activate the rule and cause the String generated by
`"inserted" + $sample.toString()` to be inserted into working memory.

Of course, when inserting sampleFact1, then sampleFact2 as above in
ExampleDroolsTest.java, I get the String "insertedSampleFact( value=5,
version=1 )" inserted, and not retracted into working memory.  I consider
this fact to be an intermediate result during accumulation of the
SampleFacts in the working memory.

I have observed that successive accumulate activations overwrite each other
if the rule is not fired in between.  This generally gives me the desired
behavior of getting the most recent when all facts meet the `result`
criteria as well, however, in this example where the most recent fact does
not meet the additional `result` criteria, it fails my use-case.

What would be a good way to accomplish this, if I cannot use the accumulate
as I have currently?



--
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-tp4026507p4026511.html
Sent from the Drools: User forum mailing list archive at Nabble.com.


More information about the rules-users mailing list