From c347972729e3145359786fe2a6eb557f5f3ad2cf Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 20 Oct 2014 15:24:19 +0100 Subject: [PATCH] Install SLF4JBridgeHandler when Log4J2LoggingSystem is initialized Previously, Log4J2LoggingSystem did not install SLF4JBridgeHandler. SLF4JBridgeHandler is used to route logging calls made using java.util.logging into SLF4J. This resulted in entries being written to System.err instead. This commit updates Log4J2LoggingSystem to register the bridge handler thereby ensuring the logging that originates into java.util.logging is routed into SLF4J. This change has been made by extracting a new abstract superclass that performs the registration. This super class is extended by all SLF4J-based LoggingSystem implementations. Fixes gh-1737 --- .../boot/logging/Slf4JLoggingSystem.java | 55 +++++++++++++++++++ .../logging/log4j/Log4JLoggingSystem.java | 15 +---- .../logging/log4j2/Log4J2LoggingSystem.java | 5 +- .../logging/logback/LogbackLoggingSystem.java | 28 +--------- .../log4j/Log4JLoggingSystemTests.java | 11 ++++ .../log4j2/Log4J2LoggingSystemTests.java | 11 ++++ .../logback/LogbackLoggingSystemTests.java | 11 ++++ 7 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java new file mode 100644 index 00000000000..6a1d498d1ef --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/logging/Slf4JLoggingSystem.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.logging; + +import org.slf4j.bridge.SLF4JBridgeHandler; +import org.springframework.util.ClassUtils; + +/** + * Abstract base class for {@link LoggingSystem} implementations that utilise SLF4J. + * + * @author Andy Wilkinson + * @since 1.2.0 + */ +public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem { + + public Slf4JLoggingSystem(ClassLoader classLoader, String... paths) { + super(classLoader, paths); + } + + @Override + public void beforeInitialize() { + super.beforeInitialize(); + try { + if (ClassUtils.isPresent("org.slf4j.bridge.SLF4JBridgeHandler", + getClassLoader())) { + try { + SLF4JBridgeHandler.removeHandlersForRootLogger(); + } + catch (NoSuchMethodError ex) { + // Method missing in older versions of SLF4J like in JBoss AS 7.1 + SLF4JBridgeHandler.uninstall(); + } + SLF4JBridgeHandler.install(); + } + } + catch (Throwable ex) { + // Ignore. No java.util.logging bridge is installed. + } + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java index fb94a549836..7e584a37ada 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java @@ -23,12 +23,10 @@ import java.util.Map; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.slf4j.bridge.SLF4JBridgeHandler; -import org.springframework.boot.logging.AbstractLoggingSystem; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; +import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.Log4jConfigurer; import org.springframework.util.StringUtils; @@ -38,7 +36,7 @@ import org.springframework.util.StringUtils; * @author Phillip Webb * @author Dave Syer */ -public class Log4JLoggingSystem extends AbstractLoggingSystem { +public class Log4JLoggingSystem extends Slf4JLoggingSystem { private static final Map LEVELS; static { @@ -57,15 +55,6 @@ public class Log4JLoggingSystem extends AbstractLoggingSystem { super(classLoader, "log4j.xml", "log4j.properties"); } - @Override - public void beforeInitialize() { - super.beforeInitialize(); - if (ClassUtils.isPresent("org.slf4j.bridge.SLF4JBridgeHandler", getClassLoader())) { - SLF4JBridgeHandler.removeHandlersForRootLogger(); - SLF4JBridgeHandler.install(); - } - } - @Override public void initialize(String configLocation) { Assert.notNull(configLocation, "ConfigLocation must not be null"); diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java index 134f18f9784..dc877fa76aa 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java @@ -27,9 +27,9 @@ import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; -import org.springframework.boot.logging.AbstractLoggingSystem; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; +import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; import org.springframework.util.ResourceUtils; import org.springframework.util.SystemPropertyUtils; @@ -38,9 +38,10 @@ import org.springframework.util.SystemPropertyUtils; * {@link LoggingSystem} for Log4j 2. * * @author Daniel Fullarton + * @author Andy Wilkinson * @since 1.2.0 */ -public class Log4J2LoggingSystem extends AbstractLoggingSystem { +public class Log4J2LoggingSystem extends Slf4JLoggingSystem { private static final Map LEVELS; static { diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java index 8a385dbf2c3..450bc34c256 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java @@ -23,13 +23,11 @@ import java.util.Map; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; -import org.slf4j.bridge.SLF4JBridgeHandler; import org.slf4j.impl.StaticLoggerBinder; -import org.springframework.boot.logging.AbstractLoggingSystem; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; +import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; import org.springframework.util.SystemPropertyUtils; @@ -43,8 +41,9 @@ import ch.qos.logback.classic.util.ContextInitializer; * * @author Phillip Webb * @author Dave Syer + * @author Andy Wilkinson */ -public class LogbackLoggingSystem extends AbstractLoggingSystem { +public class LogbackLoggingSystem extends Slf4JLoggingSystem { private static final Map LEVELS; static { @@ -64,27 +63,6 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem { "logback.xml"); } - @Override - public void beforeInitialize() { - super.beforeInitialize(); - try { - if (ClassUtils.isPresent("org.slf4j.bridge.SLF4JBridgeHandler", - getClassLoader())) { - try { - SLF4JBridgeHandler.removeHandlersForRootLogger(); - } - catch (NoSuchMethodError ex) { - // Method missing in older versions of SLF4J like in JBoss AS 7.1 - SLF4JBridgeHandler.uninstall(); - } - SLF4JBridgeHandler.install(); - } - } - catch (Throwable ex) { - // Ignore. No java.util.logging bridge is installed. - } - } - @Override public void initialize(String configLocation) { Assert.notNull(configLocation, "ConfigLocation must not be null"); diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java index 8fdc52b1a12..3fca3a4d675 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/log4j/Log4JLoggingSystemTests.java @@ -89,4 +89,15 @@ public class Log4JLoggingSystemTests { equalTo(1)); } + @Test + public void loggingThatUsesJulIsCaptured() { + this.loggingSystem.beforeInitialize(); + this.loggingSystem.initialize(); + java.util.logging.Logger julLogger = java.util.logging.Logger + .getLogger(getClass().getName()); + julLogger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java index 81a78e3fcae..9d75c508106 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java @@ -90,4 +90,15 @@ public class Log4J2LoggingSystemTests { equalTo(1)); } + @Test + public void loggingThatUsesJulIsCaptured() { + this.loggingSystem.beforeInitialize(); + this.loggingSystem.initialize(); + java.util.logging.Logger julLogger = java.util.logging.Logger + .getLogger(getClass().getName()); + julLogger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java index 8a7aacd323b..e752491c17a 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java @@ -119,4 +119,15 @@ public class LogbackLoggingSystemTests { equalTo(1)); } + @Test + public void loggingThatUsesJulIsCaptured() { + this.loggingSystem.beforeInitialize(); + this.loggingSystem.initialize(); + java.util.logging.Logger julLogger = java.util.logging.Logger + .getLogger(getClass().getName()); + julLogger.info("Hello world"); + String output = this.output.toString().trim(); + assertTrue("Wrong output:\n" + output, output.contains("Hello world")); + } + }