Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to recycle Domino objects in Java Beans

Tags:

xpages

I use a function to get access to a configuration document:

private Document lookupDoc(String key1) {
    try {
        Session sess = ExtLibUtil.getCurrentSession();
        Database wDb = sess.getDatabase(sess.getServerName(), this.dbname1);
        View wView = wDb.getView(this.viewname1);
        Document wDoc = wView.getDocumentByKey(key1, true);
        this.debug("Got a doc for key: [" + key1 + "]");
        return wDoc;
    } catch (NotesException ne) {
        if (this.DispLookupErrors)
            ne.printStackTrace();
        this.lastErrorMsg = ne.text;
        this.debug(this.lastErrorMsg, "error");
    }
    return null;
}

In another method I use this function to get the document:

Document wDoc = this.lookupDoc(key1);

if (wdoc != null) {
    // do things with the document
    wdoc.recycle();
}

Should I be recycling the Database and View objects when I recycle the Document object? Or should those be recycled before the function returns the Document?

like image 693
Newbs Avatar asked Jun 22 '12 15:06

Newbs


1 Answers

The best practice is to recycle all Domino objects during the scope within which they are created. However, recycling any object automatically recycles all objects "beneath" it. Hence, in your example method, you can't recycle wDb, because that would cause wDoc to be recycled as well, so you'd be returning a recycled Document handle.

So if you want to make sure that you're not leaking memory, it's best to recycle objects in reverse order (e.g., document first, then view, then database). This tends to require structuring your methods such that you do whatever you need to/with a Domino object inside whatever method obtains the handle on it.

For instance, I'm assuming the reason you defined a method to get a configuration document is so that you can pull the value of configuration settings from it. So, instead of a method to return the document, perhaps it would be better to define a method to return an item value:

private Object lookupItemValue(String configKey, itemName) {
    Object result = null;
    Database wDb = null;
    View wView = null;
    Document wDoc = null;
    try {
        Session sess = ExtLibUtil.getCurrentSession();
        wDb = sess.getDatabase(sess.getServerName(), this.dbname1);
        wView = wDb.getView(this.viewname1);
        wDoc = wView.getDocumentByKey(configKey, true);
        this.debug("Got a doc for key: [" + configKey + "]");
        result = wDoc.getItemValue(itemName);
    } catch (NotesException ne) {
        if (this.DispLookupErrors)
            ne.printStackTrace();
        this.lastErrorMsg = ne.text;
        this.debug(this.lastErrorMsg, "error");
    } finally {
        incinerate(wDoc, wView, wDb);
    }
    return result;
}

There are a few things about the above that merit an explanation:

  • Normally in Java, we declare variables at first use, not Table of Contents style. But with Domino objects, it's best to revert to TOC so that, whether or not an exception was thrown, we can try to recycle them when we're done... hence the use of finally.
  • The return Object (which should be an item value, not the document itself) is also declared in the TOC, so we can return that Object at the end of the method - again, whether or not an exception was encountered (if there was an exception, presumably it will still be null).
  • This example calls a utility method that allows us to pass all Domino objects to a single method call for recycling.

Here's the code of that utility method:

private void incinerate(Object... dominoObjects) {
    for (Object dominoObject : dominoObjects) {
        if (null != dominoObject) {
            if (dominoObject instanceof Base) {
                try {
                    ((Base)dominoObject).recycle();
                } catch (NotesException recycleSucks) {
                    // optionally log exception
                }
            }
        }
    }
}

It's private, as I'm assuming you'll just define it in the same bean, but lately I tend to define this as a public static method of a Util class, allowing me to follow this same pattern from pretty much anywhere.

One final note: if you'll be retrieving numerous item values from a config document, obviously it would be expensive to establish a new database, view, and document handle for every item value you want to return. So I'd recommend overriding this method to accept a List<String> (or String[ ]) of item names and return a Map<String, Object> of the resulting values. That way you can establish a single handle for the database, view, and document, retrieve all the values you need, then recycle the Domino objects before actually making use of the item values returned.

like image 129
Tim Tripcony Avatar answered Nov 09 '22 10:11

Tim Tripcony