Friday, November 9, 2012

Breaking a circular dependency in Spring

Have you ever seen a stack trace like this and wondered what to do:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanA' defined in file [\BeanA.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [BeanB]: : Error creating bean with name 'beanB' defined in file [\BeanB.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [BeanA]: : Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanB' defined in file [\BeanB.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [BeanA]: : Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
 at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730)
...
 at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
 at (Main.java:12)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanB' defined in file [\BeanB.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [BeanA]: : Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
 at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730)
...
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723)
 ... 15 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:297)
...
Then you probably have code like this:
@Component
public class BeanA {

 private final BeanB beanB;

 @Autowired
 public BeanA(BeanB beanB) {
  this.beanB = beanB;
 }

 @Override
 public String toString() {
  return beanB.getClass().getSimpleName() + " from " + this.getClass().getSimpleName();
 }

}

@Component
public class BeanB {

 private final BeanA beanA;

 @Autowired
 public BeanB(BeanA beanA) {
  this.beanA = beanA;
 }

 @Override
 public String toString() {
  return beanA.getClass().getSimpleName() + " from " + this.getClass().getSimpleName();

 }

}
How do you break such a circular reference in Spring? You could and should consider whether your code could be structured better. However, if you have considered this, then read on to find a way to break the circular reference. Take look at the Provider interface. Then take a look at this code:
@Component
public class BeanA {

 private final Provider<BeanB> beanB;

 @Autowired
 public BeanA(Provider<BeanB> beanB) {
  this.beanB = beanB;
 }

 @Override
 public String toString() {
  return beanB.get().getClass().getSimpleName() + " from " + this.getClass().getSimpleName();
 }

}

@Component
public class BeanB {

 private final Provider<BeanA> beanA;

 @Autowired
 public BeanB(Provider<BeanA> beanA) {
  this.beanA = beanA;
 }

 @Override
 public String toString() {
  return beanA.get().getClass().getSimpleName() + " from " + this.getClass().getSimpleName();

 }

}
If you run this code:
public class Main {

 public static void main(String... args) throws InterruptedException, ExecutionException {

  ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] { "META-INF/spring/app-context.xml" });
  BeanA beanA = applicationContext.getBean(BeanA.class);
  BeanB beanB = applicationContext.getBean(BeanB.class);
  System.err.println(beanA);
  System.err.println(beanB);

 }

}
You will see this instead of the above stack trace:
BeanB from BeanA
BeanA from BeanB
Note: the above is just a toy example to illustrate the point. In the code without use of the Provider interface you could actually just delete the constructors and put @Autowired on the Bean* fields (removing the final modifier) and it would work.

4 comments:

  1. Replies
    1. The effectiveness of IEEE Project Domains depends very much on the situation in which they are applied. In order to further improve IEEE Final Year Project Domains practices we need to explicitly describe and utilise our knowledge about software domains of software engineering Final Year Project Domains for CSE technologies. This paper suggests a modelling formalism for supporting systematic reuse of software engineering technologies during planning of software projects and improvement programmes in Final Year Project Centers in Chennai.

      Spring Framework has already made serious inroads as an integrated technology stack for building user-facing applications. Spring Framework Corporate TRaining the authors explore the idea of using Java in Big Data platforms.
      Specifically, Spring Framework provides various tasks are geared around preparing data for further analysis and visualization. Spring Training in Chennai

      Delete
  2. awesome blog it's very nice and useful i got many more information it's really nice i like your blog styleweb design company in velachery

    ReplyDelete