<br>  Hi Andreas,<br><br>   Yes, please open a JIRA and attach your patch. I will try to reproduce and create a test case from your description, but sometimes it would be faster if you could provide a dumbed down or obfuscated version of the rule you are using that is causing the problem...<br>
<br>   Thanks,<br>     Edson<br><br><div class="gmail_quote">2010/3/29 Andreas Kohn <span dir="ltr">&lt;<a href="mailto:andreas.kohn@fredhopper.com">andreas.kohn@fredhopper.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Hi,<br>
<br>
while working further on our drools integration we came across an odd<br>
exception when removing a particular rule:<br>
<br>
java.lang.IllegalArgumentException: Cannot remove a sink, when the list of sinks is null<br>
        at org.drools.reteoo.ObjectSource.removeObjectSink(ObjectSource.java:159)<br>
        at org.drools.reteoo.RightInputAdapterNode.doRemove(RightInputAdapterNode.java:217)<br>
        at org.drools.common.BaseNode.remove(BaseNode.java:95)<br>
        at org.drools.reteoo.BetaNode.doRemove(BetaNode.java:275)<br>
        at org.drools.common.BaseNode.remove(BaseNode.java:95)<br>
        at org.drools.reteoo.BetaNode.doRemove(BetaNode.java:280)<br>
        at org.drools.common.BaseNode.remove(BaseNode.java:95)<br>
        at org.drools.reteoo.RuleTerminalNode.doRemove(RuleTerminalNode.java:387)<br>
        at org.drools.common.BaseNode.remove(BaseNode.java:95)<br>
        at org.drools.reteoo.ReteooBuilder.removeRule(ReteooBuilder.java:237)<br>
        at org.drools.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:371)<br>
        at org.drools.common.AbstractRuleBase.removeRule(AbstractRuleBase.java:746)<br>
<br>
While stepping through the code it looked like the network was corrupt (there was indeed no<br>
sinks on the ObjectSource, but the node calling removeObjectSink was still linked to it<br>
and claiming it as source).<br>
<br>
The rule itself contains multiple NotNodes, checking a condition that looks like this:<br>
not(not(Foo.v = X) and not(Foo.v = Y))<br>
<br>
<br>
I could track this down to some sort of &quot;loop&quot; in the rete that triggers this when the outer<br>
not node is removed.<br>
<br>
When removing BetaNode#doRemove() first walks along &#39;rightInput&#39;:<br>
<br>
        this.rightInput.remove( context,<br>
                                builder,<br>
                                this,<br>
                                workingMemories );<br>
<br>
<br>
and eventually _in that call_ it also hits a node that is the direct &#39;leftInput&#39; of the original beta node.<br>
The removal marks that node as visited in the removal context, and when the &#39;rightInput.remove&#39; returns to the<br>
beta node it does not visit the leftInput due to this condition in BetaNode#doRemove():<br>
<br>
        if ( !context.alreadyVisited( this.leftInput ) ) {<br>
            this.leftInput.remove( context,<br>
                                   builder,<br>
                                   this,<br>
                                   workingMemories );<br>
        }<br>
<br>
In other words: before the remove the BetaNode had another node that was both referenced directly as &#39;leftInput&#39;,<br>
as well as an input to the &#39;rightInput&#39;.<br>
<br>
The first removal of the rule &quot;worked&quot;, and no exceptions happened. But: any further attempt to re-add the same rule and remove<br>
it again lead to the exception above.<br>
<br>
<br>
<br>
I was able to fix it with the attached patch, reproduced here:<br>
<br>
+        boolean needRemoveFromLeft = !context.alreadyVisited( this.leftInput );<br>
         this.rightInput.remove( context,<br>
                                 builder,<br>
                                 this,<br>
                                 workingMemories );<br>
-        if ( !context.alreadyVisited( this.leftInput ) ) {<br>
+        if ( needRemoveFromLeft ) {<br>
             this.leftInput.remove( context,<br>
                                    builder,<br>
                                    this,<br>
                                    workingMemories );<br>
         }<br>
<br>
With this patch applied I could add/delete/add the particular rule repeatedly without problems.<br>
<br>
The attached patch also adds an assert in ObjectSource#removeObjectSink(): when removing a sink from an object source with<br>
only one sink the sink was unconditionally replaced with an empty sink, although the argument ObjectSink could be a different<br>
sink than the one in the ObjectSource. For CompositeObjectSinkAdapters this case is checked, but not for single sinks.<br>
I originally suspected that place to be responsible for the problem I observed but the assertion never fired in my tests.<br>
<br>
<br>
Should I open a JIRA issue? Unfortunately I cannot provide a DRL to reproduce the issue, but I could<br>
try dumping the rulebase if that would help.<br>
<br>
<br>
Regards,<br>
--<br>
Andreas<br>
<font color="#888888"><br>
--<br>
Never attribute to malice that which can be adequately explained by<br>
stupidity.                                        -- Hanlon&#39;s Razor<br>
</font><br>_______________________________________________<br>
rules-dev mailing list<br>
<a href="mailto:rules-dev@lists.jboss.org">rules-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-dev</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>