Hey,
I recently upgraded drools from 5.5.0.Final to 6.0.0.CR3
A rule deletion that used to work now throws a NullPointerException.
A fact has to be inserted for the Exception to be thrown.
Here is the log :

[main] INFO org.drools.compiler.kie.builder.impl.KieRepositoryImpl - KieModule was added:MemoryKieModule[ ReleaseId=org.default:artifact:1.0.0-SNAPSHOT]
objectInserted org.test.ProximityTest$Track@2c6c5356
[Rule name=ProxRule, agendaGroup=MAIN, salience=0, no-loop=false]
Exception in thread "main" java.lang.NullPointerException
at org.drools.core.phreak.AddRemoveRule.deletePeerLeftTuple(AddRemoveRule.java:687)
at org.drools.core.phreak.AddRemoveRule.followPeer(AddRemoveRule.java:659)
at org.drools.core.phreak.AddRemoveRule.processLeftTuples(AddRemoveRule.java:620)
at org.drools.core.phreak.AddRemoveRule.flushStagedTuples(AddRemoveRule.java:243)
at org.drools.core.phreak.AddRemoveRule.removeRule(AddRemoveRule.java:134)
at org.drools.core.reteoo.ReteooBuilder.removeRule(ReteooBuilder.java:172)
at org.drools.core.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:1402)
at org.drools.core.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:1393)
at org.drools.core.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:1371)
at org.drools.core.impl.KnowledgeBaseImpl.removeRule(KnowledgeBaseImpl.java:210)
at org.test.ProximityTest.CreateKieRuleOnTheFly(ProximityTest.java:72)
at org.test.ProximityTest.main(ProximityTest.java:102)

Here is a code sample that reproduces the issue :


package org.test;
import java.util.ArrayList;
import java.util.List;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message.Level;
import org.kie.api.definition.rule.Rule;
import org.kie.api.event.rule.ObjectDeletedEvent;
import org.kie.api.event.rule.ObjectInsertedEvent;
import org.kie.api.event.rule.ObjectUpdatedEvent;
import org.kie.api.event.rule.WorkingMemoryEventListener;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class ProximityTest {
private void CreateKieRuleOnTheFly() {
KieServices ks = KieServices.Factory.get();
KieRepository kr = ks.getRepository();
KieFileSystem kfs = ks.newKieFileSystem();
// Can't understand why this does not work without the
// src/main/resources part
kfs.write("src/main/resources/org/test/rule.drl", getRule());
KieBuilder kb = ks.newKieBuilder(kfs);
kb.buildAll(); 
if (kb.getResults().hasMessages(Level.ERROR)) {
throw new RuntimeException("Build Errors:\n"
+ kb.getResults().toString());
}
KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
KieSession kSession = kContainer.newKieSession();
kSession.addEventListener(new WorkingMemoryEventListener() {
@Override
public void objectUpdated(ObjectUpdatedEvent oue) {
System.out.println("objectUpdated " + oue.getObject());
}
@Override
public void objectInserted(ObjectInsertedEvent oi) {
System.out.println("objectInserted " + oi.getObject());
}
@Override
public void objectDeleted(ObjectDeletedEvent ore) {
System.out.println("objectRetracted " + ore.getOldObject());
}
});
// CloseTrack closeTrack = new CloseTrack(100,200);
Track track = new Track(100);
// track.getCloseTracks().add(closeTrack);
// kSession.insert(track);
// track = new Track(200);
kSession.insert(track);
kSession.fireAllRules();
KieBase kieBase = kSession.getKieBase();
Rule rule = kieBase.getRule("org.test", "ProxRule");
System.out.println(rule);
kieBase.removeRule("org.test", "ProxRule");
System.out.println("done");
}
private static String getRule() {
String s = ""
+ "package org.test"
+ "\nimport org.test.ProximityTest.*"
+ "\nrule \"ProxRule\""
+ "\nwhen "
+ "\n $track:Track("
+ "\n )"
+ "\n $track1:Track("
+ "\n )"
+ "\n exists (CloseTrack(closeTrackId==$track1.trackId) from $track.closeTracks)"
+ "\nthen " + "\nSystem.out.println(\"proximity asserted\"); "
+ "\nend";
return s;
}
/** test main */
public static void main(String[] args) {
(new ProximityTest()).CreateKieRuleOnTheFly();
}
public class CloseTrack {
private int trackId;
private int closeTrackId;
public CloseTrack(int i, int j) {
this.trackId = i;
this.closeTrackId = j;
}
public int getTrackId() {
return trackId;
}
public void setTrackId(int trackId) {
this.trackId = trackId;
}
public int getCloseTrackId() {
return closeTrackId;
}
public void setCloseTrackId(int closeTrackId) {
this.closeTrackId = closeTrackId;
}
}
public class Track {
private int trackId;
private List<CloseTrack> closeTracks = new ArrayList<CloseTrack>();
public Track(int i) {
this.trackId = i;
}
public List<CloseTrack> getCloseTracks() {
return closeTracks;
}
public int getTrackId() {
return trackId;
}
public void setTrackId(int id) {
this.trackId = id;
}
public void setCloseTracks(List<CloseTrack> closeTracks) {
this.closeTracks = closeTracks;
}
}
}

Hope this helps.
Thanks.

--
N.