Commit 97e6d777 authored by Dave Syer's avatar Dave Syer

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
parent c29d2b1b
...@@ -174,6 +174,11 @@ ...@@ -174,6 +174,11 @@
<artifactId>hsqldb</artifactId> <artifactId>hsqldb</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
......
...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jdbc; ...@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.jdbc;
import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanCreationException; 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.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
...@@ -29,15 +30,16 @@ import org.springframework.util.StringUtils; ...@@ -29,15 +30,16 @@ import org.springframework.util.StringUtils;
*/ */
@ConfigurationProperties(name = DataSourceAutoConfiguration.CONFIGURATION_PREFIX) @ConfigurationProperties(name = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
@EnableConfigurationProperties @EnableConfigurationProperties
public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware { public abstract class AbstractDataSourceConfiguration implements BeanClassLoaderAware,
InitializingBean {
private String driverClassName; private String driverClassName;
private String url; private String url;
private String username = "sa"; private String username;
private String password = ""; private String password;
private int maxActive = 100; private int maxActive = 100;
...@@ -53,41 +55,67 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader ...@@ -53,41 +55,67 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader
private ClassLoader classLoader; private ClassLoader classLoader;
private EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection.NONE;
@Override @Override
public void setBeanClassLoader(ClassLoader classLoader) { public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader; this.classLoader = classLoader;
} }
@Override
public void afterPropertiesSet() throws Exception {
this.embeddedDatabaseConnection = EmbeddedDatabaseConnection
.get(this.classLoader);
}
protected String getDriverClassName() { protected String getDriverClassName() {
if (StringUtils.hasText(this.driverClassName)) { if (StringUtils.hasText(this.driverClassName)) {
return this.driverClassName; return this.driverClassName;
} }
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection String driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
.get(this.classLoader); if (!StringUtils.hasText(driverClassName)) {
this.driverClassName = embeddedDatabaseConnection.getDriverClassName();
if (!StringUtils.hasText(this.driverClassName)) {
throw new BeanCreationException( throw new BeanCreationException(
"Cannot determine embedded database driver class for database type " "Cannot determine embedded database driver class for database type "
+ embeddedDatabaseConnection + ". If you want an embedded " + this.embeddedDatabaseConnection
+ "database please put a supoprted one on the classpath."); + ". If you want an embedded "
+ "database please put a supported one on the classpath.");
} }
return this.driverClassName; return driverClassName;
} }
protected String getUrl() { protected String getUrl() {
if (StringUtils.hasText(this.url)) { if (StringUtils.hasText(this.url)) {
return this.url; return this.url;
} }
EmbeddedDatabaseConnection embeddedDatabaseConnection = EmbeddedDatabaseConnection String url = this.embeddedDatabaseConnection.getUrl();
.get(this.classLoader); if (!StringUtils.hasText(url)) {
this.url = embeddedDatabaseConnection.getUrl();
if (!StringUtils.hasText(this.url)) {
throw new BeanCreationException( throw new BeanCreationException(
"Cannot determine embedded database url for database type " "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."); + "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) { public void setDriverClassName(String driverClassName) {
...@@ -130,14 +158,6 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader ...@@ -130,14 +158,6 @@ public abstract class AbstractDataSourceConfiguration implements BeanClassLoader
this.testOnReturn = testOnReturn; this.testOnReturn = testOnReturn;
} }
protected String getUsername() {
return this.username;
}
protected String getPassword() {
return this.password;
}
protected int getMaxActive() { protected int getMaxActive() {
return this.maxActive; return this.maxActive;
} }
......
...@@ -49,8 +49,12 @@ public class CommonsDataSourceConfiguration extends AbstractDataSourceConfigurat ...@@ -49,8 +49,12 @@ public class CommonsDataSourceConfiguration extends AbstractDataSourceConfigurat
this.pool = new BasicDataSource(); this.pool = new BasicDataSource();
this.pool.setDriverClassName(getDriverClassName()); this.pool.setDriverClassName(getDriverClassName());
this.pool.setUrl(getUrl()); this.pool.setUrl(getUrl());
this.pool.setUsername(getUsername()); if (getUsername() != null) {
this.pool.setPassword(getPassword()); this.pool.setUsername(getUsername());
}
if (getPassword() != null) {
this.pool.setPassword(getPassword());
}
this.pool.setMaxActive(getMaxActive()); this.pool.setMaxActive(getMaxActive());
this.pool.setMaxIdle(getMaxIdle()); this.pool.setMaxIdle(getMaxIdle());
this.pool.setMinIdle(getMinIdle()); this.pool.setMinIdle(getMinIdle());
......
...@@ -88,6 +88,20 @@ public enum EmbeddedDatabaseConnection { ...@@ -88,6 +88,20 @@ public enum EmbeddedDatabaseConnection {
*/ */
static EmbeddedDatabaseConnection override; 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 * Returns the most suitable {@link EmbeddedDatabaseConnection} for the given class
* loader. * loader.
......
...@@ -39,8 +39,12 @@ public class TomcatDataSourceConfiguration extends AbstractDataSourceConfigurati ...@@ -39,8 +39,12 @@ public class TomcatDataSourceConfiguration extends AbstractDataSourceConfigurati
this.pool = new org.apache.tomcat.jdbc.pool.DataSource(); this.pool = new org.apache.tomcat.jdbc.pool.DataSource();
this.pool.setDriverClassName(getDriverClassName()); this.pool.setDriverClassName(getDriverClassName());
this.pool.setUrl(getUrl()); this.pool.setUrl(getUrl());
this.pool.setUsername(getUsername()); if (getUsername() != null) {
this.pool.setPassword(getPassword()); this.pool.setUsername(getUsername());
}
if (getPassword() != null) {
this.pool.setPassword(getPassword());
}
this.pool.setMaxActive(getMaxActive()); this.pool.setMaxActive(getMaxActive());
this.pool.setMaxIdle(getMaxIdle()); this.pool.setMaxIdle(getMaxIdle());
this.pool.setMinIdle(getMinIdle()); this.pool.setMinIdle(getMinIdle());
......
...@@ -23,6 +23,7 @@ import javax.sql.DataSource; ...@@ -23,6 +23,7 @@ import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.TestUtils;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -35,6 +36,7 @@ import org.springframework.util.ClassUtils; ...@@ -35,6 +36,7 @@ import org.springframework.util.ClassUtils;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
...@@ -54,6 +56,36 @@ public class DataSourceAutoConfigurationTests { ...@@ -54,6 +56,36 @@ public class DataSourceAutoConfigurationTests {
assertNotNull(this.context.getBean(DataSource.class)); 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 @Test
public void testDefaultDataSourceCanBeOverridden() throws Exception { public void testDefaultDataSourceCanBeOverridden() throws Exception {
this.context.register(TestDataSourceConfiguration.class, this.context.register(TestDataSourceConfiguration.class,
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
<log4j.version>1.2.17</log4j.version> <log4j.version>1.2.17</log4j.version>
<logback.version>1.0.13</logback.version> <logback.version>1.0.13</logback.version>
<mockito.version>1.9.5</mockito.version> <mockito.version>1.9.5</mockito.version>
<mysql.version>5.1.23</mysql.version>
<reactor.version>1.0.0.M3</reactor.version> <reactor.version>1.0.0.M3</reactor.version>
<servlet-api.version>3.0.1</servlet-api.version> <servlet-api.version>3.0.1</servlet-api.version>
<slf4j.version>1.7.5</slf4j.version> <slf4j.version>1.7.5</slf4j.version>
...@@ -104,6 +105,11 @@ ...@@ -104,6 +105,11 @@
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
<version>${log4j.version}</version> <version>${log4j.version}</version>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency> <dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId> <groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId> <artifactId>thymeleaf-layout-dialect</artifactId>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment