CDI supports circular dependency injection when at least one of the beans has a normal scope*, this may be useful when sharing contextual information between beans of same or different scope (e.g. MVC pattern).

The CDI BeanManager is responsible for the creation of all CDI beans and managing contextual access to all normal scoped beans.

@RequestScoped public class Foo { @Inject private Bar bar; ... } @RequestScoped public class Bar { @Inject private Foo foo; ... }

This works because the BeanManager injects a client proxy for any normal scoped bean. When a method is invoked on the client proxy, the call results in a contextual lookup via the BeanManager.

@Dependent* beans in CDI are treated as pseudo scoped, unlike normal scoped beans the bean-manager does not inject a client proxy. Instead it instantiates the @Dependent bean immediately, injecting a direct reference to the newly created bean. This direct relationship ensures that the @Dependent bean inherits the scope of enclosing bean.

Circular injects which only involve dependent beans are essentially the same as:

public class Foo { private Bar bar = new Bar(); ... } public class Bar { private Foo foo = new Foo(); ... }

Which would lead to a StackOverflowError at runtime since Foo tries to instantiate a new Bar object, which in turn instanties a new Foo, and so on.

Weld discovers this issue during deployment, throwing a DeploymentException, preempting a StackOverflowError at runtime.

org.jboss.weld.exceptions.DeploymentException: WELD-001443: Pseudo scoped bean has circular dependencies. Dependency path: - Managed Bean [class com.knitelius.circle.Foo] with qualifiers [@Any @Default], - [BackedAnnotatedField] @Inject private com.knitelius.jaxwsconversation.Foo.bar, - Managed Bean [class com.knitelius.circle.Bar] with qualifiers [@Any @Default], - [BackedAnnotatedField] @Inject private com.knitelius.jaxwsconversation.Bar.foo, - Managed Bean [class com.knitelius.circle.Foo] with qualifiers [@Any @Default]

It is suggested frequently that this can be resolved by lazy instantiation using CDI Instance or Provider.

@Dependent public class Foo { @Inject private Instance<Bar> barInstance; ... public void doStuff() { Bar bar = barInstance.get(); ... } } @Dependent public class Bar { @Inject private Instance<Foo> fooInstance; ... }

It will run, but it’s bad design and will most likely produce unexpected results.

Foo 1 holds a reference to Bar 1. Bar 1 on the other hand does not hold a circular reference back to Foo 1 but obtains its own dependent instance of Foo 2. Therefore no state can be shared between Foo or Bar.

Conclusion

The only logical use of circular injections is when state is to be shared between contextual beans, in all other scenarios you should definitely consider restructuring your code.