From b634e35f4fd63c9633dfffc80713d9b132d86a1e Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Wed, 8 Jan 2020 16:19:55 +0200 Subject: [PATCH] DataSource url property is ignored when there is no connection pool see gh-19192 --- .../jdbc/DataSourceAutoConfiguration.java | 14 +++++-- .../jdbc/DataSourceConfiguration.java | 37 +++++++++++++++++-- .../DataSourceAutoConfigurationTests.java | 15 +++++++- .../boot/jdbc/DataSourceBuilder.java | 3 +- .../boot/jdbc/DataSourceBuilderTests.java | 11 +++++- 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java index 3ecdab3d2416..d42d3c6fd133 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -37,6 +37,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; /** @@ -73,8 +74,9 @@ protected static class PooledDataSourceConfiguration { } /** - * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type} - * is set or {@link PooledDataSourceAvailableCondition} applies. + * {@link AnyNestedCondition} that checks that either one of + * {@code spring.datasource.type}, {@code spring.datasource.url} properties is set or + * {@link PooledDataSourceAvailableCondition} applies. */ static class PooledDataSourceCondition extends AnyNestedCondition { @@ -87,6 +89,12 @@ static class ExplicitType { } + @ConditionalOnProperty(prefix = "spring.datasource", name = "url") + @ConditionalOnClass(SimpleDriverDataSource.class) + static class ExplicitUrl { + + } + @Conditional(PooledDataSourceAvailableCondition.class) static class PooledDataSourceAvailable { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java index d94e9d3ec1a7..ea31c059f9c1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -20,13 +20,17 @@ import com.zaxxer.hikari.HikariDataSource; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.util.StringUtils; /** @@ -114,12 +118,39 @@ org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties propert */ @Configuration(proxyBeanMethods = false) @ConditionalOnMissingBean(DataSource.class) - @ConditionalOnProperty(name = "spring.datasource.type") + @Conditional(ExplicitDataSourceTypeOrUrlCondition.class) static class Generic { @Bean DataSource dataSource(DataSourceProperties properties) { - return properties.initializeDataSourceBuilder().build(); + return properties.initializeDataSourceBuilder().type(determineType(properties)).build(); + } + + private static Class determineType(DataSourceProperties properties) { + Class type = properties.getType(); + if (type == null) { + type = DataSourceBuilder.findType(properties.getClassLoader()); + } + return (type != null) ? type : SimpleDriverDataSource.class; + } + + } + + static class ExplicitDataSourceTypeOrUrlCondition extends AnyNestedCondition { + + ExplicitDataSourceTypeOrUrlCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty(prefix = "spring.datasource", name = "type") + static class ExplicitType { + + } + + @ConditionalOnProperty(prefix = "spring.datasource", name = "url") + @ConditionalOnClass(SimpleDriverDataSource.class) + static class ExplicitUrl { + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java index 109c05b296db..ca3e8d8c5849 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -158,6 +158,16 @@ void explicitTypeNoSupportedDataSource() { .run(this::containsOnlySimpleDriverDataSource); } + @Test + void createDataSourceExplicitUrlPresentAndNoPoolDataSourceAvailable() { + this.contextRunner + .withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", + "org.apache.commons.dbcp", "org.apache.commons.dbcp2")) + .withPropertyValues("spring.datasource.driverClassName:org.hsqldb.jdbcDriver", + "spring.datasource.url:jdbc:hsqldb:mem:testdb") + .run(this::containsOnlySimpleDriverDataSource); + } + @Test void explicitTypeSupportedDataSource() { this.contextRunner @@ -169,7 +179,8 @@ void explicitTypeSupportedDataSource() { private void containsOnlySimpleDriverDataSource(AssertableApplicationContext context) { assertThat(context).hasSingleBean(DataSource.class); - assertThat(context).getBean(DataSource.class).isExactlyInstanceOf(SimpleDriverDataSource.class); + assertThat(context).getBean(DataSource.class).isExactlyInstanceOf(SimpleDriverDataSource.class) + .extracting("driver").isNotNull(); } @Test diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java index f21da930efff..68d759d20f11 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -89,6 +89,7 @@ private void bind(DataSource result) { ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases(); aliases.addAliases("url", "jdbc-url"); aliases.addAliases("username", "user"); + aliases.addAliases("driver-class-name", "driver-class"); Binder binder = new Binder(source.withAliases(aliases)); binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result)); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java index 2fe866786884..21c3f6f97cd3 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -29,6 +29,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; + import static org.assertj.core.api.Assertions.assertThat; /** @@ -68,6 +70,13 @@ void defaultToCommonsDbcp2AsLastResort() { assertThat(this.dataSource).isInstanceOf(BasicDataSource.class); } + @Test + void simpleDriverDataSource() { + this.dataSource = DataSourceBuilder.create().url("jdbc:h2:test").type(SimpleDriverDataSource.class).build(); + assertThat(this.dataSource).isInstanceOf(SimpleDriverDataSource.class); + assertThat(this.dataSource).extracting("driver").isNotNull(); + } + @Test void specificTypeOfDataSource() { HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();