Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the spring annotation @ConditionalOnMissingBean do?

I am trying to start a springboot application where this annotation has been used. When I try to start the application it gives me the following error:

org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException Failed to deduce bean type for com.shutterfly.sbs.platform.SbsPlatformConfigurationClientConfig.getRestTemplate

Code:

@ConditionalOnMissingBean
@Bean
public RestTemplate getRestTemplate() {
    return new RestTemplate();
}
like image 353
Ravi Wadje Avatar asked Jun 11 '18 11:06

Ravi Wadje


People also ask

What is @ConditionalOnMissingBean in spring boot?

The @ConditionalOnMissingBean annotation is a spring conditional annotation for registering beans only when they are not already in the application context. See the documentation: https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.html.

What is the use of @ConditionalOnMissingBean?

Annotation Type ConditionalOnMissingBean. @Conditional that only matches when no beans meeting the specified requirements are already contained in the BeanFactory . None of the requirements must be met for the condition to match and the requirements do not have to be met by the same bean.

What does the @SpringBootApplication annotation do?

Spring Boot @SpringBootApplication annotation is used to mark a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning. It's same as declaring a class with @Configuration, @EnableAutoConfiguration and @ComponentScan annotations.

What can be used to load a bean on the absence of a specific bean?

36.3. The @ConditionalOnBean and @ConditionalOnMissingBean annotations allow configurations to be skipped based on the presence or absence of specific beans. You can use the value attribute to specify beans by type, or name to specify beans by name.


4 Answers

The @ConditionalOnMissingBean annotation is used to load a bean only if a given bean is missing:

@Bean
@ConditionalOnMissingBean(SomeBean.class)
public SomeBean otherBean(){
    return new SomeBean();
}

The above bean will get loaded by Spring only if there is no other bean of this type present in the context. On the other hand, if there is already a bean of the type SomeBean present in the application context, the above bean will not be created.

Some use cases where this annotation comes in handy are:

  • Specifying a fallback bean which gets only loaded as a backup if there is no bean of the same type present (for example: using an in-memory database if there is no real database configured)
  • Specifying a default bean which allows being overridden in the case that a more specific bean of the same type is present in the context (for example: using a default authentication mechanism unless someone decides to replace it with his own custom authentication)

Reference: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

like image 162
Marko Previsic Avatar answered Oct 26 '22 08:10

Marko Previsic


The @ConditionalOnMissingBean annotation is a spring conditional annotation for registering beans only when they are not already in the application context.

See the documentation: https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/api/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.html

like image 26
Mike Rylander Avatar answered Oct 26 '22 09:10

Mike Rylander


We use @ConditionalOnMissingBean if we want to include a bean only if a specified bean is not present. For ex.

Let's configure a transactionManager bean that will only be loaded if a bean of type JpaTransactionManager is not already defined:

@Bean
@ConditionalOnMissingBean(type = "JpaTransactionManager")
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

To understand more consider this scenario as well.

Let's say in my project I configured a bean videoDecoderService

@Bean
@ConditionalOnMissingBean(VideoDecoderService.class)
public videoDecoderService videoDecoderService(){
return new VideoDecoderService;
}

What it will do is whoever is using my project would be able to override the videoDecoderService with the videoDecoderService of their own. If they are not writing their own videoDecoderService then this default one will be provided.

like image 6
chirag soni Avatar answered Oct 26 '22 07:10

chirag soni


You should not skip the part of the documentation that clearly says:

The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only.

It goes on later to say:

If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after

In rather simple words it might mean that the @Bean brought in by the some other auto-configuration should take precedence over the one that you defined. For that to work, you need to properly set-up the order of those configurations via @AutoConfigureBefore.

like image 4
Eugene Avatar answered Oct 26 '22 07:10

Eugene