Adam Żarniewicz
Adam Żarniewicz

Reputation: 66

Spring Boot @ConditionalOnProperty doesn't load bean

I'm trying to implement a service, which will use two different repositories based on env variable.

Based on this article: https://reflectoring.io/dont-use-spring-profile-annotation/

I want to use configuration with @ConditionalOnProperty annotation to load appropriate implementation on startup.

I did everything exactly like in the article, but spring throws an exception saying that the bean is not defined:

Description:

Parameter 0 of method myService in com.adam.MyServiceConfiguration required a bean of type 'com.adam.MyRepository' that could not be found.


Action:

Consider defining a bean of type 'com.adam.MyRepository' in your configuration.


Process finished with exit code 0

Here is the configuration of service:

@Configuration
class MyServiceConfiguration {
    @Bean
    fun mySerivce(myRepository: MyRepository) = MyService(myRepository)
}

And here is the configuration of repository beans:

@Configuration
class DataSourceConfiguration {

    @Bean
    @ConditionalOnProperty(
        prefix = "datasource",
        name = ["mock"],
        havingValue = "false",
        matchIfMissing = true
    )
    fun myRepository(httpClient: HttpClient): MyRepository =
        HttpRepository(httpClient)

    @Bean
    @ConditionalOnProperty(
        prefix = "datasource",
        name = ["mock"],
        havingValue = "true"
    )
    fun myRepository(): MyRepository = InMemoryRepository()
}

Can anybody see what am I doing wrong? I'm struggling with it for hours.

I tried using @DependsOn but then the error was that there is no bean defined of that name.

I also enabled logging and if I'm reading this right the bean should be resolved properly:

   My#repository:
      Did not match:
         - @ConditionalOnProperty (datasource.mock=false) found different value in property 'mock' (OnPropertyCondition)
      Matched:
         - @ConditionalOnProperty (datasource.mock=true) matched (OnPropertyCondition)

Upvotes: 2

Views: 6928

Answers (1)

Andy Wilkinson
Andy Wilkinson

Reputation: 116061

You have two @Bean methods named myRepository on one @Configuration class. This means that there are two different methods both defining a bean named myRepository. This confuses Spring Framework's condition evaluation as described in this issue. The confusion means that the conditions on both myRepository() methods are evaluated when defining a single myRepository bean. Your two conditions are mutually exclusive so no bean is defined.

You can fix the problem by ensuring that your two @Bean methods have distinct names. For example you could name them httpRepository and inMemoryRepository.

Upvotes: 2

Related Questions