Late last night I released the XPages OpenLog Logger project on OpenNTF. There have been options for logging to OpenLog from XPages for some time – Matt White’s OpenLogXPages SSJS library from TaskJam and the OpenLogItem class I included in XPages Help Application. So why did I bother with this?
Firstly, if you think this is just an aggregation of previous code, think again. The Java implementation has three main changes:
- I was frustrated with having to create an OpenLogItem in each class or in a central utils class. So all methods are now static. So now I just call OpenLogItem.logError() instead of calling a getOpenLogItem() method from some intermediate class to get an instance of OpenLogItem, and then calling logError(). Note to self: must get round to changing my Java templates in Designer’s preferences!
- The log path was hard-coded in the script, so I never went beyond the default. But a few weeks ago I was introduced (or re-introduced probably) to the code to access the xsp.properties. So the location of the log path has been extracted to xsp.properties, with a fall-back to the notes.ini, and a final fall-back to “OpenLog.nsf”. The same has been provided for debugLevel, for backup error handling if the OpenLog database is not available.
- The third change was to provide it as an OSGi plugin, so it doesn’t need copying and pasting into every database.
But the most significant reason I did this work was not specifically for me (although I’ll still use it). Through our mentoring package and at conferences I speak to a lot of newer XPages developers and I’m conscious of a number of challenges around SSJS development.
- I don’t have a problem using OpenLogXPages SSJS library – the demo video below shows I make extensive use of it. But I’m conscious it’s not Apache-licensed, which can be a problem for some companies. This SSJS implementation had to be.
- Custom error pages have a gotcha when triggered from a partial refresh. So for less experienced developers, this application not only explains that but also provides a sample error page.
- OpenLogXPages was an SSJS script library. They don’t perform well. Also, you don’t get all the information about the error. I wanted to provide more, both for myself when using SSJS and also for others.
- Using it from SSJS had to be quick and flexible, because code templating is not available in SSJS. So when I write SSJS, I have to type in my try/catch block, I need to remember the syntax for logging an error. I didn’t want to have to import the Java package, so I needed a bean. So this has addError() and addEvent() methods with a flexible list of parameters. The slight gotcha is that with addError() if you want to add a custom message, it is inserted as the second parameter. That’s to avoid conflicts in methods, because the last parameter is also a String.
- I wanted the logging from SSJS to avoid logging the same event / error multiple times. That occurs because of the JSF lifecycle, but can confuse (as well as clogging up OpenLog). The SSJS implementation handles all that.
- I didn’t want to provide just a JavaDoc. As a developer coming from a Domino background, they often frustrate me because they give a parameter type (e.g. String or int), but don’t document what is expected. The application has detailed documentation on calling from SSJS or Java, with the methods available and examples. As ever, there are little easter eggs, like explaining how you can use this and this.getParent() to avoid hard-coding.
- I wanted to give a video of how to implement it, whether the code resides in the NSF or in an OSGi plugin. Neither is particularly scary, but many developers may not have done this.
- I wanted to show it’s not a huge task to refactor existing applications, also showing the Search and Replace functionality in Designer, for those who are not aware of its flexibility. That’s in this video.
One aspect I’m undecided on at the moment is whether to extend the Java code to have addJavaErrors() and addJavaEvents() methods. It would require another managed bean, so you would have to call that from Java. The benefit it would give is that duplicate errors and events from Java would also be suppressed. I would welcome feedback on that.
Any other suggestions for enhancements are also welcome.