0

I am getting the following error with tomcat:

09:06:18,168 WARNING [org.apache.tomcat.jdbc.pool.PooledConnection] (ServerService Thread Pool -- 6) Not loading a JDBC driver as driverClassName property is null.
09:06:18,170 SEVERE [org.apache.tomcat.jdbc.pool.ConnectionPool] (ServerService Thread Pool -- 6) Unable to create initial connections of pool.: java.sql.SQLException: The url cannot be null

I have ran this both in JBOSS and the embedded tomcat server and still got this error. I even took out the jar files from the war from and ran it from JBOSS and still got the same error.

I am able to create the EntityMangers but before they are created I get the above error. The program continues to run than complains about a class is not a managed type. However those @Entities are being scanned.

I get the same error with JBOSS:

09:06:18,171 WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (ServerService Thread Pool -- 6) HHH000342: Could not obtain connection to query metadata : The url cannot be null
09:06:18,183 INFO  [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 6) HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
09:06:18,199 INFO  [org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl] (ServerService Thread Pool -- 6) HHH000422: Disabling contextual LOB creation as connection was null

DataSources:

@Configuration
@PropertySource("classpath:application.yml")
public class MainDataSourceConfig {
    
    /*******************************
     *       Datasource     *
     * *****************************/
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.dataSource.Main")
    public DataSource mainDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /*******************************
     *  Transaction manager *
     * *****************************/
    @Bean
    @Primary
    DataSourceTransactionManager transactionManager(@Qualifier("mainDataSource") DataSource datasource) {
        DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
        return txm;
    }
    
    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("mainDataSource")DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setPersistenceUnitName("mainEntityManger");
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
        entityManagerFactory.setPackagesToScan("com.customers.domain");
        
        entityManagerFactory.setJpaProperties(additionalProperties());
        return entityManagerFactory;
    }
    
    private Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.ddl-auto","none");
        return properties;
    }
    
}

Second DataSource

@Configuration
@PropertySource("classpath:application.yml")
public class SecondDataSourceConfig {
    
    /*******************************
     *      Datasource      *
     * *****************************/
    @Bean
    @ConfigurationProperties(prefix="spring.dataSource.Second")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /*******************************
     *  Transaction manager *
     * *****************************/
    @Bean
    DataSourceTransactionManager transactionManager(@Qualifier("secondDataSource") DataSource datasource) {
        DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
        return txm;
    }
    
    @Bean
    public LocalContainerEntityManagerFactoryBean keyviewEntityMangerFactory(@Qualifier("secondDataSource") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setPersistenceUnitName("secondEntityManger");
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
        entityManagerFactory.setPackagesToScan("com.statements.domain");
        entityManagerFactory.setJpaProperties(additionalProperties());
        
        return entityManagerFactory;
    }
    
    private Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.ddl-auto","none");
        
        return properties;
    }
            
}

application.yml

#Spring Boot Config for Oracle
spring:
  dataSource:
    Main:
      url: [url]
      username: [username]
      password: [password]
      driverClassName: oracle.jdbc.OracleDriver

    Second:
      url: [url]
      username: [username]
      password: [password]
      driverClassName: oracle.jdbc.OracleDriver

    tomcat:
      min-idle: 1

# Spring Boot Actuator settings
#https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
endpoints.health.sensitive: false
#management.security.enabled: true
management.context-path: /healthCheck

endpoints.info.id: info
endpoints.info.sensitive: false
endpoints.info.enabled: true
info.app.name: Request
info.app.description: Request Description
info.app.version: 0.0.1-SNAPSHO

I have been at this for over a week I cannot figure out why it is saying the url is null and later when the entityManagers are created saying one of my domain packages are not a managed type. It seems to have an issue scanning second set of packages. I confirmed this changing the class names since I noticed it was compiled it alphabetical order and when I did that it changed which package it was complaining about. #note: It picks a different class every time I run it of that same package and they are @Entity annotated.

I am also using @EntityScan, @ComponentScan , @SpringBootApplication, @EnableAutoConfiguration on the main method.

NOTE: When I remove the second Datasource everything works fine. This only happens when I bring in the second one.

------------------------Update 1-----------------------------------

I just put the dataSource information into two different yml files and still got the same error. Then I decided to take out the main data source out and just implement the second as the only one in the project. THEN I got the same error. However the URI and everything are correct, not sure why this is happening.

