The Carbon Java Framework  

Logging with Apache Commons Logging

Configuration Service Design

Printer Friendly Version

Author: Akash Tayal (atayal at sapient.com)
Version: $Revision: 1.2 $($Author: atayal $ / $Date: 2003/04/02 07:19:09 $)
Created: January 2002

Introduction

This package provides an API for logging in server-based applications that can be used around a variety of different logging implementations, including prebuilt support for the following:

  • Log4J from Apache's Jakarta project. Each named Log instance is connected to a corresponding Log4J Category.
  • JDK Logging API , included in JDK 1.4 or later systems. Each named Log instance is connected to a corresponding java.util.logging.Logger instance.
  • LogKit from Apache's Jakarta project. Each named Log instance is connected to a corresponding LogKit Logger.
  • NoOpLog implementation that simply swallows all log output, for all named Log instances.
  • SimpleLog implementation that writes all log output, for all named Log instances, to System.out.

Configuring the Commons Logging Package

Choosing A LogFactory Implementation

From an application perspective, the first requirement is to retrieve an object reference to the LogFactory instance that will be used to create Log instances for this application. This is normally accomplished by calling the static getFactory() method. This method implements the following discovery algorithm to select the name of the LogFactory implementation class this application wants to use:

  • Check for a system property named org.apache.commons.logging.LogFactory.
  • Use the JDK 1.3 JAR Services Discovery mechanism (see http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html for more information) to look for a resource named META-INF/services/org.apache.commons.logging.LogFactory whose first line is assumed to contain the desired class name.
  • Look for a properties file named commons-logging.properties visible in the application class path, with a property named org.apache.commons.logging.LogFactory defining the desired implementation class name.
  • Fall back to a default implementation, which is described further below.

If a commons-logging.properties file is found, all of the properties defined there are also used to set configuration attributes on the instantiated LogFactory instance.

Once an implementation class name is selected, the corresponding class is loaded from the current Thread context class loader (if there is one), or from the class loader that loaded the LogFactory class itself otherwise. This allows a copy of commons-logging.jar to be shared in a multiple class loader environment (such as a servlet container), but still allow each web application to provide its own LogFactory implementation, if it so desires. An instance of this class will then be created.

The Default LogFactory Implementation

The Logging Package APIs include a default LogFactory implementation class ( org.apache.commons.logging.impl.LogFactoryImpl) that is selected if no other implementation class name can be discovered. Its primary purpose is to create (as necessary) and return Log instances in response to calls to the getInstance() method. The default implementation uses the following rules:

  • At most one Log instance of the same name will be created. Subsequent getInstance() calls to the same LogFactory instance, with the same name or Class parameter, will return the same Log instance.
  • When a new Log instance must be created, the default LogFactory implementation uses the following discovery process is used:
    • Look for a system property named org.apache.commons.logging.Log (for backwards compatibility to pre-1.0 versions of this API, a system property org.apache.commons.logging.log is also consulted).
    • Look for a configuration attribute of this factory named org.apache.commons.logging.Log.
    • If the Log4J logging system is available in the application class path, use the corresponding wrapper class ( Log4JCategoryLog).
    • If the application is executing on a JDK 1.4 system, use the corresponding wrapper class ( Jdk14Logger).
    • Fall back to the default no-output logging wrapper ( NoOpLog).
  • Load the class of the specified name from the thread context class loader (if any), or from the class loader that loaded the LogFactory class otherwise.
  • Instantiate an instance of the selected Log implementation class, passing the specified name as the single argument to its constructor.

If you wish to receive logging output to System.out, but have not installed one of the three supported logging packages, a simple Log implementation named SimpleLog is available. You can select it, based on the above rules, by including a system property definition on the command line that starts your application:

    java \
      -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog \
      MyApplication

See the SimpleLog JavaDocs for detailed configuration information for this implementation.

Configuring the Underlying Logging System

The basic principle is that the user is totally responsible for the configuration of the underlying logging system. Commons-logging should not change the existing configuration.

Each individual Log implementation may support its own configuration properties. These will be documented in the class descriptions for the corresponding implementation class.

Some Log implementations (such as the one for Log4J) require an external configuration file for the entire logging environment. This file should be prepared in a manner that is specific to the actual logging technology being used.

Configuration of the behavior of the JCL ultimately depends upon the logging toolkit being used. The JCL SPI uses Log4J by default if it is available (in the CLASSPATH).

Log4J

As Log4J is the default logger, a few details are presented herein to get the developer/integrator going. Configure Log4J using system properties and/or a properties file:

  • log4j.configuration=log4j.properties
  • Use this system property to specify the name of a Log4J configuration file. If not specified, the default configuration file is log4j.properties.
     
  • log4j.rootCategory=priority [, appender]*
  • Set the default (root) logger priority.
     
  • log4j.logger.logger.name=priority
  • Set the priority for the named logger and all loggers hierarchically lower than, or below, the named logger. logger.name corresponds to the parameter of LogFactory.getLog(logger.name), used to create the logger instance. Priorities are: DEBUG, INFO, WARN, ERROR, or FATAL. Log4J understands hierarchical names, enabling control by package or high-level qualifiers: log4j.logger.org.apache.component=DEBUG will enable debug messages for all classes in both org.apache.component and org.apache.component.sub. Likewise, setting log4j.logger.org.apache.component=DEBUG will enable debug message for all 'component' classes, but not for other Jakarta projects.
     
  • log4j.appender.appender.Threshold=priority
  • Log4J appenders correspond to different output devices: console, files, sockets, and others. If appender's threshold is less than or equal to the message priority then the message is written by that appender. This allows different levels of detail to be appear at different log destinations. For example: one can capture DEBUG (and higher) level information in a logfile, while limiting console output to INFO (and higher).

Integration

The minimum requirement to integrate with another logger is to provide an implementation of the org.apache.commons.logging.Log interface. In addition, an implementation of the org.apache.commons.logging.LogFactory interface can be provided to meet specific requirements for connecting to, or instantiating, a logger.

  • org.apache.commons.logging.Log

  • The default LogFactory provided by JCL can be configured to instantiate a specific implementation of the org.apache.commons.logging.LogFactory interface by setting the property of the same name (org.apache.commons.logging.LogFactory). This property can be specified as a system property, or in the commons-logging.properties file, which must exist in the CLASSPATH.

    Default logger if not plugged

    The Jakarta Commons Logging SPI uses the implementation of the org.apache.commons.logging.LogFactory interface specified by the system property org.apache.commons.logging.LogFactory. If the property is not specified or the class is not available then the JCL provides access to a default logging toolkit by searching the CLASSPATH for the following toolkits, in order of preference:

    • Log4J
    • JDK 1.4
    • JCL SimpleLog

  • org.apache.commons.logging.LogFactory

  • If desired, the default implementation of the org.apache.commons.logging.LogFactory interface can be overridden, allowing the JDK 1.3 Service Provider discovery process to locate and create a LogFactory specific to the needs of the application. Review the Javadoc for the LogFactoryImpl.java for details.

Mechanism

  • Life cycle
  • The JCL LogFactory implementation must assume responsibility for either connecting/disconnecting to a logging toolkit, or instantiating/initializing/destroying a logging toolkit.
     
  • Exception handling
  • The JCL Log interface doesn't specify any exceptions to be handled, the implementation must catch any exceptions.
     
  • Multiple threads
  • The JCL Log and LogFactory implementations must ensure that any synchronization required by the logging toolkit is met.

Reference

For details please visit the Jakarta commons project .

Credits

This documenation is prepared using the user guide and documentation available on Jakarta Commons Project.


Copyright © 2001-2003, Sapient Corporation