5

I want to configure two datasources in my SpringBoot (version 2.4) application.

Below is the application.properties:

spring.datasource2.url=jdbc:postgresql://localhost:5432/db1
spring.datasource2.username=//username
spring.datasource2.password=//pwd
spring.datasource2.initialization-mode=always
spring.datasource2.driver-class-name=org.postgresql.Driver

spring.datasource1.url=jdbc:postgresql://localhost:5432/db2
spring.datasource1.username=//usrename
spring.datasource1.password=//pwd
spring.datasource1.initialization-mode=always
spring.datasource1.driver-class-name=org.postgresql.Driver

spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.hibernate.show-sql=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.id.new_generator_mappings=false
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

spring.h2.console.enabled=true
spring.datasource.continue-on-error=true

spring.servlet.multipart.max-file-size=50MB

spring.servlet.multipart.max-request-size=50MB


project.http.enable=false
project.https.port=9090

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

server.os=LINUX

dl.writeTOFile=false
dl.writeTOConsole=true

Below is my pom.xml:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- marked the embedded servlet container as provided -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.4.0</version>
        </dependency>

When I run the application, I get the following error:

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

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
    If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

When I add one datasource as Spring.datasource and other as Spring.datasource1, application starts up fine but it is looking into the DB configured in Spring.datasource only.

Following is the DB1 Config class:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories( entityManagerFactoryRef = "DB1EntityManagerFactory", transactionManagerRef = "DB1TransactionManager",    basePackages = {
    "com.datasource1.repository" } )
@EntityScan("com.datasource1.entity" )
public class Db1Config {
    
        @Primary
        @Bean
        @ConfigurationProperties("spring.datasource")
        public DataSourceProperties SourceProperties() {
            return new DataSourceProperties();
        }
        
        @Primary
        @Bean( name = "DB1Datasource" )
        @ConfigurationProperties( prefix = "spring.datasource.configuration" )
        public DataSource dataSource()
        {
            return SourceProperties().initializeDataSourceBuilder()
                    .type(HikariDataSource.class).build();
        }
        
        @Primary
        @Bean( name = "DB1EntityManagerFactory" )
        public LocalContainerEntityManagerFactoryBean barEntityManagerFactory( EntityManagerFactoryBuilder builder,
                @Qualifier( "DB1Datasource" ) DataSource dataSource )
        {
            return builder.dataSource(dataSource).packages("com.datasource1.entity")
                    .persistenceUnit("db1").build();
        }
        
        @Primary
        @Bean( name = "DB1TransactionManager" )
        public PlatformTransactionManager barTransactionManager(
                @Qualifier( "DB1EntityManagerFactory" ) EntityManagerFactory barEntityManagerFactory )
        {
            return new JpaTransactionManager(barEntityManagerFactory);
        }
}

Following is the DB2Config:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories( entityManagerFactoryRef = "DB2EntityManagerFactory", transactionManagerRef = "DB2TransactionManager",    basePackages = {
    "com.DB2.repository" } )
@EntityScan( "com.DB2.entity" )
public class Db2Config {
    
        @Bean
        @ConfigurationProperties("spring.datasource2")
        public DataSourceProperties DB2SourceProperties() {
            return new DataSourceProperties();
        }

        
        @Bean( name = "DB2Datasource" )
        @ConfigurationProperties( prefix = "spring.datasource2.configuration" )
        public DataSource dataSource()
        {
            return DB2SourceProperties().initializeDataSourceBuilder()
                    .type(HikariDataSource.class).build();
        }
        
        @Bean( name = "DB2EntityManagerFactory" )
        public LocalContainerEntityManagerFactoryBean barEntityManagerFactory( EntityManagerFactoryBuilder builder,
                @Qualifier( "DB2Datasource" ) DataSource dataSource )
        {
            return builder.dataSource(dataSource).packages("com.DB2.entity")
                    .persistenceUnit("db2").build();
        }
        
        @Bean( name = "DB2TransactionManager" )
        public PlatformTransactionManager barTransactionManager(
                @Qualifier( "DB2EntityManagerFactory" ) EntityManagerFactory barEntityManagerFactory )
        {
            return new JpaTransactionManager(barEntityManagerFactory);
        }
}

How do I resolve this issue?

code-geek
  • 441
  • 1
  • 8
  • 22
  • Have you read [this](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources)? – M. Deinum Dec 07 '20 at 14:33
  • @M.Deinum, Yes I have added the necessary configuration classes. Still I face the issue – code-geek Dec 07 '20 at 14:38
  • 1
    You are binding `spring.datasource` while your properties are named `spring.datasource1` that is not going to work. – M. Deinum Dec 07 '20 at 18:32

2 Answers2

3

You should change

spring.datasource1.url=jdbc:postgresql://localhost:5432/db2

to

spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/db2

Not sure why this is the case and the docs don't say so, but I had this issue and this did the trick for me

Edit: As @M. Deinum mentioned in his comment: These

        @ConfigurationProperties("spring.datasource")
        (...)
        @ConfigurationProperties( prefix = "spring.datasource.configuration" )

should be changed to

        @ConfigurationProperties("spring.datasource1")
        (...)
        @ConfigurationProperties( prefix = "spring.datasource1.configuration" )
Amir Schnell
  • 611
  • 4
  • 11
  • Thank you. I tried this already but didn't work:( – code-geek Dec 07 '20 at 16:08
  • have you tried setting `jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect` ? – Amir Schnell Dec 07 '20 at 16:11
  • [https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.data](https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.data) states that the property name is `spring.datasource.username`. – Pierre C Dec 17 '21 at 22:17
1

i faced this issue after creating "project.jar" while in IDE / STS (spring tool suit) it was working fine.

unnecessary spaces " " in the "application.yml" file can cause this.

server:
  port: 8085


spring:
 datasource:
  url: jdbc:mysql://localhost:3306/studentdb
  username: root
  password: root
  driver-class-name: com.mysql.cj.jdbc.Driver
 jpa:
   hibernate:
    ddl-auto: update
   show-sql: true
   database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
 application:
  name: STUDENT-SERVICE

instead of tweaking my "application.yml" file
i simply moved all my statements in "application.yml" file to
"application.properties" file and formatted the statements like required in ".properties".

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/studentdb
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format.sql=true

spring.application.name=student-service

server.port=8085

(you can add params at the end of url)
(spring.datasource.url=jdbc:mysql://localhost:3306/studentdb?allowPublicKeyRetrieval=true&useSSL=false)

and voilà

sifr_dot_in
  • 3,153
  • 2
  • 33
  • 42