[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:07:49 EDT 2013


Oops - the "even better" doesn't quite achieve the same thing.
Sorry
-W

On 27/10/2013, Wolfgang Laun <wolfgang.laun at gmail.com> wrote:
> 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