The spring boot exception BeanCurrentlyInCreationException: Error creating bean with name: Requested bean is currently in creation happens when two beans are in circular dependences with each other. If the bean A depends on another bean B and the bean B depends on the bean A, the BeanCurrentlyInCreationException will occur.
BEAN A -> BEAN B -> BEAN A (two beans in circular dependency)
BEAN A -> BEAN B -> BEAN C -> BEAN A (three beans in circular dependency)
When the spring boot application loads all the beans, it attempts to auto-wire the dependent beans. If two beans are in circular dependency, each bean will wait for another bean to be loaded. There’s going to be a deadlock loading the bean. The spring boot application will therefore throw the exception BeanCurrentlyInCreationException: Error creating bean with name: Requested bean is currently in creation.
Exception
The stack trace of Exception BeanCurrentlyInCreationException: Error creating bean with name: Requested bean is currently in creation will be seen as below.
2020-12-10 08:08:33.166 WARN 79750 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'department' defined in file [/SpringBootBean/target/classes/com/yawintutor/Department.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'lion' defined in file [/SpringBootBean/target/classes/com/yawintutor/Lion.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'tiger' defined in file [/SpringBootBean/target/classes/com/yawintutor/Tiger.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'lion': Requested bean is currently in creation: Is there an unresolvable circular reference?
2020-12-10 08:08:33.174 INFO 79750 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-12-10 08:08:33.196 ERROR 79750 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
department defined in file [/SpringBootBean/target/classes/com/yawintutor/Department.class]
┌─────┐
| lion defined in file [/SpringBootBean/target/classes/com/yawintutor/Lion.class]
↑ ↓
| tiger defined in file [/SpringBootBean/target/classes/com/yawintutor/Tiger.class]
└─────┘
Root Cause
If two or more beans in the spring boot application participate in the circular dependencies, spring boot application could not load any beans in the application context as each bean depends on another bean. Spring boot could not decide which bean should be loaded first in a circular dependency. As a result, the spring boot will throw the exception when loading the bean into the application context.
How to reproduce this exception
If two beans are created with circular dependencies in the spring boot, each bean will wait for another bean to be loaded first. This is going to be the deadlock scenario. The spring boot application detects the deadlock condition when loading bean in the application context and throws the exception.
package com.yawintutor;
public interface Animal {
public String getName();
}
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
public Lion(Animal tiger) {
}
@Override
public String getName() {
return "Lion";
}
}
package com.yawintutor;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
public Tiger(Animal lion) {
}
@Override
public String getName() {
return "Tiger";
}
}
Output
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
department defined in file [/SpringBootBean/target/classes/com/yawintutor/Department.class]
┌─────┐
| lion defined in file [/SpringBootBean/target/classes/com/yawintutor/Lion.class]
↑ ↓
| tiger defined in file [/SpringBootBean/target/classes/com/yawintutor/Tiger.class]
└─────┘
Solution 1
Circular dependency is due to the problem of programming or architecture. Walk around the beans that are part of a circular dependency, consider redesigning the beans. This is going to solve the exception. The component must be loaded into a hierarchical dependency model instead of a circular model.
The brainstorming activity or the peer review will help in understanding the circular dependency and avoid the circular dependency. To address this exception, the loading sequence of the beans should be redesigned.
Solution 2
The beans in the circular dependency could be loaded using the @Autowired annotation. The @Autowired annotation creates a bean and loads the dependence. This is going to solve the exception. However the exception would be caused if the methods in the beans rely on each other.
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
@Autowired
Animal tiger;
@Override
public String getName() {
return "Lion";
}
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
@Autowired
Animal lion;
@Override
public String getName() {
return "Tiger";
}
}
Solution 3
The spring boot application supports lazy loading of the beans. The @Lazy annotation uses loading the bean whenever it is needed instead of loading it at the start. The bean will be injected after the bean has been created and loaded into the context. First the beans in the circular dependency will be created and then the other beans will be injected into the bean.
package com.yawintutor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
public Lion(@Lazy Animal tiger) {
}
@Override
public String getName() {
return "Lion";
}
}
package com.yawintutor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
public Tiger(@Lazy Animal lion) {
}
@Override
public String getName() {
return "Tiger";
}
}
Solution 4
The spring boot annotation @PostConstruct will be used to execute a method after the constructor method is called. Circular dependency beans can be initiated using the post-construction method. Beans will first be created using the constructor, and then the annotated @PostConstruct method will be used to create the bean.
package com.yawintutor;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
@Autowired
Tiger tiger;
@PostConstruct
public void load() {
tiger.setLion(this);
}
@Override
public String getName() {
return "Lion";
}
public void setTiger(Tiger tiger) {
this.tiger =tiger;
}
}
package com.yawintutor;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
@Autowired
Lion lion;
@PostConstruct
public void load() {
lion.setTiger(this);
}
@Override
public String getName() {
return "Tiger";
}
public void setLion(Lion lion) {
this.lion =lion;
}
}
Solution 5
The @Autowired annotation can be used in the setter method. Beans may be assigned using the @Autowired setter method. First the beans are loaded and then the setter method is called to auto-wire the other beans.
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Lion implements Animal{
Tiger tiger;
@Override
public String getName() {
return "Lion";
}
@Autowired
public void setTiger(Tiger tiger) {
this.tiger =tiger;
}
}
package com.yawintutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal{
Lion lion;
@Override
public String getName() {
return "Tiger";
}
@Autowired
public void setLion(Lion lion) {
this.lion =lion;
}
}