Java Util Logging Configuration

The java util logging configuration is defined by a file logging.properties:

  • java.util.logging.config.file system property

  • java.util.logging.config.class identifying a class in your application responsible for configuration

  • Java 8: $JAVA_HOME/jre/lib/logging.properties

  • Java 9: $JAVA_HOME/conf/logging.properties

And can be detected during application startup if necessary:

public void static main(String ...){
   File logging = new File("logging.properties");
   if( logging.exists() && !System.getProperties().hasKey("java.util.logging.config.file")){
     System.setProperty("java.util.logging.config.file", path);
   }
   else {
     System.setProperty("java.util.logging.config.class", "ApplicationDefaultLogging");
   }
}

Falling back to ApplicationDefaultLogging (reading logging.properties from src/main/resources/logging.properties resource included in jar:

class ApplicationDefaultLogging {
   public ApplicationDefaultLogging(){
       try( Inputstream stream : ApplicationDefaultLogging.class.getResourceAsStream("/logging.properties")){
          LogManager.readConfiguration(stream);
       }
   }
}

To define a default configuration level provide a the .level property to the minimal level of interest for you:

.level= FINER

You can specify a different level to be shown to the console (than is saved out to xml). To define the java.util.logging.ConsoleHandler.level property to the minimal level you want to see on the console:

# Limit the message that are printed on the console to FINE and above.
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

For Windows user, check the value displayed by chcp on the command line - you may need to add:

# windows users may need to provide character encoding
java.util.logging.ConsoleHandler.encoding = Cp850

To list detailed messages for a specific module you can define a different logging level may be specified for each module.:

org.geotools.gml.level = FINE
org.geotools.referencing.level = INFO

Provides fairly detailed logging message from the GML module, but not from the referencing module.

Custom Levels

Logging defines two custom levels to better map to logging frameworks:

  • Logging.FATAL - unrecoverable error that will cause application or operation to fail

  • Logging.OPERATION - operation configuration

MonolineFormatter

GeoTools can produces a console output similar to the Log4J one (single-line instead of multi-line log message) if the following code is invoked once at application starting time:

Logging.ALL.forceMonolineConsoleOutput();

Alternatively, this formatter can also be configured in the logging.properties without the need for the above-cited method call:

java.util.logging.ConsoleHandler.formatter = org.geotools.util.logging.MonolineFormatter
java.util.logging.ConsoleHandler.level = FINE

# Optional
# org.geotools.util.logging.MonolineFormatter.time = HH:mm:ss.SSS
# org.geotools.util.logging.MonolineFormatter.source = class:short

See the MonolineFormatter javadoc for details.

Java Util Logging Guidance

Logging frameworks mechanism to delegate to java.util.logging as a backend.

  • SL4J: Add slf4j-jdk14.jar to classpath:

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-jdk14</artifactId>
      <version>${sl4j.version}</version>
    </dependency>
    
  • Log4J 1.2: configure an appender route to java util logging

    <appender name="jul" class="org.apache.log4j.JulAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c - %m%n "/>
        </layout>
    </appender>
    
  • commons-logging:

    Use commons-logging.properties:

    org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
    

Java Util 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>logging</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
      <name>GeoTools Logging Integration Example</name>
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.deploy.skip>true</maven.deploy.skip>
        <geotools.version>29-SNAPSHOT</geotools.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>
      </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>
            <inherited>true</inherited>
            <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>
                <classpath/>
                <argument>-Djava.util.logging.config.file=logging.properties</argument>
                <argument>-Djava.awt.headless=true</argument>
                <argument>-Duser.country=US</argument>
                <argument>-Duser.language=en</argument>
                <argument>org.geotools.tutorial.logging.LoggingIntegration</argument>
              </arguments>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  2. Configure java.util.logging with logging.properties:

    handlers=java.util.logging.ConsoleHandler
    
    java.util.logging.ConsoleHandler.level = ALL
    java.util.logging.ConsoleHandler.formatter = org.geotools.util.logging.MonolineFormatter
    org.geotools.util.logging.MonolineFormatter.source = class:short
    
    # Loggers created by org.geotools.util.logging.Logging
    .level= ALL
    org.geotools.level = CONFIG
    
    # Not created by LoggingIntegration (so this setting is never used)
    org.geotools.tutorial.level = FINE
    
    # Created by LoggingInteraction
    org.geotools.tutorial.logging.level = FINEST
    

    Warning

    Only Loggers that are used are configured, this can be frustrating if you assume a parent logger has been setup and will provide an expected default level.

  3. During startup java util logging will use:

    • The logging.properties included in your Java Runtime Environment.

    • The /WEB-INF/logging.properties included in web application

    You can override this behaviour with system property:

    -Djava.util.logging.config.file=logging.properties
    
  4. Application LogbackJIntegration.java startup example for src/min/java.

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

    /*
     *    GeoTools Sample code and Tutorials by Open Source Geospatial Foundation, and others
     *    https://docs.geotools.org
     *
     *    To the extent possible under law, the author(s) have dedicated all copyright
     *    and related and neighboring rights to this software to the public domain worldwide.
     *    This software is distributed without any warranty.
     *
     *    You should have received a copy of the CC0 Public Domain Dedication along with this
     *    software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
     */
    package org.geotools.tutorial.logging;
    
    import java.io.File;
    import java.util.logging.Logger;
    import java.util.logging.Level;
    import org.geotools.util.factory.GeoTools;
    import org.geotools.util.logging.DefaultLoggerFactory;
    import org.geotools.util.logging.Logging;
    /**
     * Logging integration demonstration illustrating use of logging.properties to configure GeoTools.
     */
    public class LoggingIntegration {
        static {
            GeoTools.init();
        }
    
        static final Logger LOGGER = Logging.getLogger(LoggingIntegration.class);
    
        public static void main(String args[]) {
    
            if (Logging.ALL.getLoggerFactory() != DefaultLoggerFactory.getInstance()) {
                System.err.println(
                        "Expected GeoTools.init() use native java util logging factory, was "
                                + Logging.ALL.getLoggerFactory());
            }
    
            LOGGER.info("Welcome to Logging Integration Example");
            checkProperty("java.util.logging.config.file");
            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 void checkProperty(String property) {
            if (System.getProperties().containsKey(property)) {
                LOGGER.config(property + "=" + System.getProperty(property));
            }
        }
    }
    
  1. An exec:exec target is provided to make this easier to test:

    mvn exec:exec
    

    The exec:exec goal was configured with -Djava.util.logging.config.file=logging.properties.

    Note

    Avoid testing with exec:java which uses maven java runtime environment (already pre-configured for logging).