How Spring boot injects different datasources into JdbcTemplate in different profiles

Viewed 126

I have a Spring boot application that uses H2 in memory database for local development (default profile) and Postgresql for dev environment (dev profile).

I have added both H2 and postgresql in pom.xml

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>

In application.yml I am configuring H2

spring:
  datasource:
    url: jdbc:h2:mem:quizdb
    username: quizdb_user
    password: mypassword
    driverClassName: org.h2.Driver

  h2:
    console:
      enabled: true

in application-dev.yml I am configuring postgresql

spring:
    pgdatasource:
      pgurl: jdbc:postgresql://localhost:5432/quizdb
      pgusername: quizdb_user
      pgpassword: mypassword
      pgdriverClassName: org.postgresql.Driver

Also, I am creating postgresql dataSourceBean manually from a configuration class as follow, that will trigger only for dev profile:

@Configuration

@Profile("dev")

public class AppConfiguration {
    
    @Bean
    public DataSource dataSource(Environment env)
    {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(env.getProperty("spring.pgdatasource.pgdriverClassName"));
        hikariConfig.setJdbcUrl(env.getProperty("spring.pgdatasource.pgurl")); 
        hikariConfig.setUsername(env.getProperty("spring.pgdatasource.pgusername"));
        hikariConfig.setPassword(env.getProperty("spring.pgdatasource.pgpassword"));

        hikariConfig.setMaximumPoolSize(5);
        hikariConfig.setPoolName("springHikariCP");

        HikariDataSource dataSource = new HikariDataSource(hikariConfig);

        return dataSource;
    }
}

When I run the application in default profile, it invoked H2 and with dev profile (Adding VM argument: -Dspring.profiles.active=dev) it invoked postgresql.

I am accessing the database through JdbcTemplate and when I print the underlying datasource, it correctly shows H2 datasource for local (default profile) and postgresql for dev profile. In other words it works as expected.

However, I fail to understand following:

When running in dev profile, then also H2 datasource is being created since H2 is added in pom.xml and explicitly configured in application.yml (which is read first in dev profile). So, I guess in dev profile, it creates 2 Hikari datasources, one with H2 and one with postgresql. Then in dev profile, how spring boot is automatically (and correctly) injecting postgresql datasource to JdbcTemplate? I was expecting it will throw an error saying two Hikari datasource found and advise to use @Primary annotation.

Any clarification would be appreciated!

Thanks

0 Answers
Related