mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-10-06 17:29:19 +00:00
Back off DevTools' JDBC and R2DBC support when modules are missing
DevToolsDataSourceAutoConfiguration and DevToolsR2dbcAutoConfiguration were only guarded by classes from the JDK and r2dbc-spi respectively. When a single user-defined DataSource or ConnectionFactory bean was present, their conditions went on to reference classes from spring-boot-jdbc or spring-boot-r2dbc. Both are optional dependencies of spring-boot-devtools, so startup failed with a NoClassDefFoundError when they were absent. This commit adds a class from each module to the class conditions. Without the modules the conditions could never match, so this only turns the failure into a back-off. See gh-51872 Signed-off-by: Kosuke Yanagihara <11373191+ksky8864@users.noreply.github.com>
This commit is contained in:
committed by
Stéphane Nicoll
parent
8c7c372dcb
commit
f0987da4bb
+1
-1
@@ -61,7 +61,7 @@ import org.springframework.util.Assert;
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.3
|
||||
*/
|
||||
@ConditionalOnClass(DataSource.class)
|
||||
@ConditionalOnClass({ DataSource.class, DataSourceProperties.class })
|
||||
@ConditionalOnEnabledDevTools
|
||||
@Conditional(DevToolsDataSourceCondition.class)
|
||||
@AutoConfiguration(afterName = "org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration")
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ import org.springframework.util.Assert;
|
||||
* @author Phillip Webb
|
||||
* @since 2.5.6
|
||||
*/
|
||||
@ConditionalOnClass(ConnectionFactory.class)
|
||||
@ConditionalOnClass({ ConnectionFactory.class, R2dbcAutoConfiguration.class })
|
||||
@ConditionalOnEnabledDevTools
|
||||
@Conditional(DevToolsConnectionFactoryCondition.class)
|
||||
@AutoConfiguration(afterName = "org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration")
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-present 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
|
||||
*
|
||||
* https://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.devtools.autoconfigure;
|
||||
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link DevToolsDataSourceAutoConfiguration} when {@code spring-boot-jdbc} is
|
||||
* not on the classpath.
|
||||
*
|
||||
* @author Kosuke Yanagihara
|
||||
*/
|
||||
@ClassPathExclusions(packages = "org.springframework.boot.jdbc.autoconfigure")
|
||||
class DevToolsDataSourceAutoConfigurationWithoutSpringBootJdbcTests {
|
||||
|
||||
@Test
|
||||
void backsOffWithSingleManuallyConfiguredDataSource() throws Exception {
|
||||
// DevTools is disabled when JUnit is on the stack so refresh on a new thread
|
||||
FutureTask<ConfigurableApplicationContext> task = new FutureTask<>(() -> {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(SingleDataSourceConfiguration.class);
|
||||
context.refresh();
|
||||
return context;
|
||||
});
|
||||
new Thread(task).start();
|
||||
try (ConfigurableApplicationContext context = task.get()) {
|
||||
assertThat(context.getBeansOfType(DataSource.class)).hasSize(1);
|
||||
assertThat(context.containsBean("inMemoryDatabaseShutdownExecutor")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration(DevToolsDataSourceAutoConfiguration.class)
|
||||
static class SingleDataSourceConfiguration {
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() {
|
||||
return mock(DataSource.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.devtools.autoconfigure.DevToolsR2dbcAutoConfiguration.R2dbcDatabaseShutdownEvent;
|
||||
import org.springframework.boot.r2dbc.SimpleConnectionFactoryProvider.SimpleTestConnectionFactory;
|
||||
import org.springframework.boot.r2dbc.autoconfigure.R2dbcAutoConfiguration;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -166,6 +169,35 @@ class DevToolsR2dbcAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
@ClassPathExclusions(packages = "org.springframework.boot.r2dbc.autoconfigure")
|
||||
class WithoutSpringBootR2dbc {
|
||||
|
||||
@Test
|
||||
void backsOffWithSingleManuallyConfiguredConnectionFactory() throws Exception {
|
||||
// DevTools is disabled when JUnit is on the stack so refresh on a new thread
|
||||
FutureTask<ConfigurableApplicationContext> task = new FutureTask<>(() -> {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(SingleConnectionFactoryWithDevToolsConfiguration.class);
|
||||
context.refresh();
|
||||
return context;
|
||||
});
|
||||
new Thread(task).start();
|
||||
try (ConfigurableApplicationContext context = task.get()) {
|
||||
assertThat(context.getBeansOfType(ConnectionFactory.class)).hasSize(1);
|
||||
assertThat(context.containsBean("inMemoryR2dbcDatabaseShutdownExecutor")).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(SingleConnectionFactoryConfiguration.class)
|
||||
@ImportAutoConfiguration(DevToolsR2dbcAutoConfiguration.class)
|
||||
static class SingleConnectionFactoryWithDevToolsConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class SingleConnectionFactoryConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user