Logging¶
This document explains the logging architecture and implementation choices in GeoServer Cloud, including how logging dependencies are managed and how GeoTools/GeoServer logging is integrated with Spring Boot.
Logging Architecture: spring-jcl¶
GeoServer Cloud uses spring-jcl (Spring's Jakarta Commons Logging bridge) instead of the traditional commons-logging library. This is the recommended approach for Spring Boot applications.
Why spring-jcl?¶
Spring Boot applications should use spring-jcl because:
- Spring Boot's default - Spring Boot automatically excludes
commons-loggingand providesspring-jclas its replacement - Seamless SLF4J integration -
spring-jclbridges directly to SLF4J/Logback without additional configuration - No extra bridges needed - With
commons-logging, you would needjcl-over-slf4jto route logs to Logback - No classloader issues - The original
commons-logginghad notorious classloader discovery problems thatspring-jcleliminates
The Upstream GeoServer Conflict¶
Upstream GeoServer's gs-main module explicitly excludes spring-jcl:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-jcl</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
This exclusion exists because traditional GeoServer (non-Spring Boot) uses commons-logging directly, and having both libraries causes LogFactory class conflicts.
GeoServer Cloud Solution¶
Since GeoServer Cloud is a Spring Boot application, we explicitly re-add spring-jcl in src/apps/geoserver/pom.xml to override the upstream exclusion. This ensures all GeoServer microservices use Spring Boot's preferred logging bridge.
Logging Initialization¶
The logging bridge configuration is set up by GeoServerContextInitializer (src/starters/webmvc/src/main/java/org/geoserver/cloud/autoconfigure/context/GeoServerContextInitializer.java), which is an ApplicationContextInitializer that runs before Spring beans are loaded.
This initializer replaces upstream GeoServer's GeoserverInitStartupListener (a servlet context listener that runs too late in Spring Boot) and configures the following system properties:
// Tell GeoServer not to control logging, Spring Boot will handle it
System.setProperty("RELINQUISH_LOG4J_CONTROL", "true");
// Tell GeoTools to use Commons Logging for log redirection
System.setProperty("GT2_LOGGING_REDIRECTION", "CommonsLogging");
The GT2_LOGGING_REDIRECTION=CommonsLogging setting is crucial because:
- It configures GeoTools to redirect its
java.util.loggingcalls through Commons Logging - Commons Logging calls are then handled by
spring-jcl spring-jclbridges to SLF4J- SLF4J routes to Logback (Spring Boot's default)
This creates the logging chain: GeoTools JUL -> Commons Logging -> spring-jcl -> SLF4J -> Logback
Other redirection options were considered but rejected: - Logback: Incorrectly maps logging levels (e.g., FINE called with INFO doesn't log) - Log4J2: Fails when calling Logger.setLevel() due to API changes in newer Log4j2 versions