When a Spring Bean is named exactly like the spring boot application class a NoSuchBeanDefinitionException is thrown.
The error message is quite confusing because a bean of the specific type exists on source-code level. Just because the application class is equally named it cannot be found.
I think it should be possible to detect this and throw a more appropriate exception or a textual hint.
I also think that this issue is quite likely to appear in microservice-environments with a bounded context and is not just an edge-case.
Steps to reproduce: 1. Create a spring boot application
@SpringBootApplication
public class FooService {
public static void main(String[] args) {
SpringApplication.run(FooService.class, args);
}
}
- In another package create a bean with the same name as the application class
@Service
public class FooService {
}
- Create a service which injects the previously created bean
@Service
public class BarService {
private final FooService fooService;
public BarService(FooService fooService) {
this.fooService = fooService;
}
}
- Start the application
It will produce the following output:
2022-07-23 15:49:38.770 INFO 27400 --- [ main] com.example.demo.FooService : Starting FooService using Java 17.0.3 on DESKTOP-3FIUVON with PID 27400 (P:\tmp\spring-boot-naming-error\target\classes started by tobi in P:\tmp\spring-boot-naming-error)
2022-07-23 15:49:38.776 INFO 27400 --- [ main] com.example.demo.FooService : No active profile set, falling back to 1 default profile: "default"
2022-07-23 15:49:39.340 WARN 27400 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'barService' defined in file [P:\tmp\spring-boot-naming-error\target\classes\com\example\demo\deeper\BarService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.deeper.FooService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2022-07-23 15:49:39.354 INFO 27400 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-07-23 15:49:39.398 ERROR 27400 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demo.deeper.BarService required a bean of type 'com.example.demo.deeper.FooService' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.deeper.FooService' in your configuration.
Process finished with exit code 1
Comment From: snicoll
What version of Spring Boot is this? Spring Boot prevents bean overriding by default since 2.1 so I would expect a different error message.
Comment From: twobiers
I have created an example repo for this issue with Spring Boot 2.7.2: https://github.com/twobiers/spring-boot-naming-error
Personally, I had this issue with 2.6.9
Comment From: pruidong
I also reproduced this problem in Spring Boot 3.0.0-M2.
I found that the following class is not registered as a Spring Bean, so an exception is thrown when BarService is injected.
@Service
public class FooService {
}
The condition to trigger the BeanDefinitionOverrideException is that the bean is defined in two different classes:
The first class defines:
@Bean
public BarService barService(){
return new BarService();
}
The second class defines:
@Bean
public BarService barService(){
return new BarService();
}
Comment From: wilkinsona
This looks like a Framework bug to me. The same underlying failure occurs with the following main class:
package com.example.demo;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class FooService {
public static void main(String[] args) {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
((DefaultListableBeanFactory)context.getBeanFactory()).setAllowBeanDefinitionOverriding(false);
context.register(FooService.class);
context.refresh();
}
}
}
Using this main class removes Spring Boot from the application.
com.example.demo.deeper.FooService isn't registered as, during component scanning, ClassPathBeanDefinitionScanner.isCompatible(BeanDefinition, BeanDefinition) returns true when comparing its definition with the definition for com.example.demo.FooService. In this case I don't think they should be considered to be compatible and a ConflictingBeanDefinitionException should have been thrown.
We'll transfer this to the Framework team so that they can take a look.
Comment From: stoiandelev
I have this problem in this class: package com.example.favouritePlaceInTheWorld.config;
@Configuration public class WebConfigurationInterceptor implements WebMvcConfigurer {
private final StatsInterceptor statsInterceptor;
private final IpBlackListInterceptor ipBlackListInterceptor;
private final MaintenanceInterceptor maintenanceInterceptor;
public WebConfigurationInterceptor(StatsInterceptor statsInterceptor,
IpBlackListInterceptor ipBlackListInterceptor,
MaintenanceInterceptor maintenanceInterceptor) {
this.statsInterceptor = statsInterceptor;
this.ipBlackListInterceptor = ipBlackListInterceptor;
this.maintenanceInterceptor = maintenanceInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(statsInterceptor);
registry.addInterceptor(ipBlackListInterceptor);
registry.addInterceptor(maintenanceInterceptor);
}
}
When I run the app with docker I receive. NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.favouritePlaceInTheWorld.repository.IpBlockedAddressesRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} this: Any Idea?
Comment From: snicoll
@stoiandelev please ask questions on StackOverflow.
Comment From: jhoeller
Fixed as of 6.1 through #25952 already.