diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfiguration.java index 9b7bae28e1..6975ce7cfa 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfiguration.java @@ -65,11 +65,22 @@ public class H2ConsoleAutoConfiguration { ServletRegistrationBean registration = new ServletRegistrationBean<>(new WebServlet(), urlMapping); configureH2ConsoleSettings(registration, properties.getSettings()); if (logger.isInfoEnabled()) { - logDataSources(dataSource, path); + withThreadContextClassLoader(getClass().getClassLoader(), () -> logDataSources(dataSource, path)); } return registration; } + private void withThreadContextClassLoader(ClassLoader classLoader, Runnable action) { + ClassLoader previous = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + action.run(); + } + finally { + Thread.currentThread().setContextClassLoader(previous); + } + } + private void logDataSources(ObjectProvider dataSource, String path) { List urls = dataSource.orderedStream().map((available) -> { try (Connection connection = available.getConnection()) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java index 132b37a0d1..e3c3719549 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/h2/H2ConsoleAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.h2; +import java.net.URL; +import java.net.URLClassLoader; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -24,6 +26,8 @@ import javax.sql.DataSource; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -137,7 +141,8 @@ class H2ConsoleAutoConfigurationTests { @Test @ExtendWith(OutputCaptureExtension.class) void allDataSourceUrlsAreLoggedWhenMultipleAvailable(CapturedOutput output) { - this.contextRunner + ClassLoader webAppClassLoader = new URLClassLoader(new URL[0]); + this.contextRunner.withClassLoader(webAppClassLoader) .withUserConfiguration(FailingDataSourceConfiguration.class, MultiDataSourceConfiguration.class) .withPropertyValues("spring.h2.console.enabled=true").run((context) -> assertThat(output).contains( "H2 console available at '/h2-console'. Databases available at 'someJdbcUrl', 'anotherJdbcUrl'")); @@ -179,9 +184,20 @@ class H2ConsoleAutoConfigurationTests { private DataSource mockDataSource(String url) throws SQLException { DataSource dataSource = mock(DataSource.class); - given(dataSource.getConnection()).willReturn(mock(Connection.class)); - given(dataSource.getConnection().getMetaData()).willReturn(mock(DatabaseMetaData.class)); - given(dataSource.getConnection().getMetaData().getURL()).willReturn(url); + given(dataSource.getConnection()).will(new Answer() { + + @Override + public Connection answer(InvocationOnMock invocation) throws Throwable { + assertThat(Thread.currentThread().getContextClassLoader()).isEqualTo(getClass().getClassLoader()); + Connection connection = mock(Connection.class); + DatabaseMetaData metadata = mock(DatabaseMetaData.class); + given(connection.getMetaData()).willReturn(metadata); + given(metadata.getURL()).willReturn(url); + return connection; + } + + }); + return dataSource; }