The UnsatisfiedDependencyException is a common exception that occurs when there is a problem creating a bean in the Spring framework. This exception typically occurs when there is a missing or conflicting dependency between beans in the application context. In this blog post, we will take a look at an example of this exception and show how to resolve it.
Example
Let’s say we have a class, MyService
, which depends on another class, MyDependency
. In order to use MyService
, we need to first create an instance of MyDependency
and set it as a property of MyService
. We can do this using the @Autowired
annotation, which tells Spring to automatically wire the dependency.
@Service
public class MyService {
@Autowired
private MyDependency myDependency;
// other methods and properties
}
@Service
public class MyDependency {
// other methods and properties
}
Exception
However, if we forget to create an instance of MyDependency
in the application context, we will get an UnsatisfiedDependencyException when trying to create an instance of MyService
.
Error creating bean with name 'myService': Unsatisfied dependency expressed through field 'myDependency'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.MyDependency' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
The exception message is telling us that there is no bean of type MyDependency
available in the application context, and that MyService
has a required dependency on it. To resolve this exception, we need to either create an instance of MyDependency
or remove the dependency from MyService
.
@Service
public class MyService {
@Autowired(required = false)
private MyDependency myDependency;
// other methods and properties
}
or
@Service
public class MyDependency {
// other methods and properties
}
@Service
public class MyService {
private MyDependency myDependency;
@Autowired
public MyService(MyDependency myDependency){
this.myDependency = myDependency;
}
// other methods and properties
}
Using @ComponentScan annotation
Additionally, to avoid this exception, we can also use the @ComponentScan
annotation in the configuration class to scan for the beans in the package where MyDependency
class is located.
@Configuration
@ComponentScan(basePackages = {"com.example"})
public class AppConfig {
// other configuration
}
In this way, Spring will automatically create an instance of MyDependency
and wire it to MyService
.
Using @Qualifier annotation
One way to resolve the exception is to use the @Qualifier
annotation to specify which bean should be used to satisfy the dependency. For example, if we have multiple beans of the same type, we can use the @Qualifier
annotation to specify which bean should be used for the dependency.
@Service
@Qualifier("myDependency1")
public class MyDependency1 {
// other methods and properties
}
@Service
@Qualifier("myDependency2")
public class MyDependency2 {
// other methods and properties
}
@Service
public class MyService {
@Autowired
@Qualifier("myDependency1")
private MyDependency myDependency;
// other methods and properties
}
Using @Primary annotation
Another way to resolve the exception is to use the @Primary
annotation to specify which bean should be used as the primary bean for a given type. For example, if we have multiple beans of the same type and want to use one of them as the primary bean, we can use the @Primary
annotation.
@Service
public class MyDependency1 {
// other methods and properties
}
@Service
@Primary
public class MyDependency2 {
// other methods and properties
}
@Service
public class MyService {
@Autowired
private MyDependency myDependency;
// other methods and properties
}
In this example, MyDependency2
will be used as the primary bean for the MyDependency
type, and will be autowired to MyService
.
Using @Bean annotation
It’s also possible to resolve the exception by creating the missing bean programmatically in the configuration class and register it to the application context using the @Bean
annotation
@Configuration
public class AppConfig {
@Bean
public MyDependency myDependency() {
return new MyDependency();
}
}
In this example, the myDependency
bean is created and registered to the application context, and will be available for autowiring to other beans.
Conclusion
In conclusion, UnsatisfiedDependencyException can be resolved in multiple ways, such as removing the dependency, creating the missing bean, using the @Qualifier
and @Primary
annotations, or programmatically creating and registering the bean in the configuration class. It’s important to understand the root cause of the exception and to choose the appropriate solution accordingly.