Resolving Spring Circular Reference Problem with proxied class

Have you ever run into a problem like this ?

"Error creating bean with name 'beanA': Bean with name 'beanA' has been injected into other beans (beanB) in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."

Let me first explain why this happens:

You have a circular dependency between your BeanA & BeanB. In such cases, if one of your bean does not have any AOP applied to it (transaction / audit-trail etc) , spring behaves fine. However, if both of your beans are proxied or in other word, has AOP advice attached to it (mostly transaction advice) , you have a problem. This is because spring initially injects the raw version of your bean beanA in the other bean beanB but later adds Aspect into it. So If your beanA has any aspect (transaction / audit-trail ) , they will not be in action when beanB uses beanA. Spring does not allow this by default and gives you the exception.

In a perfect world and in a perfect project, you wouldn’t want circular dependency in your beans. But as we know, the world is not perfect and sometimes you just have to do it (obviously within same module).

How do I do it you ask? Fortunately you have a few options :

1. Set “allowEagerInit” to false in your application context.
2. Break the circular dependency for spring by not injecting one of the bean with application context and get the bean @ runtime by calling “applicationContext.getBean”
3. Write your own BeanFactory to allow circular dependency ( If you are ok with the side effects )

I am going to describe the 3rd method in details. With spring, its always very simple to add hook in necessary points. First write a class like this:

public class AllowRawInjectionDespiteWrappingXMLWebApplicationContext extends
		XmlWebApplicationContext {

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
			throws IOException {
		beanFactory.setAllowRawInjectionDespiteWrapping(true);
		super.loadBeanDefinitions(beanFactory);
	}

	 
}

All I am doing here is changing the default value “allowRawInjectionDespiteWrapping” to true to let spring know I am OK with raw injection of my AOP beans.

Next, Change your default contextClass “XmlWebApplicationContext” class name which spring uses by adding the following in your web.xml file.

	<context-param>
	        <param-name>contextClass</param-name>
	        <param-value>com.myapp.AllowRawInjectionDespiteWrappingXMLWebApplicationContext</param-value>
	</context-param>

All that trouble to break a design rule (avoid circular dependency)..Fair enough !!

Advertisements

3 thoughts on “Resolving Spring Circular Reference Problem with proxied class

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s