Commit e66745a9 authored by Patryk Kostrzewa's avatar Patryk Kostrzewa Committed by Stephane Nicoll

Improve FailureAnalyzer for embedded datasource

See gh-11953
parent 2b9006b3
...@@ -16,26 +16,72 @@ ...@@ -16,26 +16,72 @@
package org.springframework.boot.autoconfigure.jdbc; package org.springframework.boot.autoconfigure.jdbc;
import java.util.Objects;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.DataSourceBeanCreationException; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.DataSourceBeanCreationException;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/** /**
* An {@link AbstractFailureAnalyzer} for failures caused by a * An {@link AbstractFailureAnalyzer} for failures caused by a
* {@link DataSourceBeanCreationException}. * {@link DataSourceBeanCreationException}.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Patryk Kostrzewa
*/ */
class DataSourceBeanCreationFailureAnalyzer class DataSourceBeanCreationFailureAnalyzer
extends AbstractFailureAnalyzer<DataSourceBeanCreationException> { extends AbstractFailureAnalyzer<DataSourceBeanCreationException>
implements EnvironmentAware {
private Environment environment;
@Override @Override
protected FailureAnalysis analyze(Throwable rootFailure, protected FailureAnalysis analyze(Throwable rootFailure,
DataSourceBeanCreationException cause) { DataSourceBeanCreationException cause) {
String message = cause.getMessage(); return getFailureAnalysis(cause);
String description = message.substring(0, message.indexOf('.')).trim(); }
String action = message.substring(message.indexOf('.') + 1).trim();
return new FailureAnalysis(description, action, cause); @Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
private FailureAnalysis getFailureAnalysis(DataSourceBeanCreationException cause) {
final EmbeddedDatabaseConnection connection = cause.getConnection();
final String action;
if (EmbeddedDatabaseConnection.NONE == connection) {
action = "If you want an embedded database "
+ "please put a supported one on the classpath.";
}
else {
action = "If you have database settings to be loaded "
+ "from a particular profile you may need to activate it"
+ getActiveProfiles();
} }
return new FailureAnalysis(cause.getMessage(), action, cause);
}
private String getActiveProfiles() {
final StringBuilder message = new StringBuilder();
if (Objects.nonNull(this.environment)) {
String[] profiles = this.environment.getActiveProfiles();
if (ObjectUtils.isEmpty(profiles)) {
message.append(" (no profiles are currently active).");
}
else {
message.append(" (the profiles ");
message.append(StringUtils.arrayToCommaDelimitedString(profiles));
message.append(" are currently active).");
}
}
return message.toString();
}
} }
...@@ -32,11 +32,8 @@ import org.springframework.boot.jdbc.DataSourceBuilder; ...@@ -32,11 +32,8 @@ import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DataSourceInitializationMode; import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection; import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
...@@ -47,16 +44,15 @@ import org.springframework.util.StringUtils; ...@@ -47,16 +44,15 @@ import org.springframework.util.StringUtils;
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Benedikt Ritter * @author Benedikt Ritter
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Patryk Kostrzewa
* @since 1.1.0 * @since 1.1.0
*/ */
@ConfigurationProperties(prefix = "spring.datasource") @ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean { implements BeanClassLoaderAware, InitializingBean {
private ClassLoader classLoader; private ClassLoader classLoader;
private Environment environment;
/** /**
* Name of the datasource. Default to "testdb" when using an embedded database. * Name of the datasource. Default to "testdb" when using an embedded database.
*/ */
...@@ -166,11 +162,6 @@ public class DataSourceProperties ...@@ -166,11 +162,6 @@ public class DataSourceProperties
this.classLoader = classLoader; this.classLoader = classLoader;
} }
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
this.embeddedDatabaseConnection = EmbeddedDatabaseConnection this.embeddedDatabaseConnection = EmbeddedDatabaseConnection
...@@ -244,8 +235,9 @@ public class DataSourceProperties ...@@ -244,8 +235,9 @@ public class DataSourceProperties
driverClassName = this.embeddedDatabaseConnection.getDriverClassName(); driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
} }
if (!StringUtils.hasText(driverClassName)) { if (!StringUtils.hasText(driverClassName)) {
throw new DataSourceBeanCreationException(this.embeddedDatabaseConnection, throw new DataSourceBeanCreationException(
this.environment, "driver class"); "Failed to determine a suitable driver class",
this.embeddedDatabaseConnection);
} }
return driverClassName; return driverClassName;
} }
...@@ -290,8 +282,9 @@ public class DataSourceProperties ...@@ -290,8 +282,9 @@ public class DataSourceProperties
String url = (databaseName == null ? null String url = (databaseName == null ? null
: this.embeddedDatabaseConnection.getUrl(databaseName)); : this.embeddedDatabaseConnection.getUrl(databaseName));
if (!StringUtils.hasText(url)) { if (!StringUtils.hasText(url)) {
throw new DataSourceBeanCreationException(this.embeddedDatabaseConnection, throw new DataSourceBeanCreationException(
this.environment, "url"); "Failed to determine suitable jdbc url",
this.embeddedDatabaseConnection);
} }
return url; return url;
} }
...@@ -522,37 +515,17 @@ public class DataSourceProperties ...@@ -522,37 +515,17 @@ public class DataSourceProperties
static class DataSourceBeanCreationException extends BeanCreationException { static class DataSourceBeanCreationException extends BeanCreationException {
DataSourceBeanCreationException(EmbeddedDatabaseConnection connection, private final EmbeddedDatabaseConnection connection;
Environment environment, String property) {
super(getMessage(connection, environment, property));
}
private static String getMessage(EmbeddedDatabaseConnection connection, DataSourceBeanCreationException(String message,
Environment environment, String property) { EmbeddedDatabaseConnection connection) {
StringBuilder message = new StringBuilder();
message.append("Cannot determine embedded database " + property
+ " for database type " + connection + ". ");
message.append("If you want an embedded database please put a supported "
+ "one on the classpath. ");
message.append("If you have database settings to be loaded from a "
+ "particular profile you may need to active it");
if (environment != null) {
String[] profiles = environment.getActiveProfiles();
if (ObjectUtils.isEmpty(profiles)) {
message.append(" (no profiles are currently active)");
}
else {
message.append(" (the profiles \""
+ StringUtils.arrayToCommaDelimitedString(
environment.getActiveProfiles())
+ "\" are currently active)");
} super(message);
} this.connection = connection;
message.append(".");
return message.toString();
} }
public EmbeddedDatabaseConnection getConnection() {
return this.connection;
}
} }
} }
...@@ -41,12 +41,8 @@ public class DataSourceBeanCreationFailureAnalyzerTests { ...@@ -41,12 +41,8 @@ public class DataSourceBeanCreationFailureAnalyzerTests {
@Test @Test
public void failureAnalysisIsPerformed() { public void failureAnalysisIsPerformed() {
FailureAnalysis failureAnalysis = performAnalysis(TestConfiguration.class); FailureAnalysis failureAnalysis = performAnalysis(TestConfiguration.class);
assertThat(failureAnalysis.getDescription()).isEqualTo( assertThat(failureAnalysis.getDescription()).isEqualTo("Failed to determine a suitable driver class");
"Cannot determine embedded database driver class for database type NONE"); assertThat(failureAnalysis.getAction()).isEqualTo("If you want an embedded database please put a supported one on the classpath.");
assertThat(failureAnalysis.getAction()).isEqualTo("If you want an embedded "
+ "database please put a supported one on the classpath. If you have "
+ "database settings to be loaded from a particular profile you may "
+ "need to active it (no profiles are currently active).");
} }
private FailureAnalysis performAnalysis(Class<?> configuration) { private FailureAnalysis performAnalysis(Class<?> configuration) {
......
...@@ -72,7 +72,7 @@ public class DataSourcePropertiesTests { ...@@ -72,7 +72,7 @@ public class DataSourcePropertiesTests {
new FilteredClassLoader("org.h2", "org.apache.derby", "org.hsqldb")); new FilteredClassLoader("org.h2", "org.apache.derby", "org.hsqldb"));
properties.afterPropertiesSet(); properties.afterPropertiesSet();
this.thrown.expect(DataSourceProperties.DataSourceBeanCreationException.class); this.thrown.expect(DataSourceProperties.DataSourceBeanCreationException.class);
this.thrown.expectMessage("Cannot determine embedded database url"); this.thrown.expectMessage("Failed to determine suitable jdbc url");
properties.determineUrl(); properties.determineUrl();
} }
......
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