How to resolve 'org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ...' - using stereotype Annotations and using @Configuration, @Bean Annotation
"At the end of the day, it doesn't really matter whether you use XML, annotation or Java configuration. It's important that beans are known to application context." - Tomasz Nurkiewicz
Hello everyone, in this article, we will learn how to resolve
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.knf.dev.demo.account.HelloManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
Using:
1. Stereotype Annotations.
2. @Configuration, @Bean Annotation.
Before going to the example just a quick overview of NoSuchBeanDefinitionException, @Configuration annotation, @Bean annotation, and @Component annotation(Stereotype annotation).
NoSuchBeanDefinitionException:
The 'org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.knf.dev.demo.account.HelloManager' available: expected at least 1 bean which qualifies as autowire candidate....' will be thrown when the bean is not available or defined while auto-wired in another class. If the bean is not available when the spring boot bean is annotated by @Autowired from the spring boot ApplicationContext, this exception will be thrown from the application.
@Configuration:
The @Configuration annotation is a part of the spring core framework. The @Configuration is a marker annotation which denotes that a class declares one or more @Bean methods and may be processed by the Spring container to engender bean definitions and service requests for those beans at runtime.
@Bean:
The @Bean annotation is a part of the spring core framework. The @Bean annotation tells that a method produces a bean to be managed by the Spring container.@Component:
The @Component annotation is utilized to denote a class as a Component. It signifies that Spring will autodetect these classes for dependency injection when annotation-predicated configuration and classpath scanning is utilized.
@ComponentScan:
The @ComponentScan annotation provides a mechanism to identify Spring bean candidates explicitly. If the application is a Spring Boot application, then all the packages under the package containing the Spring Boot application class will be covered by an implicit component scan.
**Important Notes**
- The @ComponentScan annotation provides a mechanism to identify Spring bean candidates explicitly. If the application is a Spring Boot application, then all the packages under the package containing the Spring Boot application class will be covered by an implicit component scan.
- Spring Boot’s @SpringBootApplication annotation implies the @Configuration, @ComponentScan, and @EnableAutoConfiguration annotations.
- The process of searching the classpath for classes that should contribute to the application context is called component scanning.
- The @SpringBootApplication annotation implies the @Configuration, @ComponentScan, and @EnableAutoConfiguration annotations.
- By default, the @ComponentScan annotation will scan for components in the current package and all its sub-packages. So if your application doesn’t have a varying package structure then there is no need for explicit component scanning.
Spring Boot Example 1: Reproduce the issue,
Hello.java:
public class Hello {
private String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public Hello(String message) { super(); this.message = message; }
public Hello() { super(); }}
HelloManager.java:
public interface HelloManager {
public Hello hello();}
HelloManagerImpl.java:
public class HelloManagerImpl implements HelloManager {
@Override public Hello hello() { Hello hello = new Hello("Hello Spring!"); return hello; }}
HelloConfig.java:
public class HelloConfig {
public HelloManager helloWorld() { return new HelloManagerImpl(); }}
Spring Boot Main Driver:
@SpringBootApplicationpublic class DemoApplication implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(DemoApplication.class);
@Autowired private HelloManager HelloManager;
public static void main(String[] args) throws Exception { SpringApplication.run(DemoApplication.class, args); }
@Override public void run(String... args) throws Exception { String hello = HelloManager.hello().getMessage(); LOG.info(hello);
}}
Spring Boot’s @SpringBootApplication annotation implies the @Configuration, @ComponentScan, and @EnableAutoConfiguration annotations.
Exception:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'HelloManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.knf.dev.demo.account.HelloManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2022-05-01 01:11:38.364 INFO 23309 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-05-01 01:11:39.078 ERROR 23309 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field HelloManager in com.knf.dev.demo.account.DemoApplication required a bean of type 'com.knf.dev.demo.account.HelloManager' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.knf.dev.demo.account.HelloManager' in your configuration.
Solution: Using @Configuration and @Bean
@Configurationpublic class HelloConfig {
@Bean public HelloManager helloWorld() { return new HelloManagerImpl(); }}
Here we have a @Configuration class that we can use to create and use beans within the application context. @Bean is used to mark a method as one that creates a bean and Spring will then add it to the context for us.
Console Output:
Hello Spring!
Spring Boot Example 2: Reproduce the issue,
Hello.java:
public class Hello {
private String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public Hello(String message) { super(); this.message = message; }
public Hello() { super(); }}
HelloManager.java:
public interface HelloManager {
public Hello hello();}
HelloManagerImpl.java:
public class HelloManagerImpl implements HelloManager {
@Override public Hello hello() { Hello hello = new Hello("Hello Spring!"); return hello; }}
Spring Boot Main Driver:
@SpringBootApplicationpublic class DemoApplication implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(DemoApplication.class);
@Autowired private HelloManager HelloManager;
public static void main(String[] args) throws Exception { SpringApplication.run(DemoApplication.class, args); }
@Override public void run(String... args) throws Exception { String hello = HelloManager.hello().getMessage(); LOG.info(hello);
}}
Exception:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'HelloManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.knf.dev.demo.account.HelloManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2022-05-01 01:32:57.447 INFO 6535 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-05-01 01:32:57.571 ERROR 6535 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field HelloManager in com.knf.dev.demo.account.DemoApplication required a bean of type 'com.knf.dev.demo.account.HelloManager' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.knf.dev.demo.account.HelloManager' in your configuration.
Solution: Using stereotype annotation
@Component //or other stereotype annotationspublic class HelloManagerImpl implements HelloManager {
@Override public Hello hello() {
Hello hello = new Hello("Hello Spring!"); return hello; }}
Mark HelloManagerImpl with @Component annotation.
Console Output:
Hello Spring!
When to use What?
@Component Preferable for component scanning and automatic wiring.
Sometimes @Component is not an option.
For example, You want to wire components from 3rd-party libraries but you don't have the source code so you can't annotate its classes with @Component, so automatic configuration is not possible.
The @Bean annotation returns an object that spring should register as a bean in the application context. The body of the method bears the logic responsible for engendering the instance.