Community
  • 1
  • 1
Mike3355
  • 11,305
  • 24
  • 96
  • 184

2 Answers2

2

I recently ran into a similar issue while creating a test harness using spring boot (no SpringBootApplication annotation) and I eventually found that I needed to use a data source properties and explicitly specify @EnableConfigurationProperties in the configuration class:

@Configuration
@EnableConfigurationProperties(value = DataSourceProperties.class)
public class ....

Defined beans for the data source properties:

@Bean(name = "ds1Props")
@ConfigurationProperties(prefix = "path.to.ds1.properties")
public DataSourceProperties ds1DataSourceProperties() {
    return new DataSourceProperties();
}

@Bean(name = "ds2Props")
@ConfigurationProperties(prefix = "path.to.ds2.properties")
public DataSourceProperties ds2DataSourceProperties() {
    return new DataSourceProperties();
}

And then inject them into the data source bean methods:

@Bean
public DataSource dataSource1(@Qualifier("ds1Props") DataSourceProperties ds1Props) {
    return ds1Props.initializeDataSourceBuilder().build();
}

@Bean
public DataSource dataSource2(@Qualifier("ds2Props") DataSourceProperties ds2Props) {
    return ds2Props.initializeDataSourceBuilder().build();
}

Hope this helps or gets you going. I was unsure as to why I needed to explicitly set this as its part of the jdbc auto configuration. ( i think it may be because the spring boot datasource configuration may be processed after my data source configuration)

--- Update: Working sample based on original source, modified to match my db environment, using spring boot 1.3.1 with starter web and starter jpa packages. The @Primary's are required to fulfil dependencies to the auto configured DataSourceInitializer and OpenSessionInViewInterceptor.

@SpringBootApplication
public class Application {

public static void main(String[] args) {
    SpringApplication.run(new Object[] { Application.class }, args);
}

@Primary
@Bean
@ConfigurationProperties(prefix = "spring.dataSource.Main")
public DataSource mainDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
DataSourceTransactionManager mainTransactionManager(@Qualifier("mainDataSource") DataSource datasource) {
    DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
    return txm;
}

@Primary
@Bean
public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory(
        @Qualifier("mainDataSource") DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setPersistenceUnitName("mainEntityManger");
    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
    entityManagerFactory.setPackagesToScan("com.sbp.domain.main");
    entityManagerFactory.setJpaProperties(additionalProperties());
    return entityManagerFactory;
}

@Bean
@ConfigurationProperties(prefix = "spring.dataSource.Second")
public DataSource secondDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean
DataSourceTransactionManager secondTransactionManager(@Qualifier("secondDataSource") DataSource datasource) {
    DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
    return txm;
}

@Bean
public LocalContainerEntityManagerFactoryBean secondEntityMangerFactory(
        @Qualifier("secondDataSource") DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setPersistenceUnitName("secondEntityManger");
    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
    entityManagerFactory.setPackagesToScan("com.sbp.domain.second");
    entityManagerFactory.setJpaProperties(additionalProperties());
    return entityManagerFactory;
}

private Properties additionalProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    properties.setProperty("hibernate.ddl-auto", "none");
    return properties;
}
}
Bob Lukens
  • 700
  • 6
  • 10
  • I did what you said and things are looking positive but now it says 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).` – Mike3355 Dec 02 '16 at 17:19
  • But it only says it for the second datasource. `Unsatisfied dependency expressed through method 'secondEntityMangerFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException:` – Mike3355 Dec 02 '16 at 17:23
  • Can you share the spring boot version and the boot packages you are pulling in? I took your original code above, created a project using started web and starter jpa and was able to start the application with no errors. – Bob Lukens Dec 03 '16 at 03:50
  • also - here is another post with an alternate implementation but good details. http://stackoverflow.com/questions/26308035/spring-boot-spring-data-jpa-with-multiple-datasources – Bob Lukens Dec 03 '16 at 03:59
  • here is the full source of the app I created using your original source code: – Bob Lukens Dec 03 '16 at 04:19
0

You'll need to setup two sets of beans with unique names (ie transactionManager2)

Get rid of the @Primary - that says take this bean over the other. In this case you need both beans in the context - hence the need for unique names.

see: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html

If you're using Spring Data JPA do:

@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
        entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
    ...
}

@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
        entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
    ...
}
John Thompson
  • 514
  • 3
  • 7