I've encountered a NPE in TruthMaintananceSystem:304 on retractions of
tracked facts (because getLogicalDependencies() returns null).

I hunted it down to DefaultKnowledgeHelper::setActivation() method. A
comment there says that this was added to resolve the JBRULES-2558
bug.

My attempt to fix it is attached - instead of removing the list of
logical dependencies, I instead track re-additions and then remove
everything else.
diff --git a/prj/sd-server/src/main/java/org/drools/base/DefaultKnowledgeHelper.java b/prj/sd-server/src/main/java/org/drools/base/DefaultKnowledgeHelper.java
index dc0eaac..0192840 100644
--- a/prj/sd-server/src/main/java/org/drools/base/DefaultKnowledgeHelper.java
+++ b/prj/sd-server/src/main/java/org/drools/base/DefaultKnowledgeHelper.java
@@ -22,6 +22,7 @@ import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.Collections;
 import java.util.IdentityHashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 import org.drools.FactException;
@@ -31,6 +32,7 @@ import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalRuleFlowGroup;
 import org.drools.common.InternalWorkingMemoryActions;
 import org.drools.common.InternalWorkingMemoryEntryPoint;
+import org.drools.common.TruthMaintenanceSystem;
 import org.drools.impl.StatefulKnowledgeSessionImpl;
 import org.drools.reteoo.ReteooWorkingMemory;
 import org.drools.rule.Declaration;
@@ -66,7 +68,7 @@ public class DefaultKnowledgeHelper
 
     private IdentityHashMap<Object, FactHandle> identityMap;
 
-    private LinkedList                          previousJustified;
+    private IdentityHashMap<Object, FactHandle> reasserted;
 
     public DefaultKnowledgeHelper() {
 
@@ -77,6 +79,7 @@ public class DefaultKnowledgeHelper
 
         this.identityMap = new IdentityHashMap<Object, FactHandle>();
 
+	    this.reasserted = new IdentityHashMap<Object, FactHandle>();
     }
 
     public void readExternal(ObjectInput in) throws IOException,
@@ -87,6 +90,7 @@ public class DefaultKnowledgeHelper
         tuple = (Tuple) in.readObject();
         workingMemory = (InternalWorkingMemoryActions) in.readObject();
         identityMap = (IdentityHashMap<Object, FactHandle>) in.readObject();
+	    reasserted = (IdentityHashMap<Object, FactHandle>) in.readObject();
     }
 
     public void writeExternal(ObjectOutput out) throws IOException {
@@ -96,6 +100,7 @@ public class DefaultKnowledgeHelper
         out.writeObject( tuple );
         out.writeObject( workingMemory );
         out.writeObject( identityMap );
+	    out.writeObject( reasserted );
     }
 
     public void setActivation(final Activation agendaItem) {
@@ -103,8 +108,9 @@ public class DefaultKnowledgeHelper
         this.subrule = agendaItem.getSubRule();
         this.activation = agendaItem;
         // -- JBRULES-2558: logical inserts must be properly preserved
-        this.previousJustified = agendaItem.getLogicalDependencies();
-        agendaItem.setLogicalDependencies( null );
+	    //Ha. This hack doesn't work in case of recursive retractions.
+        //this.previousJustified = agendaItem.getLogicalDependencies();
+        //agendaItem.setLogicalDependencies( null );
         // -- JBRULES-2558: end
         this.tuple = agendaItem.getTuple();
     }
@@ -115,7 +121,7 @@ public class DefaultKnowledgeHelper
         this.activation = null;
         this.tuple = null;
         this.identityMap.clear();
-        this.previousJustified = null;
+        this.reasserted.clear();
     }
 
     public void insert(final Object object) throws FactException {
@@ -132,6 +138,7 @@ public class DefaultKnowledgeHelper
                                                        this.activation );
         this.getIdentityMap().put( object,
                                    handle );
+	    this.reasserted.put(object, handle);
     }
 
     public void insertLogical(final Object object) throws FactException {
@@ -141,39 +148,31 @@ public class DefaultKnowledgeHelper
 
     public void insertLogical(final Object object,
                               final boolean dynamic) throws FactException {
-        // iterate to find previous equal logical insertion
-        LogicalDependency dep = null;
-        if ( this.previousJustified != null ) {
-            for ( dep = (LogicalDependency) this.previousJustified.getFirst(); dep != null; dep = (LogicalDependency) dep.getNext() ) {
-                if ( object.equals( ((InternalFactHandle) dep.getFactHandle()).getObject() ) ) {
-                    this.previousJustified.remove( dep );
-                    break;
-                }
-            }
-        }
+		FactHandle handle = this.workingMemory.insert( object,
+													   dynamic,
+													   true,
+													   this.rule,
+													   this.activation );
 
-        if ( dep != null ) {
-            // Add the previous matching logical dependency back into the list
-            this.activation.addLogicalDependency( dep );
-        } else {
-            // no previous matching logical dependency, so create a new one
-            FactHandle handle = this.workingMemory.insert( object,
-                                                           dynamic,
-                                                           true,
-                                                           this.rule,
-                                                           this.activation );
-
-            this.getIdentityMap().put( object,
-                                       handle );
-        }
+		this.getIdentityMap().put( object,
+								   handle );
+
+		this.reasserted.put(object, handle);
     }
 
     public void cancelRemainingPreviousLogicalDependencies() {
-        if ( this.previousJustified != null ) {
-            for ( LogicalDependency dep = (LogicalDependency) this.previousJustified.getFirst(); dep != null; dep = (LogicalDependency) dep.getNext() ) {
-                this.workingMemory.getTruthMaintenanceSystem().removeLogicalDependency( activation, dep, activation.getPropagationContext() );
-            }
-        }
+	    // iterate to find previous equal logical insertion
+	    final LinkedList previousJustified=this.activation.getLogicalDependencies();
+	    final TruthMaintenanceSystem tms=this.workingMemory.getTruthMaintenanceSystem();
+	    if ( previousJustified != null ) {		    
+		    for (Iterator iter = previousJustified.javaUtilIterator(); iter.hasNext();) {
+			    LogicalDependency dep =(LogicalDependency) iter.next();
+			    final Object obj=((InternalFactHandle) dep.getFactHandle()).getObject();
+			    if (!reasserted.containsKey(obj))
+				    tms.removeLogicalDependency( activation, dep, activation.getPropagationContext() );
+
+		    }
+	    }
     }
 
     public void update(final FactHandle handle,
_______________________________________________
rules-dev mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/rules-dev

Reply via email to