Do not default username/password for DataSource unless embedded

To use a DataSource pool (Tomcat or DBCP) the user must supply a valid
driver class name *and* database URL. If both are supplied and the
driver class is not one of the embedded ones, then no default username
or password is provided.

Fixes gh-94
This commit is contained in:
Dave Syer 2013-11-04 13:33:46 +00:00
parent c29d2b1be4
commit 97e6d77711
7 changed files with 113 additions and 28 deletions

View File

@ -174,6 +174,11 @@
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>

View File

@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.util.StringUtils;
@ -29,15 +30,16 @@ import org.springframework.util.StringUtils;
*/
@ConfigurationProperties(name = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
@EnableConfigurationProperties
public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware {
public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware,
InitializingBean {
private String driverClassName;
private String url;
private String username = "sa";
private String username;
private String password = "";
private String password;
private int maxActive = 100;
@ -53,41 +55,67 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader
private ClassLoader classLoader;
private EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection.NONE;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void afterPropertiesSet() throws Exception {
this.embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
}
protected String getDriverClassName() {
if (StringUtils.hasText(this.driverClassName)) {
return this.driverClassName;
}
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
this.driverClassName = embeddedDatabaseConnection.getDriverClassName();
if (!StringUtils.hasText(this.driverClassName)) {
String driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
if (!StringUtils.hasText(driverClassName)) {
throw new BeanCreationException(
"Cannot determine embedded database driver class for database type "
+ embeddedDatabaseConnection + ". If you want an embedded "
+ "database please put a supoprted one on the classpath.");
+ this.embeddedDatabaseConnection
+ ". If you want an embedded "
+ "database please put a supported one on the classpath.");
}
return this.driverClassName;
return driverClassName;
}
protected String getUrl() {
if (StringUtils.hasText(this.url)) {
return this.url;
}
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
this.url = embeddedDatabaseConnection.getUrl();
if (!StringUtils.hasText(this.url)) {
String url = this.embeddedDatabaseConnection.getUrl();
if (!StringUtils.hasText(url)) {
throw new BeanCreationException(
"Cannot determine embedded database url for database type "
+ embeddedDatabaseConnection + ". If you want an embedded "
+ this.embeddedDatabaseConnection
+ ". If you want an embedded "
+ "database please put a supported on on the classpath.");
}
return this.url;
return url;
}
protected String getUsername() {
if (StringUtils.hasText(this.username)) {
return this.username;
}
if (EmbeddedDatabaseConnection.isEmbedded(this.driverClassName)) {
return "sa";
}
return null;
}
protected String getPassword() {
if (StringUtils.hasText(this.password)) {
return this.password;
}
if (EmbeddedDatabaseConnection.isEmbedded(this.driverClassName)) {
return "";
}
return null;
}
public void setDriverClassName(String driverClassName) {
@ -130,14 +158,6 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader
this.testOnReturn = testOnReturn;
}
protected String getUsername() {
return this.username;
}
protected String getPassword() {
return this.password;
}
protected int getMaxActive() {
return this.maxActive;
}

View File

@ -49,8 +49,12 @@ public class CommonsDataSourceConfiguration extends AbstractDataSourceConfigurat
this.pool = new BasicDataSource();
this.pool.setDriverClassName(getDriverClassName());
this.pool.setUrl(getUrl());
this.pool.setUsername(getUsername());
this.pool.setPassword(getPassword());
if (getUsername() != null) {
this.pool.setUsername(getUsername());
}
if (getPassword() != null) {
this.pool.setPassword(getPassword());
}
this.pool.setMaxActive(getMaxActive());
this.pool.setMaxIdle(getMaxIdle());
this.pool.setMinIdle(getMinIdle());

View File

@ -88,6 +88,20 @@ public enum EmbeddedDatabaseConnection {
*/
static EmbeddedDatabaseConnection override;
/**
* Convenience method to determine if a given driver class name represents an embedded
* database type.
*
* @param driverClass the driver class
* @return true if the driver class is one of the embedded types
*/
public static boolean isEmbedded(String driverClass) {
return driverClass != null
&& (driverClass.equals(HSQL.driverClass)
|| driverClass.equals(H2.driverClass) || driverClass
.equals(DERBY.driverClass));
}
/**
* Returns the most suitable {@link EmbeddedDatabaseConnection} for the given class
* loader.

View File

@ -39,8 +39,12 @@ public class TomcatDataSourceConfiguration extends AbstractDataSourceConfigurati
this.pool = new org.apache.tomcat.jdbc.pool.DataSource();
this.pool.setDriverClassName(getDriverClassName());
this.pool.setUrl(getUrl());
this.pool.setUsername(getUsername());
this.pool.setPassword(getPassword());
if (getUsername() != null) {
this.pool.setUsername(getUsername());
}
if (getPassword() != null) {
this.pool.setPassword(getPassword());
}
this.pool.setMaxActive(getMaxActive());
this.pool.setMaxIdle(getMaxIdle());
this.pool.setMinIdle(getMinIdle());

View File

@ -23,6 +23,7 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import org.springframework.boot.TestUtils;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
@ -35,6 +36,7 @@ import org.springframework.util.ClassUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
@ -54,6 +56,36 @@ public class DataSourceAutoConfigurationTests {
assertNotNull(this.context.getBean(DataSource.class));
}
@Test
public void testEmbeddedTypeDefaultsUsername() throws Exception {
TestUtils.addEnviroment(this.context,
"spring.datasource.driverClassName:org.hsqldb.jdbcDriver",
"spring.datasource.url:jdbc:hsqldb:mem:testdb");
this.context.register(DataSourceAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
DataSource bean = this.context.getBean(DataSource.class);
assertNotNull(bean);
org.apache.tomcat.jdbc.pool.DataSource pool = (org.apache.tomcat.jdbc.pool.DataSource) bean;
assertEquals("org.hsqldb.jdbcDriver", pool.getDriverClassName());
assertEquals("sa", pool.getUsername());
}
@Test
public void testExplicitDriverClassClearsUserName() throws Exception {
TestUtils.addEnviroment(this.context,
"spring.datasource.driverClassName:com.mysql.jdbc.Driver",
"spring.datasource.url:jdbc:mysql://localhost");
this.context.register(DataSourceAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
DataSource bean = this.context.getBean(DataSource.class);
assertNotNull(bean);
org.apache.tomcat.jdbc.pool.DataSource pool = (org.apache.tomcat.jdbc.pool.DataSource) bean;
assertEquals("com.mysql.jdbc.Driver", pool.getDriverClassName());
assertNull(pool.getUsername());
}
@Test
public void testDefaultDataSourceCanBeOverridden() throws Exception {
this.context.register(TestDataSourceConfiguration.class,

View File

@ -28,6 +28,7 @@
<log4j.version>1.2.17</log4j.version>
<logback.version>1.0.13</logback.version>
<mockito.version>1.9.5</mockito.version>
<mysql.version>5.1.23</mysql.version>
<reactor.version>1.0.0.M3</reactor.version>
<servlet-api.version>3.0.1</servlet-api.version>
<slf4j.version>1.7.5</slf4j.version>
@ -104,6 +105,11 @@
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>