0

I am trying to configure the spring data source programmatically. The idea is to override the default data source if tenant information is specified or else use the default data source for backward compatibility. I tried coming up with something like :

@Component
@AllArgsConstructor
public class TenancyDataSource {

  private TenantConfigs tenantConfigs;
  private DataSource dataSource;

  @Bean
  public DataSource dataSource() {
    
    String tenant = System.getenv(AppConstants.TENANT);

    if (!ObjectUtils.isEmpty(tenant)) {
      TenantConfigs config =
          tenantConfigs
              .getDataSources()
              .stream()
              .filter(TenantConfig -> tenantConfig.getTenantName().equals(tenant))
              .findFirst()
              .orElse(null);

      if (!ObjectUtils.isEmpty(config)) {
        return DataSourceBuilder.create()
            .url(config.getUrl())
            .password(config.getPassword())
            .username(config.getUsername())
            .build();
      }
    }

    return dataSource;
  }
}

But this does not work due to circular dependency. What would be the best way to implement it ?

Suraj Menon
  • 1,486
  • 3
  • 28
  • 50
  • Why would you need to wire the datasource in the class that constructs said datasource? So why is `DataSource` even a field? If this method does anything the default won't be available in the first place. – M. Deinum Apr 13 '21 at 12:22
  • Yes @M.Deinum, that's the problem. I followed this question - https://stackoverflow.com/questions/43142703/get-a-reference-to-currently-active-datasource-in-spring-boot & tried this out because `spring.datasource` are not read directly. Also not sure if it will impact the default data source in any way – Suraj Menon Apr 13 '21 at 12:29
  • 1
    If you have a configuration class that produces a `DataSource` Spring Boot will **not** automatically configure the datasource. So yes it has an impact. What you should do is write an `@Confguration` class that will only be available when the environment property is present. Work **with** the framework not against it. You can simply use an `@ConditionalOnProperty` on the `@Configuration` class and it will simply backoff when not set. – M. Deinum Apr 13 '21 at 12:32
  • Thanks using @ConditionalOnProperty with the tenant propert helped – Suraj Menon Apr 13 '21 at 12:58

1 Answers1

0

SpringBoot treats environment variables as properties by default. So using @ConditionalOnProperty with the "tenant" property worked

  @Bean
  @ConditionalOnProperty(name = AppConstants.TENANT)
  public DataSource dataSource() {
   
    return DataSourceBuilder.create()
        .url(config.getUrl())
        .password(config.getPassword())
        .username(config.getUsername())
        .build();
  }
Suraj Menon
  • 1,486
  • 3
  • 28
  • 50