Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is @javax.annotation.ManagedBean a CDI bean defining annotation?

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:

  1. Being an EJB session bean component.
  2. Being annotated with the ManagedBean annotation.
  3. 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.

like image 484
Martin Andersson Avatar asked Aug 15 '14 13:08

Martin Andersson


People also ask

What are CDI beans?

A CDI bean is a POJO, plain old java object, that has been automatically instantiated by the CDI container, and is injected into all, and any qualifying injection points in the application. The CDI container initiates the bean discovery process during deployment.

Which annotation is used to instantiate CDI beans?

As you may have noticed, the bean is nothing more than a plain old Java object, annotated with the @Dependent annotation. This annotation, called the dependent scope, declares that POJO is a CDI component. The dependent scope tells the CDI context to create a new instance whenever you request an injection to this bean.

What is CDI in JSF?

Contexts and Dependency Injection (CDI), specified by JSR-299, is an integral part of Java EE 6 and provides an architecture that allows Java EE components such as servlets, enterprise beans, and JavaBeans to exist within the lifecycle of an application with well-defined scopes.

What is EJB and CDI?

The "C" in CDI is the main difference between EJB beans and managed CDI beans. CDI-managed beans are contextual and EJB beans are not. Managed beans in CDI live in well-defined scope. They are created and destroyed on demand by the container.


1 Answers

This is not a complete answer as confusion will inevitably arise when we try to put together and make sense out of all specifications. I just wanted to say that CDI 1.2 has made a clarification about what exactly a bean defining annotation is (see section "2.5.1. Bean defining annotations"). CDI 1.2 give a list:

The set of bean defining annotations contains:

  • @ApplicationScoped, @SessionScoped, @ConversationScoped and @RequestScoped annotations,
  • all other normal scope types,
  • @Interceptor and @Decorator annotations,
  • all stereotype annotations (i.e. annotations annotated with @Stereotype),
  • and the @Dependent scope annotation.

It should be added that what defines a "normal scope type" (second bullet point) is a custom scope annotated @NormalScope.

like image 185
Martin Andersson Avatar answered Nov 12 '22 16:11

Martin Andersson