The Spring Boot exception “org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type available” occurs when attempting to auto-wire a bean in another class, but the bean is either not available or not defined in the Spring application context. This exception is thrown when the @Autowired
annotation is used, and Spring Boot fails to find a qualifying bean of the specified type within the ApplicationContext. The NoSuchBeanDefinitionException is raised if the required bean is not present or not correctly defined when attempting to use @Autowired
to inject the bean into another component in a Spring Boot application. It is crucial to ensure that the bean is properly declared and available in the application context to prevent this exception.
In a Spring Boot application, beans can be injected using either the class type or Java naming conventions. If neither of these methods matches a qualifying bean within the application context, the exception “org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type” will be thrown. This exception indicates that Spring Boot could not find a bean that matches the specified criteria during the auto-wiring process.
If a Java class is not loaded into the context of the Spring Boot application, an exception will be thrown. To ensure that a Java class is recognized as a bean and available for injection, it should be appropriately configured with annotations such as @Component
, @Service
, @Repository
, or @Controller
. Alternatively, the bean class can be annotated with @Bean
within a @Configuration
class. These annotations inform Spring Boot about the intended use of the class as a bean and its specific role within the application context, allowing for proper bean initialization and injection. Failure to apply these annotations may result in the mentioned exception when attempting to use the class as a bean.
In Spring Boot, the BeanFactory is responsible for loading all the Java beans into the application context. If the BeanFactory encounters a situation where it cannot find or load a particular Java bean, it throws the exception “org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type available.” This exception is typically logged in the console output at the startup of the Spring Boot application.
Exception
s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'zoo': Unsatisfied dependency expressed through field 'lion'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.yawintutor.Lion' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Root Cause
Dependency injection is a key feature of Spring Boot, where all beans are loaded into the ApplicationContext, and dependent beans are injected automatically. If Spring Boot encounters a situation where it cannot find or inject a particular bean, it throws the exception NoSuchBeanDefinitionException
. The reasons behind this exception could be that the bean is not available in the ApplicationContext, it cannot be located, or an error occurred during the injection process. It is essential to ensure that the required beans are properly configured, annotated, and available in the application context to prevent such exceptions and ensure smooth dependency injection in Spring Boot applications.
Solution 1 – Bean Not Available in ApplicationContext
package com.yawintutor;
public class Lion {
// .....
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Zoo {
@Autowired
Lion lion;
}
Output
s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'zoo':
Unsatisfied dependency expressed through field 'lion'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.yawintutor.Lion' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Solution
The error encountered is “expected at least 1 bean which qualifies as autowire candidate.” To resolve this issue, it is necessary to include the injection class in the ApplicationContext by using the @Component
annotation. By adding the @Component
annotation to the Lion
class, the exception “NoSuchBeanDefinitionException: No qualifying bean of type” can be effectively addressed. The example below illustrates the solution by incorporating the @Component
annotation to resolve the mentioned exception.
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Lion {
// .....
}
Solution 2 – Bean Not Loaded in ApplicationContext
Even with the injected bean annotated with @Component
, the Spring Boot application continues to throw the NoSuchBeanDefinitionException
exception. This issue persists because the Java bean is not loaded into the ApplicationContext. In the provided example, the Zoo
class attempts to inject the Lion
class bean, which is annotated with @Component
. Despite this annotation, the NoSuchBeanDefinitionException
still arises, indicating that the Lion
class bean is not successfully loaded into the ApplicationContext.
package com.yawin;
import org.springframework.stereotype.Component;
@Component
public class Lion {
// .....
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Zoo {
@Autowired
Lion lion;
}
Output
s.c.a.AnnotationConfigApplicationContext :
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'zoo':
Unsatisfied dependency expressed through field 'lion';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.yawin.Lion' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
Solution
The encountered error is “expected at least 1 bean which qualifies as autowire candidate.” To address this issue, the solution involves adding the injection class to the ApplicationContext using the @ComponentScan
annotation. It is crucial to ensure that the Spring Boot main class serves as the root package.
In the provided example, there exist two packages, namely “com.yawintutor” and “com.yawin.” Notably, the Lion
class is not situated under the “com.yawintutor” root package. When a class is not created under the root package, it may not be loaded by Spring Boot. The @ComponentScan
annotation becomes instrumental in explicitly specifying the packages required to load the bean into the Spring Boot context.
To resolve the NoSuchBeanDefinitionException: No qualifying bean of type
exception, the @ComponentScan
annotation should be applied to the Zoo
class. The subsequent example demonstrates the resolution of the exception by incorporating the @ComponentScan
annotation
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
@Component
@ComponentScan("com.yawin")
public class Zoo {
@Autowired
Lion lion;
}
Solution 3 – Implementation class not available for Interface
When an interface is created without an implementation class, and Spring Boot attempts to inject the interface, it fails to auto-wire the interface, resulting in a NoSuchBeanDefinitionException
exception. The absence of an implemented class for the interface makes it impossible for Spring Boot to fulfill the auto-wiring request. The following example illustrates the scenario where an interface triggers the NoSuchBeanDefinitionException
exception:
package com.yawintutor;
public interface Animal {
public String getName();
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Zoo {
@Autowired
public Animal animal;
}
Output
s.c.a.AnnotationConfigApplicationContext :
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'zoo':
Unsatisfied dependency expressed through field 'animal';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.yawintutor.Animal' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
Solution
To resolve the issue where the implementation class for the interface is not available in the Spring Boot context, it is necessary to create an implementation class for the interface and ensure that it is registered as a Spring Boot bean in the ApplicationContext. The following example demonstrates the creation of an implementation class Lion
for the Animal
interface:
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
@Override
public String getName() {
return "Lion";
}
}
Solution 4 – Found Multiple Implemented Class for Interface
When an interface is associated with multiple implementation classes, Spring Boot encounters challenges in auto-wiring the interface when attempting to inject one of the implemented classes. In such instances, the absence of clear resolution criteria may result in Spring Boot’s failure to perform the auto-wiring process. The example provided below exemplifies this scenario, where the interface triggers a NoSuchBeanDefinitionException
exception:
package com.yawintutor;
public interface Animal {
public String getName();
}
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
@Override
public String getName() {
return "Lion";
}
}
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
@Override
public String getName() {
return "Tiger";
}
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Zoo {
@Autowired
public Animal animal;
}
Solution
When an interface has two or more implementation classes, Spring Boot may face challenges in injecting the interface. To resolve this ambiguity and specify which implementation class should be injected, the @Qualifier
annotation is employed. The @Qualifier
annotation provides explicit information to Spring Boot, guiding the injection process. The example below illustrates the usage of @Qualifier
to inject an implemented class into an interface:
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Zoo {
@Autowired
@Qualifier("lion")
public Animal animal;
}
Solution 5 – No bean named available
When manually loading a bean from the Spring Boot ApplicationContext, it is essential to configure the bean name following Java naming conventions. If the bean name deviates from the expected convention, it may result in a NoSuchBeanDefinitionException
exception.
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Lion {
// .....
}
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBootNoBeanApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBootNoBeanApplication.class, args);
ctx.getBean("lion1", Lion.class);
}
}
Output
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'lion1' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:808)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1279)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:297)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1114)
at com.yawintutor.SpringBootNoBeanApplication.main(SpringBootNoBeanApplication.java:12)
Solution
In the given example, the bean name “lion1” does not adhere to Java naming conventions, leading to a thrown exception: “NoSuchBeanDefinitionException: No bean named available.” To resolve this issue, changing the bean name to align with Java conventions will address the exception.
package com.yawintutor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBootNoBeanApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(SpringBootNoBeanApplication.class, args);
ctx.getBean("lion", Lion.class);
}
}