<br>   Section 2.5.2.2 of the documentation:<br><br><a href="http://downloads.jboss.com/drools/docs/5.0.1.26597.FINAL/drools-fusion/html_single/index.html#d0e1086">http://downloads.jboss.com/drools/docs/5.0.1.26597.FINAL/drools-fusion/html_single/index.html#d0e1086</a><br>
<br>   The documentation does not goes down in all the details, but negated patterns will cause the rule to wait and asynchronously fire (like when using the duration attribute) when the matching pattern is not readily available. <br>
<br>   For deterministic unit testing you need to use a pseudo clock, instead of the default realtime clock.<br><br>   []s<br>   Edson<br><br><div class="gmail_quote">2009/9/8 bill simms <span dir="ltr">&lt;<a href="mailto:sitrious@gmail.com">sitrious@gmail.com</a>&gt;</span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hello again,<br><br>Recently while continuing to work on a complex event processing project I have encountered strange,<br>
but interesting, situations where the fireAllRules() method of a StatefulKnowledgeSession appears to<br>
return before actually emptying the activations on the agenda.  I was under the impression that this <br>method only returns after all activations, including subsequent activations, have been completed and<br>removed from the agenda.  If I&#39;m incorrect then feel free to disregard the rest of this message.<br>

<br>[Drools v 5.0.1, JUnit 4.0, Spring 2.5.6]<br><br>The behavior I have noticed begins when working with a rule such as &quot;Find Missing Input Events&quot; <br>(in file test.drl):<br>------------------------------------------------------------------------<br>

package org.drools.test<br><br>import org.drools.test.*<br><br>declare Event<br>    @role( event )<br>    @timestamp( beginning )<br>    @duration( length )<br>    @expires( 1h )<br>end<br><br>declare Fault<br>    @role( event )<br>

    @timestamp( beginning )<br>    @duration( length )<br>    @expires( 1h )<br>end<br><br>query &quot;getFaults&quot;<br>    $fault: Fault() from entry-point &quot;faults&quot;<br>end<br><br>rule &quot;Find Missing Input Events&quot;<br>

    when<br>        $a: Event()<br>            from entry-point &quot;input&quot;<br>        $b: Event( this after $a)<br>            from entry-point &quot;input&quot;<br>        not (Event( (this after $a || this metby $a), (this before $b || this meets $b))<br>

            from entry-point &quot;input&quot;)<br>        not (Fault(this metby $a, this meets $b)<br>            from entry-point &quot;faults&quot;)<br>    then<br>        entryPoints[&quot;faults&quot;].insert(new Fault($a, $b));<br>

end<br><br>rule &quot;Print Faults&quot;<br><br>    when<br>        $f: Fault() from entry-point &quot;faults&quot;<br>    then<br>        System.out.println($f);<br>end<br>------------------------------------------------------------------------<br>

<br>The purpose of this rule is to detect when one or more events are missing in an event sequence.  The<br>events in question are supposed to continue from one to the next without any time in-between.  If this <br>rule does discover a gap/absence between two events a Fault is created for further processing.  (*Note <br>

that the Event and Fault classes that I used only contain two fields, beginning and length, to be used as<br>the time-stamp and duration respectively.)  I noticed the unexpected behavior shortly after creating this <br>unit test:<br>

<br>------------------------------------------------------------------------<br>public class FireAllRulesTest {<br><br>    KnowledgeBase knowledgeBase;<br>    <br>    StatefulKnowledgeSession session;<br>    <br>    /**<br>

     * @throws java.lang.Exception<br>     */<br>    @Before<br>    public void setUp() throws Exception {<br>        KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();<br>        builder.add(ResourceFactory.newFileResource(&quot;target/test-classes/test.drl&quot;), ResourceType.DRL);<br>

        <br>        if(builder.hasErrors()){<br>            throw new RuntimeException(builder.getErrors().toString());<br>        }<br>        KnowledgeBaseConfiguration configuration = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();<br>

        configuration.setOption(EventProcessingOption.STREAM);<br>        <br>        knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase(configuration);<br>        knowledgeBase.addKnowledgePackages(builder.getKnowledgePackages());<br>

        <br>        session = knowledgeBase.newStatefulKnowledgeSession();<br>        WorkingMemoryConsoleLogger logger = new WorkingMemoryConsoleLogger(session);<br>    }<br>    <br>    @Test<br>    public void testAbsence(){<br>

        System.out.println(&quot;Running...&quot;);<br>        //Record the rules that have fired.<br>        ActivationTrackingEventListener listener = new ActivationTrackingEventListener();<br>        session.addEventListener(listener);<br>

        <br>        //Start at 0, go to 100.<br>        Event first = new Event(0,100);<br>        <br>        //Start at 1000, go to 1100. Absence of 900.<br>        Event second = new Event(1000, 100);<br>        <br>        //Start at 1100, go to 1200.  No absence.<br>

        Event third = new Event(1100, 100);<br>        <br>        //Start at 1200, go to 1300.  No absence.<br>        Event fourth = new Event(1200, 100);<br><br>        //Start at 2000, go to 2100.  Absence of 700.<br>

        Event fifth = new Event(2000, 100);<br>        <br>        WorkingMemoryEntryPoint ingest = session.getWorkingMemoryEntryPoint(&quot;input&quot;);<br>        ingest.insert(first);<br>        ingest.insert(second);<br>

        ingest.insert(third);<br>        ingest.insert(fourth);        <br>        ingest.insert(fifth);<br>        <br>        System.out.println(&quot;All events have been inserted.&quot;);<br><br>        session.fireAllRules();<br>

        <br>        System.out.println(&quot;Rules have finished firing.&quot;);<br><br>        //Expect that &quot;Find Missing Input Events&quot; has fired and that there are two faults as a result.<br>        assertTrue(listener.hasRuleFired(&quot;Find Missing Input Events&quot;));<br>

        assertEquals(2,faultCount());<br>        <br>        System.out.println(&quot;Test completed.&quot;);<br>    }<br>    <br>    public int faultCount(){<br>        QueryResults results = session.getQueryResults(&quot;getFaults&quot;);<br>

        return results.size();<br>    }<br><br>}<br>------------------------------------------------------------------------<br><br>The typical result of this test is a failure about 90% of the time.  Strangely, the other 10% of the time this exact <br>

