NotesException: Object has been removed or recycled
A few days ago, a customer reported that one of our applications was not working properly and sent the associated logs.
It was very quickly clear under what conditions the error occurred. So it was reproducible, which is the first important step to troubleshooting.
Nevertheless, it took some time to locate the cause. Finally, I was able to find the “error”. To send it ahead. The “error” is not limited to a specific Domino version. The problem also occurs under Domino 9.0.1 FP10.
To illustrate the problem I wrote a small Java agent.
When we work with Java in the Domino environment, one of the best practices is to recycle Domino objects. We do this in countless places in our applications, and it hasn’t really caused a problem yet.
Not so in this particular case. Let’s take a look at the code of the agent.
import lotus.domino.*;
public class JavaAgent extends AgentBase {
Database db = null;
public void NotesMain() {
DocumentCollection col = null;
Document doc = null;
try {
Session session = getSession();
db = session.getCurrentDatabase();
col = db.getAllDocuments();
doc = db.getDocumentByUNID(col.getFirstDocument().getUniversalID());
if (null != doc) {
System.out.println("MAIN: " + doc.getItemValueString("Subject"));
foo(doc);
System.out.println("MAIN_2: " + doc.getItemValueString("Subject"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void foo(Document doc) {
try {
System.out.println("FOO: " + doc.getItemValueString("Subject"));
bar(doc.getUniversalID());
} catch (NotesException e) {
e.printStackTrace();
}
}
public void bar(String unid) {
Document doc2 = null;
try {
doc2 = db.getDocumentByUNID(unid);
System.out.println("BAR: " + doc2.getItemValueString("Subject"));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
doc2.recycle();
} catch (NotesException e) {
// fail silent
}
}
}
}
My test database contains a single document. The document has an item “Subject”.
In the MAIN method of the agent we fetch the document and get the UNID.
Now we get the document via this UNID and assign it to the LOCAL variable doc.
On the Domino console we display the content of the item Subject.
Then we branch to the method FOO, and pass the object doc as parameter.
Here, too, we display the contents of Subject.
Now we branch to another method BAR. Since the method is called from many places in the real application, and the document is not available everywhere, we pass the UNID and assign the document found via db.getDocumentByUNID to the LOCAL variable doc2.
Again, we display the contents of Subject. So far everything is OK. When leaving BAR, the LOCAL variable doc2 is recycled and we return to MAIN, where we again display the contents of the item Subject.
And exactly at this point we get an error message. (line 22)
AMgr: Start executing agent 'test' in 'java.nsf' Agent Manager: Agent printing: MAIN: I am a sampe document Agent Manager: Agent printing: FOO: I am a sampe document Agent Manager: Agent printing: BAR: I am a sampe document Agent Manager: Agent error: NotesException: Object has been removed or recycled Agent Manager: Agent error: at lotus.domino.local.NotesBase.CheckObject(Unknown Source) Agent Manager: Agent error: at lotus.domino.local.Document.getItemValueString(Unknown Source) Agent Manager: Agent error: at JavaAgent.NotesMain(JavaAgent.java:22) Agent Manager: Agent error: at lotus.domino.AgentBase.runNotes(Unknown Source) Agent Manager: Agent error: at lotus.domino.NotesThread.run(Unknown Source) AMgr: Agent 'test' in 'java.nsf' completed execution
If we remove the doc2.recycle() in the finally block of the BAR method, then the agent works as expected.
Looks like a db.getDocumentByUNID() references to the same cAPI backend Object and the object is discarded when it is recycled anywhere in the code flow, regardless if it is assigned to different LOCAL variables.
Not sure, if this is a BUG in Domino, or if it is considered as work as designed. Will open a case with HCL support.
I am totally baffled that no one has encountered this problem yet.
I have also always been under the (obviously) mistaken assumption that LOCAL variables are treated as such.