diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java index ee31b9b07a..e0003c510a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java @@ -248,20 +248,29 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem implements BeanF } private void reportConfigurationErrorsIfNecessary(LoggerContext loggerContext) { - List statuses = loggerContext.getStatusManager().getCopyOfStatusList(); StringBuilder errors = new StringBuilder(); - for (Status status : statuses) { + List suppressedExceptions = new ArrayList<>(); + for (Status status : loggerContext.getStatusManager().getCopyOfStatusList()) { if (status.getLevel() == Status.ERROR) { errors.append((errors.length() > 0) ? String.format("%n") : ""); errors.append(status.toString()); + if (status.getThrowable() != null) { + suppressedExceptions.add(status.getThrowable()); + } } } - if (errors.length() > 0) { - throw new IllegalStateException(String.format("Logback configuration error detected: %n%s", errors)); + if (errors.length() == 0) { + if (!StatusUtil.contextHasStatusListener(loggerContext)) { + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + } + return; } - if (!StatusUtil.contextHasStatusListener(loggerContext)) { - StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + IllegalStateException ex = new IllegalStateException( + String.format("Logback configuration error detected: %n%s", errors)); + for (Throwable suppressedException : suppressedExceptions) { + ex.addSuppressed(suppressedException); } + throw ex; } private void configureByResourceUrl(LoggingInitializationContext initializationContext, LoggerContext loggerContext, diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java index 9d992af0bb..f46b40e84b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java @@ -38,6 +38,7 @@ import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy; +import ch.qos.logback.core.util.DynamicClassLoadingException; import ch.qos.logback.core.util.StatusPrinter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -676,6 +677,16 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { assertThat(output).contains(" elements cannot be nested within an"); } + @Test + void whenConfigurationErrorIsDetectedUnderlyingCausesAreIncludedAsSuppressedExceptions() { + this.loggingSystem.beforeInitialize(); + assertThatIllegalStateException() + .isThrownBy(() -> initialize(this.initializationContext, "classpath:logback-broken.xml", + getLogFile(tmpDir() + "/tmp.log", null))) + .satisfies((ex) -> assertThat(ex.getSuppressed()) + .hasAtLeastOneElementOfType(DynamicClassLoadingException.class)); + } + private void initialize(LoggingInitializationContext context, String configLocation, LogFile logFile) { this.loggingSystem.getSystemProperties((ConfigurableEnvironment) context.getEnvironment()).apply(logFile); this.loggingSystem.initialize(context, configLocation, logFile);