same test is run it will pass, without any modifications.  Equally interesting is the output of the WorkingMemoryLogger:<br><br>------------------------------------------------------------------------<br>Running...<br>OBJECT ASSERTED value:org.drools.test.Event@1b994de factId: 1<br>

BEFORE ACTIVATION FIRED rule:Find Missing Input Events activationId:Find Missing Input Events [2, 1, 0] <br>      declarations: $b=org.drools.test.Event@2803d5(2); $a=org.drools.test.Event@1b994de(1)<br>ACTIVATION CREATED rule:Find Missing Input Events activationId:Find Missing Input Events [2, 1, 0] <br>

      declarations: $b=org.drools.test.Event@2803d5(2); $a=org.drools.test.Event@1b994de(1)<br>OBJECT ASSERTED value:org.drools.test.Event@2803d5 factId: 2<br>OBJECT ASSERTED value:org.drools.test.Event@1b32627 factId: 3<br>

OBJECT ASSERTED value:org.drools.test.Event@ad157f factId: 4<br>ACTIVATION CREATED rule:Find Missing Input Events activationId:Find Missing Input Events [5, 4, 0] <br>      declarations: $b=org.drools.test.Event@1bfa3d3(5); $a=org.drools.test.Event@ad157f(4)<br>

OBJECT ASSERTED value:org.drools.test.Event@1bfa3d3 factId: 5<br>All events have been inserted.<br>***Rules have finished firing.<br>ACTIVATION CREATED rule:Print Faults activationId:Print Faults [6, 0] declarations: $f=org.drools.test.Fault@159780d(6)<br>

OBJECT ASSERTED value:org.drools.test.Fault@159780d factId: 6<br>AFTER ACTIVATION FIRED rule:Find Missing Input Events activationId:Find Missing Input Events [2, 1, 0] <br>      declarations: $b=org.drools.test.Event@2803d5(2); $a=org.drools.test.Event@1b994de(1)<br>

BEFORE ACTIVATION FIRED rule:Print Faults activationId:Print Faults [6, 0] declarations: $f=org.drools.test.Fault@159780d(6)<br>org.drools.test.Fault@159780d<br>AFTER ACTIVATION FIRED rule:Print Faults activationId:Print Faults [6, 0] declarations: $f=org.drools.test.Fault@159780d(6)<br>

BEFORE ACTIVATION FIRED rule:Find Missing Input Events activationId:Find Missing Input Events [5, 4, 0] <br>      declarations: $b=org.drools.test.Event@1bfa3d3(5); $a=org.drools.test.Event@ad157f(4)<br>ACTIVATION CREATED rule:Print Faults activationId:Print Faults [7, 0] declarations: $f=org.drools.test.Fault@c26b16(7)<br>

OBJECT ASSERTED value:org.drools.test.Fault@c26b16 factId: 7<br>AFTER ACTIVATION FIRED rule:Find Missing Input Events activationId:Find Missing Input Events [5, 4, 0] <br>      declarations: $b=org.drools.test.Event@1bfa3d3(5); $a=org.drools.test.Event@ad157f(4)<br>

BEFORE ACTIVATION FIRED rule:Print Faults activationId:Print Faults [7, 0] declarations: $f=org.drools.test.Fault@c26b16(7)<br>org.drools.test.Fault@c26b16<br>AFTER ACTIVATION FIRED rule:Print Faults activationId:Print Faults [7, 0] declarations: $f=org.drools.test.Fault@c26b16(7)<br>

------------------------------------------------------------------------<br><br>It seems that the rule is indeed firing correctly, but that it is doing so only after returning from fireAllRules method.  <br>I have marked line that follows fireAllRules() with *** above.  So the rule fires, but the test fails because the firing <br>

takes place after the junit  assertions are checked.<br><br>But that&#39;s not all, it gets more interesting.  Looking back at the rule file, when you comment out the last condition:<br><br>    not (Fault(this metby $a, this meets $b)<br>


                from entry-point &quot;faults&quot;)<br><br>The problem with the unit test disappears.  After much thought I&#39;m still not sure why this is, but the last condition is<br>critical to avoid creating redundant Faults (Because a lot of the Events are redundant as well.  It just comes with the<br>

problem being solved).  The problem also disappears if you put a Thread.sleep(1000) after firing the rules, which is<br>why I suspect a timing issue between the rules firing and the unit test assertions being evaluated.  This could explain<br>

why the test sometimes works, and sometimes doesn&#39;t.<br><br>I&#39;m hopeful that someone will understand why this is happening, and point how how to prevent it.  Thank you in advance.<br><font color="#888888"><br>Bill<br>
<br>
</font><br>_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>  Edson Tirelli<br>  JBoss Drools Core Development<br>  JBoss by Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a><br>