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

Mark Proctor mproctor at codehaus.org
Sun Oct 27 12:57:38 EDT 2013


By default the rule engine has no concept of latest, there is simply the data that is currently present. It evaluates that data to produce activations, and then fires those.

If you need the notion of latest, and are unable to emulate this yourself, you can switch the engine to steam mode and use events. If the fact is the event you can do something like the follow:
s1 : SampleFact( )
not( SampleFact( this after s1 )
eval( s1.getValue < 10 )


Mark


On 27 Oct 2013, at 16:33, mikerod <mjr4184 at gmail.com> wrote:

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