The logging of text messages to a console or line printer is among the oldest of debugging practices. So you'd expect that even in a relatively new language such as Java, the technique of logging debugging messages would be perfected. Indeed, many solutions exist, from basic System.out.println methods to log4j to Sun’s JDK Logging API, which was introduced in Java 1.4. But until one logging system gains dominance, writing portable code that includes logging statements poses a bit of a problem. The Commons Logging project fixes that problem.
An introduction to Commons Logging
Commons Logging is a subproject of the Jakarta project, which is in turn a subproject under the Apache name. The Jakarta project’s goal is to produce reusable code suitable for inclusion in third-party applications. With this mandate and the multitude of incompatible logging solutions deployed, Jakarta developers had two choices when it came to logging. They could select one solution and thus produce code that requires any applications that include it to select the same logging package Jakarta did. Or they could not use logging statements at all and lose myriad benefits, ranging from ease of debugging to self-documenting code. Not happy with either solution, the Jakarta developers began the Commons Logging project.
The Commons Logging project is not another logging solution—there are plenty of those. Instead, it’s a lightweight abstraction layer that intelligently wraps whatever logging system is available. Whenever a message logging call is made, it’s routed to the underlying logging system. The end result is code that’s portable to any log system in common use.
Deploying Commons Logging
Using the Commons Logging system requires almost no new code and will look familiar to anyone who has used log4j or the JDK Logging API. The small commons-logging.jar archive must be placed in the calling application's CLASSPATH. Listing A shows the minimum logging code necessary to log a text statement. The first two lines are simply imports for the required Commons Logging classes.
The statement commented Line A requests an instance of the Log class from the static LogFactory. This Log instance is simply a delegating wrapper around whatever logging package the LogFactory selected. The getLog static method on the LogFactory takes a single parameter that can be a String or a Class. This parameter specifies the logging category if that concept is supported by the underlying logging system. The statement commented Line B simply tells the Log object to delegate a logging request. In addition to the debug level of severity, info, warn, error, and fatal levels exist. These are mapped as closely as possible to whatever severity levels are supported by the underlying logging system.
Along with logging simple text messages, the Log class allows for the logging of Exception objects and for querying the current severity threshold of the underlying logging system. Exception objects can be passed to the debug, info, warn, error, and fatal methods as an optional second parameter in a fashion familiar to anyone who has used log4j or the JDK Logging API. Checking the current severity threshold is done using the isXxxxxxEnabled methods that exist for each of the five supported severity levels. Their use is purely for optimization purposes.
The Commons Logging layer represents a least common denominator approach to logging. It does not support all the features offered by the various logging systems it encapsulates. Instead, it provides uniform access to the features common across most of the systems to which it can delegate. Those familiar with the log4j system will notice the absence of both nested diagnostic contexts and the general ObjectRenderer system for logging objects directly.
Also missing from the Commons Logging system is any mechanism for configuring the various underlying logging systems. Even adjustments so basic as setting the logging threshold are impossible. The reason for this is clear when you consider both the wide variety of configuration schemes used by each of the possible logging backends and the goal of Commons Logging. The Commons Logging project exists to provide logging functionality for modular code to be included in other code projects. Configuring the logging system is best handled by the application doing the including, not by the module using the Commons Logging system.
Configuring Commons Logging
While the Commons Logging system doesn’t provide any way to configure the underlying logging system, it does provide a way to select the system that logging requests will be delegated to. The LogFactory class makes that decision. The default LogFactory implementation provides many ways to specify which underlying logging system should be used. The first step is to look for a system property named org.apache.commons.logging.Log whose value, if present, is taken as the name of the Class to be instantiated. The single category parameter to the getLog method is passed as a String to the constructor of the specified class.
If the org.apache.commons.logging.Log property is not found or does not have a valid class name as its value, the log4j logging system is used, if available. If the log4j classes are unavailable, the JDK Logging API is used, if present. If neither of those systems is available, log messages are silently discarded without error. You can route messages to standard output by setting the org.apache.commons.logging.Log property to com.apache.commons.logging.impl.SimpleLog. If greater flexibility in the creation of Log instances is required, you can even replace the default LogFactory implementation with a custom LogFactory by setting the org.apache.commons.logging.LogFactory system property to the class name of the desired custom implementation.
When to use it
The Commons Logging project’s goal was not to build a one-size-fits-all logging package but rather to provide a logging package that does not force surrounding code to use one logging package or another. Is it the right choice for end-user applications and servlets? Probably not. They might benefit from some of the special features provided by logging systems that don’t fit within the Commons Logging project's least common denominator worldview. Is Commons Logging a good pick for reusable libraries and companywide utility code? Almost certainly.