The Question
Given that the archive we deploy is an "implicit bean archive" (see below), using @javax.inject.Inject
to inject a @javax.annotation.ManagedBean
into another managed bean work in WildFly 8.1.0, but it won't work in GlassFish 4.0.1-b08 nor GlassFish 4.1-b13. GlassFish crash with this message:
WELD-001408: Unsatisfied dependencies for type...
Do I misunderstand the following outlined specifications or do GlassFish have a bug?
CDI 1.1 Part 1
CDI 1.1 (JSR-346) section 12.1 "Bean Archives" says:
An explicit bean archive is an archive which contains a beans.xml file [..]. An implicit bean archive is any other archive which contains one or more bean classes with a bean defining annotation [..].
If then, my archive has no beans.xml
descriptor file, I will still be able to use beans that have a "bean defining annotation". Question is, what is a bean defining annotation?
The CDI specification section 2.5 "Bean defining annotations" says:
Any scope type is a bean defining annotation.
So that's pritty clear and that's all there is to it according to this section of the CDI specification. If I deploy an archive with no beans.xml
descriptor file in it, then I can @Inject beans as long as they have an explicitly declared scope, @javax.enterprise.context.RequestScoped
for example. It works in both WildFly and GlassFish. However..
Managed Beans
The subset specification that all specifications within the Java EE technology stack must adhere to, Managed Beans (JSR-316), has a "base model" in which @javax.annotation.ManagedBean
do define a managed bean. The managed beans specification doesn't say that @ManagedBean
makes the bean a plausible injection target for an injection point (i.e., field or parameter). The specification do say that the beans "can be used anywhere in a Java EE application" (section MB.1.2 "Why Managed Beans?") which in my ears sound like they should be injectable too.
Java EE 7 Umbrella specification
The Java EE 7 specification (JSR-342) has this to say in section EE.5.24 "Support for Dependency Injection":
Containers must support injection points annotated with the javax.inject.Inject annotation only to the extent dictated by CDI. Per the CDI specification, dependency injection is supported on managed beans.
There are currently three ways for a class to become a managed bean:
- Being an EJB session bean component.
- Being annotated with the ManagedBean annotation.
- Satisfying the conditions described in the CDI specification.
Classes that satisfy at least one of these conditions will be eligible for full dependency injection support as described in the CDI specification.
There you go: @ManagedBean has "full dependency injection support". Not half or just a little bit of support. Yet, I'm not that sure exactly what "dependency injection support" is. But I think that the paragraph that follows describe it well enough:
Component classes listed in Table EE.5-1 that satisfy the third condition above, but neither the first nor the second condition, can also be used as CDI managed beans if they are annotated with a CDI bean-defining annotation or contained in a bean archive for which CDI is enabled. However, if they are used as CDI managed beans (e.g., injected into other managed classes), the instances that are managed by CDI may not be the instances that are managed by the Java EE container.
Basically, what this paragraph says is that the second condition is CDI managed beans that may be injected into other managed classes (because the exception beans "can also").
The umbrella specification and the managed beans specification has both made it somewhat clear that the CDI specification has the last word.
CDI 1.1 Part 2
The @ManagedBean
annotation is only found mentioned in the CDI specification two times, both of which occur in chapter 11 which speaks of life cycle CDI events that a CDI extension can observe. Section 11.5.7 is one of the hits and define a ProcessInjectionPoint
event. A managed bean may use dependency injection - no surprise there. However, section 11.5.8 define a ProcessInjectionTarget
event. Here's what the specification has to say about the ProcessInjectionTarget event:
The container must fire an event for every Java EE component class supporting injection that may be instantiated by the container at runtime, including every managed bean declared using @ManagedBean, EJB session or message-driven bean, bean, interceptor or decorator.
This phrase says undoubtedly that a @ManagedBean
may be used as target for an injection point without adding the notion of scope types (@Dependent is always default).
As stated earlier, injecting a @ManagedBean from an implicit bean archive work in WildFly and as far as I can understand, this is required by all Java EE specifications just quoted. So I think it is GlassFish that has a bug. But the CDI spec never said a word about @ManagedBean in section 2.5 "Bean defining annotations", and as always, I'm a nervewreck when reading through overlapping Java EE specifications, so I thought I should ask before I go and file a "critical" bug to the GlassFish team.
EDIT 2014-08-22
Filed a GlassFish bug: https://java.net/jira/browse/GLASSFISH-21169.