Recycle, recycle, recycle

Yesterday I stumbled upon a behavior which directed me – once again – to the most important point in Notes/Domino Java develoment. Recycling!

As you probably know recycling is special to Notes/Domino Java development. It frees the handle on the backend C element. If you don’t recycle you’ll have “ghost” objects in your Java environment. That’s bad. It may cost you memory. And…it may lead to wrong results. If you’re doing “classic” development like in agents you probably won’t run into this situation.

The start:
Assume you’ve a very long running mechanism, like an agent or a DOTS (Domino OSGi Tasklet Service) tasklet, which uses NotesDocuments and/or ViewEntries. And assume you want to re-use those documents. Here is a very simple sample script.

...
ViewEntry vweCheck = ViewEntryCollection.getFirstDocument();
ViewEntry vweCheckTemp = null;

while (vweCheck!=null) {
   System.out.println(vweCheck.getDocument().getItemValueString("myField1"));
   vweCheckTemp = vweCheck.getNextEntry(vweCheck);
   vweCheck.recycle();
   vweCheck = vweCheckTemp;
}
...

What’s happening here? It’s iterating over a view entry collection and prints a field to the console. Nothing special, eh? Now let’s change the script a little bit.

...
ViewEntry vweCheck = null;
ViewEntry vweCheckTemp = null;
for (int i=0;i<2;i++) {
   while (vweCheck!=null) {
      System.out.println(vweCheck.getDocument().getItemValueString("myField1"));
      vweCheckTemp = vweCheck.getNextEntry(vweCheck);
      vweCheck.recycle();
      vweCheck = vweCheckTemp;
   }
   Thread.sleep(30000);
}

That’ll print the same view entry collection two times – after a delay of 30 seconds – to the console. Same content? Probably.

The problem is that vweCheck.getDocument() creates a backend handle to the Notes document. If you access at a later point, i. e. after the .sleep(), vweCheck.getDocument() again you ARE NOT getting the new handle but the “old” (==cached) handle. That means you are not having access to the most current data. Even if you think you have.

The solution is to recycle the document. Here is the correct code.

...
ViewEntry vweCheck = null;
ViewEntry vweCheckTemp = null;
for (int i=0;i<2;i++) {
   while (vweCheck!=null) {
      System.out.println(vweCheck.getDocument().getItemValueString("myField1"));
      vweCheckTemp = vweCheck.getNextEntry(vweCheck);
      vweCheck.getDocument().recycle();
      vweCheck.recycle();
      vweCheck = vweCheckTemp;
   }
   Thread.sleep(30000);
}
...

As said: you normally won’t run into this kind of problem. Agents run once and kill the NotesSession then. That’s fine. If you’re digging into “the neat stuff” like creating endless running mechanisms with DOTS and are using persistency mechanisms for your Notes objects this is mission critical.

Also thanks to Nathan, Karsten, Serdar, Sjaak and Bernd for discussing the topic offline with me.