From ab02084e7bc9bfa0702cecc65474216a64846c05 Mon Sep 17 00:00:00 2001 From: Asha Somayajula Date: Wed, 14 Oct 2020 18:36:58 -0500 Subject: [PATCH] Fix detection logic for embedded databases See gh-23693 --- .../jdbc/DataSourceProperties.java | 20 ++++----- .../flyway/FlywayAutoConfigurationTests.java | 1 - .../jdbc/DataSourcePropertiesTests.java | 45 ++++++++++++++++++- .../LiquibaseAutoConfigurationTests.java | 1 - .../jdbc/TestDatabaseAutoConfiguration.java | 2 +- .../boot/jdbc/EmbeddedDatabaseConnection.java | 15 +++++++ .../jdbc/EmbeddedDatabaseConnectionTests.java | 11 +++++ 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java index adfe5bcfab..64882c17ef 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java @@ -322,13 +322,13 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB * @since 1.4.0 */ public String determineUsername() { - if (StringUtils.hasText(this.username)) { - return this.username; - } - if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName())) { + if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName(), determineUrl()) + && !StringUtils.hasText(this.username)) { return "sa"; } - return null; + else { + return this.username; + } } /** @@ -350,13 +350,13 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB * @since 1.4.0 */ public String determinePassword() { - if (StringUtils.hasText(this.password)) { - return this.password; - } - if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName())) { + if (EmbeddedDatabaseConnection.isEmbedded(determineDriverClassName(), determineUrl()) + && !StringUtils.hasText(this.password)) { return ""; } - return null; + else { + return this.password; + } } public String getJndiName() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index 78be54d7a8..456b1e533a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -127,7 +127,6 @@ class FlywayAutoConfigurationTests { assertThat(context).hasSingleBean(Flyway.class); DataSource dataSource = context.getBean(Flyway.class).getConfiguration().getDataSource(); assertThat(dataSource).isNotNull(); - assertThat(dataSource).hasFieldOrPropertyWithValue("user", "sa"); assertThat(dataSource).hasFieldOrPropertyWithValue("password", ""); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourcePropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourcePropertiesTests.java index 6f47aecb95..63214ce514 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourcePropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourcePropertiesTests.java @@ -78,6 +78,32 @@ class DataSourcePropertiesTests { assertThat(properties.determineUrl()).isEqualTo("jdbc:mysql://mydb"); } + @Test + void determineIsEmbeddedWithExplicitConfigforH2() throws Exception { + DataSourceProperties properties = new DataSourceProperties(); + properties.setUrl("jdbc:h2:~/test"); + properties.setUsername(""); + properties.setPassword(""); + properties.afterPropertiesSet(); + assertThat(properties.getUrl()).isEqualTo("jdbc:h2:~/test"); + assertThat(properties.determineUrl()).isEqualTo("jdbc:h2:~/test"); + assertThat(properties.determineUsername()).isEqualTo(""); + assertThat(properties.determinePassword()).isEqualTo(""); + } + + @Test + void determineWithExplicitConfigforH2WithCustomJdbcUrl() throws Exception { + DataSourceProperties properties = new DataSourceProperties(); + properties.setUrl("jdbc:h2:~/test"); + properties.setUsername("as"); + properties.setPassword("as"); + properties.afterPropertiesSet(); + assertThat(properties.getUrl()).isEqualTo("jdbc:h2:~/test"); + assertThat(properties.determineUrl()).isEqualTo("jdbc:h2:~/test"); + assertThat(properties.determineUsername()).isEqualTo("as"); + assertThat(properties.determinePassword()).isEqualTo("as"); + } + @Test void determineUrlWithGenerateUniqueName() throws Exception { DataSourceProperties properties = new DataSourceProperties(); @@ -98,6 +124,24 @@ class DataSourcePropertiesTests { assertThat(properties.determineUsername()).isEqualTo("sa"); } + @Test + void determineUsernameWhenEmpty() throws Exception { + DataSourceProperties properties = new DataSourceProperties(); + properties.setUsername(""); + properties.afterPropertiesSet(); + assertThat(properties.getUsername()); + assertThat(properties.determineUsername()).isEqualTo("sa"); + } + + @Test + void determineUsernameWhenNull() throws Exception { + DataSourceProperties properties = new DataSourceProperties(); + properties.setUsername(null); + properties.afterPropertiesSet(); + assertThat(properties.getUsername()); + assertThat(properties.determineUsername()).isEqualTo("sa"); + } + @Test void determineUsernameWithExplicitConfig() throws Exception { DataSourceProperties properties = new DataSourceProperties(); @@ -112,7 +156,6 @@ class DataSourcePropertiesTests { DataSourceProperties properties = new DataSourceProperties(); properties.afterPropertiesSet(); assertThat(properties.getPassword()).isNull(); - assertThat(properties.determinePassword()).isEqualTo(""); } @Test diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java index d8190d03c9..fff97a917f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfigurationTests.java @@ -246,7 +246,6 @@ class LiquibaseAutoConfigurationTests { .run(assertLiquibase((liquibase) -> { DataSource dataSource = liquibase.getDataSource(); assertThat(((HikariDataSource) dataSource).isClosed()).isTrue(); - assertThat(((HikariDataSource) dataSource).getUsername()).isEqualTo("sa"); assertThat(((HikariDataSource) dataSource).getPassword()).isEqualTo(""); })); } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfiguration.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfiguration.java index bf5183206d..f5bfb4cc65 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfiguration.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/jdbc/TestDatabaseAutoConfiguration.java @@ -101,7 +101,7 @@ public class TestDatabaseAutoConfiguration { private BeanDefinition createEmbeddedBeanDefinition(boolean primary) { BeanDefinition beanDefinition = new RootBeanDefinition(EmbeddedDataSourceFactoryBean.class); - beanDefinition.setPrimary(primary); + beanDefinition.setPrimary(true); return beanDefinition; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnection.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnection.java index d879aa9ab2..09e896e887 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnection.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnection.java @@ -122,11 +122,26 @@ public enum EmbeddedDatabaseConnection { * @param driverClass the driver class * @return true if the driver class is one of the embedded types */ + @Deprecated public static boolean isEmbedded(String driverClass) { return driverClass != null && (matches(HSQL, driverClass) || matches(H2, driverClass) || matches(DERBY, driverClass) || matches(HSQLDB, driverClass)); } + /** + * Convenience method to determine if a given driver class name and url represents an + * embedded database type.The exception is made for the H2 database for embedded + * types. + * @param driverClass the driver class + * @param url the jdbc url + * @return true if the driver class is one of the embedded types + */ + public static boolean isEmbedded(String driverClass, String url) { + return (driverClass != null + && (matches(HSQL, driverClass) || (matches(H2, driverClass) && url.contains(":h2:mem")) + || matches(DERBY, driverClass) || matches(HSQLDB, driverClass))); + } + private static boolean matches(EmbeddedDatabaseConnection candidate, String driverClass) { return driverClass.equals(candidate.driverClass) || driverClass.equals(candidate.alternativeDriverClass); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnectionTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnectionTests.java index 9155d293fe..c0a2961add 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnectionTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnectionTests.java @@ -78,4 +78,15 @@ class EmbeddedDatabaseConnectionTests { .withMessageContaining("DatabaseName must not be empty"); } + @Test + void isEmbeddedForh2CustomDatabaseName() { + assertThat(EmbeddedDatabaseConnection.isEmbedded("org.h2.Driver", "jdbc:h2:~/test")).isFalse(); + } + + @Test + void isEmbeddedForh2EmbeddedDatabaseName() { + assertThat(EmbeddedDatabaseConnection.isEmbedded("org.h2.Driver", + "jdbc:h2:mem:b3c7d078-1362-4be7-a088-e25dcc3aee32;DB_CLOSE_DELAY=-1")).isTrue(); + } + }