Tag Archives: Cannot determine embedded database driver class for database type NONE

How to Solve Cannot determine embedded database driver class for database type NONE

Debug and check the error of cannot determine embedded database driver class for database type none
import the project into IDE and start the application directly. The exception information thrown out is:

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-11-29 14:26:34.478 ERROR 29736 --- [      main] o.s.b.d.LoggingFailureAnalysisReporter  :

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database driver class for database type NONE

Action:

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).

in fact, there are two ideas at this time. You can find a solution by directly Google searching cannot determine embedded database driver class for database type none

The second way is to display the auto configuration report re run your application with ‘debug’ enabled

By searching this, you can find relevant information on spring’s official website: https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html

That is, as long as the user configures the debug switch, the auto configuration related information will be printed out

If you are familiar with spring’s environment variable injection, you can know that there are several ways to open it

Add — debug in args
Add debug = true in application.properties
through – ddebug = true
add the information after the debug switch
after adding the debug switch, you can see that the error stack is printed:

2017-11-29 14:33:08.776 DEBUG 29907 --- [      main] o.s.b.d.LoggingFailureAnalysisReporter  : Application failed to start due to an exception

org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. 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).
 at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:245) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
 at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:182) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
 at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:42) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
 at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat.dataSource(DataSourceConfiguration.java:53) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]

The code that throws an exception is:

/**
  * Determine the driver to use based on this configuration and the environment.
  * @return the driver to use
  * @since 1.4.0
  */
 public String determineDriverClassName() {
  if (StringUtils.hasText(this.driverClassName)) {
   Assert.state(driverClassIsLoadable(),
     "Cannot load driver class: " + this.driverClassName);
   return this.driverClassName;
  }
  String driverClassName = null;

  if (StringUtils.hasText(this.url)) {
   driverClassName = DatabaseDriver.fromJdbcUrl(this.url).getDriverClassName();
  }

  if (!StringUtils.hasText(driverClassName)) {
   driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
  }

  if (!StringUtils.hasText(driverClassName)) {
   throw new DataSourceBeanCreationException(this.embeddedDatabaseConnection,
     this.environment, "driver class");
  }
  return driverClassName;
 }

it can be seen that the driver class of datasource was not found, and then the datasourcebancecreationexception was thrown

One solution is to add some datasource driver classes to Maven dependencies

But the application does not use datasource in its own code. What causes spring boot to create a datasource object?What causes spring boot to create a datasource
from the exception stack, you can find the class datasourceconfiguration $tomcat, then you can find its reference, and you can find that it is used

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.PooledDataSourceConfiguration import引入的。

 @Configuration
 @Conditional(PooledDataSourceCondition.class)
 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
 @Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
   DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
   DataSourceConfiguration.Generic.class })
 protected static class PooledDataSourceConfiguration {

 }

so how does pooleddatasourceconfiguration work?You can see @ conditional (pooleddatasourcecondition. Class) from the code

Let’s look at the concrete implementation of pooleddatasourcecondition

/**
  * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
  * is set or {@link PooledDataSourceAvailableCondition} applies.
  */
 static class PooledDataSourceCondition extends AnyNestedCondition {

  PooledDataSourceCondition() {
   super(ConfigurationPhase.PARSE_CONFIGURATION);
  }

  @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
  static class ExplicitType {

  }

  @Conditional(PooledDataSourceAvailableCondition.class)
  static class PooledDataSourceAvailable {

  }

 }
PooledDataSourceCondition import @Conditional(PooledDataSourceAvailableCondition.class) :

 /**
  * {@link Condition} to test if a supported connection pool is available.
  */
 static class PooledDataSourceAvailableCondition extends SpringBootCondition {

  @Override
  public ConditionOutcome getMatchOutcome(ConditionContext context,
    AnnotatedTypeMetadata metadata) {
   ConditionMessage.Builder message = ConditionMessage
     .forCondition("PooledDataSource");
   if (getDataSourceClassLoader(context) != null) {
    return ConditionOutcome
      .match(message.foundExactly("supported DataSource"));
   }
   return ConditionOutcome
     .noMatch(message.didNotFind("supported DataSource").atAll());
  }

  /**
   * Returns the class loader for the {@link DataSource} class. Used to ensure that
   * the driver class can actually be loaded by the data source.
   * @param context the condition context
   * @return the class loader
   */
  private ClassLoader getDataSourceClassLoader(ConditionContext context) {
   Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
     .findType();
   return (dataSourceClass == null ?null : dataSourceClass.getClassLoader());
  }

 }

from the code, you can see that you are trying to find the datasourceclass. If you find it, the condition holds. Under debug, you can find that the datasourceclass you find is org. Apache. Tomcat. JDBC. Pool. Datasource

So let’s see where the class org. Apache. Tomcat. JDBC. Pool. Datasource comes from

From the Maven dependency tree, we can see that the dependencies come from spring boot starter JDBC. So the application relies on spring boot starter JDBC, but does not configure datasource

There are two ways to solve the problem

If the datasource is not used, the spring boot starter JDBC dependency can be removed, so that the spring boot related code will not be triggered
to disable the spring boot automatically initializing the datasource related code
there are two ways to disable it:

Configure exclude on main function

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })

Configure in application.properties:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration

summary
the application does not use datasource, but introduces spring boot starter JDBC into pom.xml
spring boot starter JDBC brings Tomcat JDBC, which contains the pooleddatasource configuration in org.apache.tomcat.jdbc.pool.datasource
spring boot, and judges that there are datasource implementation classes under classpath, Try to create a datasource bean
when initializing datasourceproperties, try to detect the driver class through the URL of JDBC
because the application does not configure the URL, so finally throw cannot determine embedded database driver class for database type none in datasourceproperties. Determinedriverclassname()
finally:

When troubleshooting the autoconfiguration problem of spring boot, you can check how configuration is introduced layer by layer according to the exception stack, and then check the specific judgment code of condition