-
Notifications
You must be signed in to change notification settings - Fork 34
Logging the Java Way
One of the key aims of this project was to implement standardised logging. That proved more challenging than anticipated.
With the core Java API, if you use a Domino object you need to catch or throw a NotesException. There is nothing in the API to handle logging of those errors. There are a number of loggers implemented by the various packages, but nothing to easily utilise those loggers. So invariably some custom logging needs to be implemented. That may be OpenLog, it may be some implementation of lotus.domino.Log, or it may be as simple as System.out.println(). But either way, there's work that is still needed.
But Java has some standard logging contructs. The base Java API has java.util.logging and there are extensions like log4j. To avoid dependencies we chose java.util.logging as our template. A JVM has a LogManager, which holds a number of Loggers. A specific Logger can have one or more LogHandlers which hold various settings that define how, where and whether to log from a LogRecord. Formatters can be used to format the content of a LogRecord as a String, for use by a LogHandler.
A Logger can be instantiated as required, handlers added or loaded from a configuration file, the logging level (java.util.logging.Level) can be modified as required. All in a way that is standard for Java.
It is. It should mean any exceptions from our package can be logged in a standard way. It should mean you can pass exceptions to our error handling using DominoUtils.handleException(Exception). It should mean you can modify the logging levels or locations as required. It should mean you can instantiate your own Loggers using the LogHandlers we set up - for the console, for a file, for OpenLog, for lotus.domino.Log, for Mark Leusink's Debug Toolbar, for anything else that may be of use. It should mean you can use a standard formatter across all your logging. Should.
If you've tried adding certain Java packages that have inbuilt logging in this manner to XPages, you'll know they have to be in the WebContent\WEB-INF\lib folder. Otherwise it throws a NoClassDefFoundError exception. Your class can be found. It's just that it tries to do logging, doesn't have authority, so can't initialise the class. One option is to modify the java.policy to open up access. But that's not an option in most environments. Adding it to the lib folder uses a different ClassLoader, which does have access.
Unfortunately, one of the other restrictions of the java.policy is doing anything around adding Loggers, applying LogHandlers, changing logging levels etc. So much so that the XPages Toolbox project not only requires changes to the java.policy to allow it to change logging levels, but uses Java reflection to load a different class which has a static method to change logging levels. But that's all it has. And you can't call that class's method unless you make a change to the Java policy for the application the call is being made from. Stepping through the code finds that any attempt to add a Logger or anything else that's restricted throws an AccessControlException.
So it can't be used from XPages and probably not from OSGi plugins and possibly some other options. Yet. We live in hope of finding a solution. It's just not in time for the M1 release. So in the meantime, DominoUtils.handleException checks whether it has access to change logging levels and, if not, uses the com.ibm.xsp.domino Logger, which logs to the console and the IBM_TECHNICAL_SUPPORT folder. (The initial release of M1 has a bug in it - line 62 should read private final static Logger logBackup_ = Logger.getLogger("com.ibm.xsp.domino");
In the future we hope to find some way to allow you to add Loggers, take advantage of the LogHandlers we create, modify the logging defaults, and basically make it quicker and easier to implement flexible logging. So be patient. With the bright minds we have on board, plus the wealth of experience of our readers, I'm sure we'll get there.