The structure prior to my recent work was one-dimensional.
As part of the development for XPages OpenLog Logger, I made all the methods of the OpenLogItem class static. The reasoning was so that developers didn’t need to create an OpenLogItem object before calling any method, like logError(). So instead of:
OpenLogItem oli_ = new OpenLogItem();
oli_.logError(new Throwable("An Error"));
developers could just write:
OpenLogItem.logError(new Throwable("An Error"));
OpenLogPhaseListener then picked up instances of OpenLogErrorHolder and wrote out the SSJS errors using OpenLogItem.logError() or OpenLogItem.logEvent(). In org.openntf.domino.logging, however, I had to create a modified OpenLogItem class without XPage-related functionality and wanted to use the org.openntf.domino classes instead of the lotus.domino classes. This OpenLogItem class did not have static methods. Instead the OpenLogHandler class created an instance of OpenLogItem and called the logError() method.
New Structure
When I came to incorporate XPages OpenLog Logger into OpenNTF Domino API, I needed to add the OpenLogPhaseListener, OpenLogErrorHolder and OpenLogItem classes into the org.openntf.domino.xsp plugin. That’s because the org.openntf.domino plugin doesn’t have access to any XPage classes. If it did, it would fail in contexts that don’t have access to the XPages runtime, like Java agents. So the org.openntf.domino.xsp plugin adds in all the XPage-related functionality for the project, like SSJS integration.
I didn’t want to have two separate classes for OpenLogItem, because that would be inefficient and an overhead to future development. So the org.openntf.domino.xsp version needed to extend the org.openntf.domino.logging.OpenLogItem class. But you can’t extend methods from one class and make them static in another. So a different approach was required, shown below:
org.openntf.domino logging.OpenLogItem is no more. Instead, there is an interface IOpenLogItem that lists all methods that must be implemented, along with their parameters. This is implemented by BaseOpenLogItem, which has all the methods standard to XPages and non-XPages uses. BaseOpenLogItem is then extended by DominoOpenLogItem (although there’s nothing specific in that class), and it is DominoOpenLogItem that is now used by org.openntf.domino.logging.OpenLogHandler. One other amendment here is using enums for LogType and DebugLevel, both of which are stored in the IOpenLogItem interface. These are both standard Java approaches I’ve learned through my involvement in the OpenNTF Domino API, so I’ll cover them in more detail in another post.
For the XPages usage, BaseOpenLogItem is extended by XspOpenLogItem. This has some additional and overridden methods. XspOpenLogUtil then creates an instance of XspOpenLogItem, as well as providing abstract versions of the various logError() and logEvent() methods. So when moving from XPages OpenLog Logger, you just need to change OpenLogItem.logError() to XspOpenLogUtil.logError() etc. For easy access to the OpenLogItem there is also a static method getXspOpenLogItem(), so XspOpenLogUtil.getXspOpenLogItem() will give access to any other methods like addFacesMessage(), setLogDbName() etc. So migrating an application should be a relatively quick process while keeping an easily extensible class structure.