From 2d62e1fc89de4ea880c3fb2c49d5537f3259aeee Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 14 Aug 2015 13:30:14 +0200 Subject: [PATCH] Add a property to configure the connection pool A new `spring.datasource.type` property can now be used to configure the connection pool implementation to use (rather than only relying on Boot's preferences). Closes gh-3705 --- .../jdbc/DataSourceAutoConfiguration.java | 3 ++ .../jdbc/DataSourceProperties.java | 40 +++++++++++++------ .../DataSourceAutoConfigurationTests.java | 25 +++++++++--- .../appendix-application-properties.adoc | 1 + .../main/asciidoc/spring-boot-features.adoc | 6 ++- 5 files changed, 55 insertions(+), 20 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java index 2a5de7a3cbb..ecf3df67e7a 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java @@ -120,6 +120,9 @@ public class DataSourceAutoConfiguration { .url(this.properties.getUrl()) .username(this.properties.getUsername()) .password(this.properties.getPassword()); + if (this.properties.getType() != null) { + factory.type(this.properties.getType()); + } return factory.build(); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java index 490c084ee02..1132a79b0e6 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java @@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc; import java.nio.charset.Charset; import java.util.LinkedHashMap; import java.util.Map; +import javax.sql.DataSource; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanCreationException; @@ -33,6 +34,7 @@ import org.springframework.util.StringUtils; * * @author Dave Syer * @author Maciej Walkowiak + * @author Stephane Nicoll * @since 1.1.0 */ @ConfigurationProperties(prefix = DataSourceProperties.PREFIX) @@ -40,6 +42,12 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB public static final String PREFIX = "spring.datasource"; + /** + * Fully qualified name of the connection pool implementation to use. By default, + * it is auto-detected from the classpath. + */ + private Class type; + /** * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default. */ @@ -118,6 +126,14 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB .get(this.classLoader); } + public Class getType() { + return type; + } + + public void setType(Class type) { + this.type = type; + } + public String getDriverClassName() { if (StringUtils.hasText(this.driverClassName)) { Assert.state(ClassUtils.isPresent(this.driverClassName, null), @@ -144,6 +160,10 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB return driverClassName; } + public void setDriverClassName(String driverClassName) { + this.driverClassName = driverClassName; + } + public String getUrl() { if (StringUtils.hasText(this.url)) { return this.url; @@ -159,6 +179,10 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB return url; } + public void setUrl(String url) { + this.url = url; + } + public String getUsername() { if (StringUtils.hasText(this.username)) { return this.username; @@ -169,6 +193,10 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB return null; } + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { if (StringUtils.hasText(this.password)) { return this.password; @@ -179,18 +207,6 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB return null; } - public void setDriverClassName(String driverClassName) { - this.driverClassName = driverClassName; - } - - public void setUrl(String url) { - this.url = url; - } - - public void setUsername(String username) { - this.username = username; - } - public void setPassword(String password) { this.password = password; } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java index 5d5660666eb..f7be56ef5d5 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java @@ -26,13 +26,14 @@ import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; import java.util.Random; import java.util.logging.Logger; - import javax.sql.DataSource; +import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.dbcp.BasicDataSource; import org.junit.After; import org.junit.Before; import org.junit.Test; + import org.springframework.beans.factory.BeanCreationException; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.test.EnvironmentTestUtils; @@ -42,8 +43,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; -import com.zaxxer.hikari.HikariDataSource; - import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -56,6 +55,7 @@ import static org.mockito.Mockito.mock; * Tests for {@link DataSourceAutoConfiguration}. * * @author Dave Syer + * @author Stephane Nicoll */ public class DataSourceAutoConfigurationTests { @@ -72,9 +72,7 @@ public class DataSourceAutoConfigurationTests { @After public void restore() { EmbeddedDatabaseConnection.override = null; - if (this.context != null) { - this.context.close(); - } + this.context.close(); } @Test @@ -156,6 +154,20 @@ public class DataSourceAutoConfigurationTests { assertEquals("sa", pool.getUsername()); } + @Test + public void explicitType() { + EnvironmentTestUtils.addEnvironment(this.context, + "spring.datasource.driverClassName:org.hsqldb.jdbcDriver", + "spring.datasource.url:jdbc:hsqldb:mem:testdb", + "spring.datasource.type:" + HikariDataSource.class.getName()); + this.context.register(DataSourceAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + DataSource bean = this.context.getBean(DataSource.class); + assertNotNull(bean); + assertEquals(HikariDataSource.class, bean.getClass()); + } + @Test public void testExplicitDriverClassClearsUserName() throws Exception { EnvironmentTestUtils @@ -259,6 +271,7 @@ public class DataSourceAutoConfigurationTests { } + @SuppressWarnings("unused") // see testExplicitDriverClassClearsUserName public static class DatabaseDriver implements Driver { @Override diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index cd526a3f77e..569cb641d87 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -318,6 +318,7 @@ content into your application; rather pick only the properties that you need. spring.datasource.platform= # the platform to use in the schema resource (schema-${platform}.sql) spring.datasource.continue-on-error=false # continue even if can't be initialized spring.datasource.separator=; # statement separator in SQL initialization scripts + spring.datasource.type= # fully qualified name of the connection pool implementation to use spring.datasource.driver-class-name= # JDBC Settings... spring.datasource.url= spring.datasource.username= diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index db974456e26..f39c23e089e 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -2047,8 +2047,10 @@ Here's the algorithm for choosing a specific implementation: If you use the `spring-boot-starter-jdbc` or `spring-boot-starter-data-jpa` '`starter POMs`' you will automatically get a dependency to `tomcat-jdbc`. -NOTE: Additional connection pools can always be configured manually. If you define your -own `DataSource` bean, auto-configuration will not occur. +NOTE: You can bypass that algorithm completely and specify the connection pool to use via +the `spring.datasource.type` property. Also, additional connection pools can always be +configured manually. If you define your own `DataSource` bean, auto-configuration will +not occur. DataSource configuration is controlled by external configuration properties in `+spring.datasource.*+`. For example, you might declare the following section in