Java Commons Logging Integration

The logging output can also be redirected to commons-logging:

Logging.ALL.setLoggerFactory("org.geotools.util.logging.CommonsLoggerFactory");

This requires:

<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>

Commons logging has slightly different concept of levels, using method calls to check if a level is enabled:

Java Level

Commons-Logging

OFF

FATAL

isFatalEnabled()

SEVERE

isErrorEnabled()

WARNING

isWarnEnabled()

INFO

isInfoEnabled()

CONFIG

FINE

isDebugEnabled()

FINER

FINEST

isTraceEnabled()

ALL

Because commons logging is so simple, and the commons logging API is often available as a transitive dependency required by components that use it, or implemented directly as part of Log4J, Logback or the spring-framework:

  • If you have configured CommonsLoggerFactory above, and it detects that commons logging is setup to directly use Jdk14Logger (which directly calls the java util logging api) it will act as a no-operation returning null to indicate java Logger is to be used directly.

  • A similar check is performed by GeoTools.init(), it checks with CommonsLoggerFactory and will change to DefaultLoggerFactory if commons logging is setup to use Jdk14Logger.

  • These steps are taken to avoid forcing your code to be limited by the minimal set of levels above.

Reference:

Commons Logging Integration

The following example is taken from our integration testing, this test has no additional libraries in play so GeoTools.init() defaults to direct use of Java Logger implementation.

  1. Setup pom.xml with dependencies on geotools:

    <project
      xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>org.geotools.tutorial</groupId>
      <artifactId>commons</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
      <name>GeoTools Commons Integration Example</name>
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.deploy.skip>true</maven.deploy.skip>
        <geotools.version>28-SNAPSHOT</geotools.version>
        <logback.version>1.2.11</logback.version>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-metadata</artifactId>
          <version>${geotools.version}</version>
        </dependency>
        <dependency>
          <groupId>org.geotools.ogc</groupId>
          <artifactId>net.opengis.ows</artifactId>
          <version>${geotools.version}</version>
        </dependency>
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
        </dependency>
      </dependencies>
      <repositories>
        <repository>
          <id>osgeo</id>
          <name>OSGeo Release Repository</name>
          <url>https://repo.osgeo.org/repository/release/</url>
          <snapshots><enabled>false</enabled></snapshots>
          <releases><enabled>true</enabled></releases>
        </repository>
        <repository>
          <id>osgeo-snapshot</id>
          <name>OSGeo Snapshot Repository</name>
          <url>https://repo.osgeo.org/repository/snapshot/</url>
          <snapshots><enabled>true</enabled></snapshots>
          <releases><enabled>false</enabled></releases>
        </repository>
      </repositories>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
              <executable>java</executable>
              <arguments>
                <argument>-classpath</argument>
                <!-- uses dependencies and build directory -->
                <classpath/>
                <argument>-Djava.awt.headless=true</argument>
                <argument>org.geotools.tutorial.logging.CommonsIntegration</argument>
              </arguments>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  2. Configure commons logging with commons-logging.properties added to src/main/resources:

    org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
    
  3. During startup commons-logging will use:

    • Check the classpath for commons-logging.properties.

    • Read the org.apache.commons.logging.Log property to determine logger to use.

    • Check the system property org.apache.commons.logging.Log logger not yet defined.

    • Try looking for first the Log4JLogger or Jdk14Logger if available.

      Log4JLogger is provided as part of the Log4J library.

      Jdk14Logger is provided by commons-logging, but if you are using an alternate implementation such as the spring-framework this will not be available.

    • SimpleLog making use of system err.

  4. The commons-logging.properties was setup to use SimpleLog.

    Configure SimpleLog using simplelog.properties added to src/main/resources:

    org.apache.commons.logging.simplelog.defaultlog=trace
    org.apache.commons.logging.simplelog.showdatetime=true
    org.apache.commons.logging.simplelog.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS
    
  1. Application CommonsIntegration.java startup example for src/min/java.

    Example is taking care to call GeoTools.init() prior to logger use:

    /*
     *    GeoTools - The Open Source Java GIS Toolkit
     *    http://geotools.org
     *
     *    (C) 2016, Open Source Geospatial Foundation (OSGeo)
     *
     *    This file is hereby placed into the Public Domain. This means anyone is
     *    free to do whatever they wish with this file. Use it well and enjoy!
     */
    package org.geotools.tutorial.logging;
    
    import java.util.logging.Logger;
    import java.util.logging.Level;
    
    import org.geotools.util.factory.GeoTools;
    import org.geotools.util.logging.CommonsLoggerFactory;
    import org.geotools.util.logging.Logging;
    
    /**
     * Example illustrating use of SLF4J API and Logback startup environment.
     */
    public class CommonsIntegration {
    
        public static final Logger LOGGER = initLogger();
    
        public static void main(String args[]) {
            LOGGER.info("Welcome to Commons Logging Integration Example");
    
            if(!LOGGER.getClass().getName().equals("org.geotools.util.logging.CommonsLogger")){
                LOGGER.severe("CommonsLogger expected, but was:" + LOGGER.getClass().getName() );
            }
            LOGGER.config("Configuration " + Logging.ALL.lookupConfiguration());
    
            LOGGER.finest("Everything is finest...");
            LOGGER.finer("Everything is finer...");
            LOGGER.fine("Everything is fine...");
            LOGGER.config("Everything is configured...");
            LOGGER.log(Logging.OPERATION, "Everything is operating...");
            LOGGER.info("Everything is okay.");
            LOGGER.warning("Everything is alarming!");
            LOGGER.severe("Everything is terrible!");
            LOGGER.log(Logging.FATAL, "Everything has died!");
        }
        
        private static Logger initLogger(){
            GeoTools.init();
            if( Logging.ALL.getLoggerFactory() != CommonsLoggerFactory.getInstance() ){
                System.err.println("Expected GeoTools.init() to configure CommonsLoggerFactory, was "+Logging.ALL.getLoggerFactory());
            }
            return Logging.getLogger(CommonsIntegration.class);
        }
    
    }
    
  1. An exec:exec target is provided to make this easier to test:

    mvn exec:exec
    

    Is the equivalent of:

    java -Djava.awt.headless=true \\
         org.geotools.tutorial.logging.CommonsIntegration