6

I'm running into a issue with CDI Injection into a Weld container in JBoss 7.1.1

I've got the following object model :

@Stateless
class ServiceEjb {
@Inject
A a;
}

class A {
@Inject
B b;
}

class B {
@Inject
A a;
}

When trying to inject A or B in my stateless class, injection loop and crash with a javax.enterprise.inject.CreationException.

I try many thing (scoping, @Singleton on A or B but without success). I don't want to break the code, and those injections makes senses.

Any clues will be greatly appreciated.

Nick
  • 2,827
  • 4
  • 29
  • 39
jmcollin92
  • 2,896
  • 6
  • 27
  • 49

3 Answers3

12

Circular dependency injection is not required by the CDI standard, unless at least one bean in the cycle has a normal scope. The easiest solution to this is to give A or B a normal scope. If you can't give either a normal scope (from the code mock-up, it looks like they all have the default @Dependent pseudo-scope), you will have to look for other solutions. Posting a real code sample might let us help you with a particular solution, but here is a start:

  • Can A and B be combined into the same class?
  • Can a new class, C, be extracted from A and B, so that both A and B @Inject C instead of each other?

Here are some SO links with other solutions that you might find helpful:

MVP with CDI; avoiding circular dependency

https://stackoverflow.com/questions/14044538/how-to-avoid-cdi-circular-dependency

Community
  • 1
  • 1
Nick
  • 2,827
  • 4
  • 29
  • 39
  • Thank's for your quick reply. I have to admit that the concept of normal scope is not very clear for me. Links you provide speaks about @NormalScope but this does not exists. How to declare a normal scope ? – jmcollin92 Mar 08 '13 at 20:18
  • [Most scopes are normal scopes.](http://docs.jboss.org/cdi/spec/1.0/html/contexts.html#normalscope) Session, application, conversation, and request scopes are normal scopes. This is in contrast to the _pseudoscopes_: singleton and dependent (which is the default when you don't write in a scope annotation). – Nick Mar 08 '13 at 20:58
  • So, because I already try declaring scope, this should work, if I understand well. What kind of scope may I try to a DAO (accessed by a SessionBean) ? – jmcollin92 Mar 08 '13 at 22:00
  • Thank's for your help ! I've got it working with @ApplicationScoped ! Don't know if it a good idea to have a DAO ApplicationScoped. Is this equivalent to Singleton in case of an EJB jar. – jmcollin92 Mar 08 '13 at 22:18
5

I solved the problem by using javax.inject.Provider explicitly. Although I feel like this should be done under the hood by WELD automatically this was not the case for me too. This worked for me and solved my related problem.

class A {
    @Inject
    Provider<B> b; // access with b.get()
}

class B {
    @Inject
    Provider<A> a; // access with a.get()
}

I haven't tested it, but it could be enough to use one Provider to break the cycle, i.e. you don't need to use it in both classes.

jan
  • 2,741
  • 4
  • 35
  • 56
1

You should inject an Instance<B> instead of B (and/or Instance<A> instead of A)

Sheepy
  • 677
  • 9
  • 17