One of the great things about XPages is that you can extend your skill-set as you become more confident. You can build a powerful application without needing to write your own stylesheet or use a theme or use Java. But as and when you want to push the boundaries of your knowledge further, you can start to experiment with them. It’s a lessopn which reminds me of when I first started with Domino. When I built my first application I had no knowledge of LotusScript or object-oriented programming, so everything is done with formula language. Nonetheless it was quite sophisticated in its functionality and was still being used when I last heard about it, some eight years after I built it. XPages is the same.
So now, after getting to grips with many areas of XPages, after a little experience of Java with plug-in development and some pain with debugging SSJS in more sophisticated applications, I have started to experiment with Java. I’ve used Java objects and Java classes in XPages applications before but nonetheless, as with XPages, I expected some pain and some frustrations. I wasn’t disappointed.
One of the big frustrations I had was with a line of code managing a profile document. The code was trying to re-acquire the profile document after it had been updated. The code was straightforward:
ProfileDoc = currDb.getDocumentByUNID(profileUNID)
This was in a Java bean scoped to the application. currDb was defined as a private Database object and mapped to the current database at the top of the class. profileUNID was a public String mapped to a UNID which had been written onto the profile document, so it was definitely a valid UNID. ProfileDoc was a private Document object declared at the top of the class. Because I wanted to make sure I got the up-to-date NotesDocument, the line immediately before was calling ProfileDoc.recycle().
The outcome of my code was an error “Object has been removed or recycled”. It is said that you don’t appreciate what you have until you have lost it. And since working with SSJS and Java my admiration and appreciation of the developers who wrote LotusScript has greatly increased. In LotusScript we would have a simple error number that would clearly identify which object was causing the problem. Not so with Java.
So I fell back on logical diagnosis. I added debugging to write out curDb.getTitle() to make sure that had not been recycled. I added debugging to write out profileUNID, to ensure that had not got cleared. I added debugging to make sure it was not a variable related to my OpenLog code that was being removed or recycled. All tests were passed. The logical conclusion was that for some reason I could not re-initialise ProfileDoc. So that was the focus of my attention, for the next four hours, to try to work out why I could not re-initialise ProfileDoc and find some workaround.
What I eventually found, thanks to a comment from Nathan Freeman, was that the logical conclusion I made was flawed. Because the test was based on a premise that made logical sense, but did not take into account that code is not written by a computer, but by humans and therefore may not be logical. Whenever Java recycles an object it can still hold some properties in a cached memory and one of those is the database title. So currDb.getTitle() returned a value from the cached memory, even though currDb had actually been recycled. The same is true of Document objects and others. Nor is there a clean way to do a boolean check that an object has not been recycled. In my case, I’ve just reinitialised currDb in each of the functions using it. But in other places I will probably try to get a child object (so a view from a Database or a NotesItem from a Document) and catch the error it throws if the object has been recycled.
This is one of those object lessons that I will never remove from my memory!
- Comments 
This situation certainly underscores the need for an .isRecycled() method in the Java API. Using try/catch blocks to try to guess is just insanity.
Normal crazy recycle rules apply, with the added complexity of xpages scoping:)
Under some circumstances you will get already recycled object due to error in Domino code… Promised to fix in 8.5.3 by IBM, but I can’t find provided SPR# in r5fixlist.nsf.