Log4J 2 Interoperability¶
Log4J is split into log4j-api and log4j-core jars:
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>${log4j2.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>${log4j2.version}</version>
</dependency>
To configure GeoTools to use Log4J API:
GeoTools.setLoggerFactory("org.geotools.util.logging.Log4J2LoggerFactory");
Reference:
Log4j Guidance¶
Communication from different Logging frameworks have to Log4J 2 API:
To bridge slf4j to Log4J:
- Include the following jar: - <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j18-impl</artifactId> <version>${log4j2.version}</version> </dependency> 
- This routes slf4j api calls to - log4j-core.
To bridge java util logging to Log4J:
- Include the following jar: - <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>${log4j2.version}</version> </dependency> 
- This bridge provides the following mapping: - java.util.logging.Filter: yes 
- java.util.logging.Handler: no 
 - Levels: - Java Level - Log4j Level - OFF - OFF - FATAL - FATAL - SEVERE - ERROR - WARNING - WARN - INFO - INFO - CONFIG - CONFIG - FINE - DEBUG - FINER - TRACE - FINEST - FINEST - ALL - ALL 
- There are several ways to enable - java.util.loggingbridge to Log4J:- System property: - -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
- System property during application init: - System.setProperty("java.util.logging.manager","org.apache.logging.log4j.jul.LogManager"); 
- Setup configure application - logging.propertieswith the following:- handlers = org.apache.logging.log4j.jul.Log4jBridgeHandler org.apache.logging.log4j.jul.Log4jBridgeHandler.propagateLevels = true 
- Explicitly call - Log4jBridgeHandler.install()during application init:
 - Log4jBridgeHandler.install(); 
- To bridge Log4J 1.x to Log4J (replacing the need for Reload4J): - <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>${log4j2.version}</version> </dependency> - Reference: https://logging.apache.org/log4j/2.x/manual/migration.html 
Log4j Integration¶
The following example is taken from our integration testing, this test only has Log4j 2 API in play
so GeoTools.init()` is able to unambiguously determine ``Log4JLoggerFactory can be used.
- Setup - pom.xmlwith dependencies on geotools and Log4J:- <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.geotools.tutorial</groupId> <artifactId>log4j</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>GeoTools Log4j Integration Example</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.deploy.skip>true</maven.deploy.skip> <geotools.version>33-SNAPSHOT</geotools.version> <log4j2.version>2.24.3</log4j2.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>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j2.version}</version> </dependency> <!-- java util logging logging to log4j 2 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>${log4j2.version}</version> </dependency> <!-- commons logging bridge to log4j 2 --> <!-- <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>${log4j2.version}</version> </dependency> --> <!-- slf4j bridge to log4j 2 --> <!--<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.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> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.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.Log4JIntegration</argument> </arguments> </configuration> <executions> <execution> <id>jul</id> <phase>integration-test</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>java</executable> <arguments> <argument>-classpath</argument> <!-- uses dependencies and build directory --> <classpath/> <argument>-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager</argument> <argument>-Dlog4j2.configurationFile=log4j2-production.xml</argument> <argument>-Djava.awt.headless=true</argument> <argument>org.geotools.tutorial.logging.Log4JIntegration</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> 
- Configure log4j wtih - log4j2.xmladded to- src/main/resources:- <?xml version="1.0" encoding="UTF-8"?> <!-- Concise Syntax --> <Configuration status="info" dest="out"> <CustomLevels> <CustomLevel name="CONFIG" intLevel="450" /> <CustomLevel name="FINEST" intLevel="700" /> </CustomLevels>> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%date{HH:mm:ss.SSS} %-6level [%logger{2}] - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="org.geotools.tutorial.logging" level="all" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Logger name="org.geotools" level="debug" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> - Of interest above is defining the CONFIG and FINEST custom levels. 
- During startup logback will search for - log4j2.xmlon the CLASSPATH.- To search for a different file on the classpath use - -Dlog4j2.configurationFile=log4j2-production.xml.
- Application - Log4JIntegration.javastartup 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 org.geotools.util.factory.GeoTools; import org.geotools.util.logging.Log4J2LoggerFactory; import org.geotools.util.logging.Logging; /** Example illustrating use of Log4J 2 API and startup environment. */ public class Log4JIntegration { static { GeoTools.init(); } static final Logger LOGGER = Logging.getLogger(Log4JIntegration.class); public static void main(String args[]) { LOGGER.info("Welcome to Log4j Integration Example"); if (!LOGGER.getClass().getName().equals("org.geotools.util.logging.Log4J2Logger")) { LOGGER.severe("Log4J2Logger expected, but was:" + LOGGER.getClass().getName()); } // Log4J2 properties LOGGER.info("Welcome to Log4j Integration Example"); checkProperty("log4j2.configurationFile"); 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)); } } } 
- An - exec:exectarget is provided to make this easier to test:- mvn exec:exec - Is the equivalent of: - java -Djava.awt.headless=true \\ org.geotools.tutorial.logging.Log4JIntegration 
- An - exec:exec@jultarget is provided to try out a more realistic production setting.- mvn exec:exec@jul - Is the equivalent of: - java -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \\ -Dlog4j2.configurationFile=log4j2-production.xml \\ -Djava.awt.headless=true \\ org.geotools.tutorial.logging.Log4JIntegration - This makes use of the - log4j2-production.xmlconfiguration, and sets up log4j jul bridge.- <?xml version="1.0" encoding="UTF-8"?> <!-- Concise Syntax --> <Configuration status="info" dest="out"> <CustomLevels> <CustomLevel name="CONFIG" intLevel="450" /> <CustomLevel name="FINEST" intLevel="700" /> </CustomLevels>> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%date{HH:mm:ss.SSS} %-6level [%logger{2}] - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="org.geotools" level="config" additivity="false"> <AppenderRef ref="Console"/> </Logger> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration> - This logging configuration reduces the levels recorded.