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

Wolfgang Laun wolfgang.laun at gmail.com
Sun Oct 27 13:05:10 EDT 2013


It's generally a bad idea to introduce null when it isn't absolutely necessary.

$sample : SampleFact( value < 10 ) from
      accumulate( $sf : SampleFact(),
                           init( SampleFact temp = null; long vers =
Long.MIN_VALUE ),
                           action( if ($sf.version > temp.version){
temp = $sf; vers = $sf.version } ),
                           result( temp) )

Or even better

$sample : SampleFact() from
      accumulate( $sf : SampleFact(value < 10 ),

and continuing as above.

-W

On 27/10/2013, 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