Are @ManagedBeans obsolete in JavaEE6 because of @Named in CDI/Weld?
Because of CDI (开发者_开发技巧and its implementation Weld), every POJO in JEE6 can be annotated with @Named
, which makes the POJO accessible to the view.
Does that mean that ManagedBeans are completely obsolete now?
Or did I miss something where @ManagedBean
still makes sense?
In short, @ManagedBean
makes sense for applications that use JSF but do not use JSR 299 (whatever the reason is). Below a longer explanation from Gavin King:
Re: Comparisons to @ManagedBean annotations in JSF2?:
While looking through the Weld examples, and the older WebBeans documentation, it looks like a competitor to the new @ManagedBean JSF 2.0 annotations. Is there any information on when we'd want to use one over the other?
It's a good question, and I'm not really in full agreement with the answers that have been posted so far.
The new EE Managed Beans specification defines a base component model for Java EE, together with a very basic set of container services (
@Resource
,@PostConstruct
,@PreDestroy
).The idea is that other specifications (beginning with EJB, CDI, JSF and the new Java Interceptors spec) build upon this base component model and layer additional services, for example transaction management, typesafe dependency injection, interceptors. So at this level, the managed beans, CDI, interceptors and EJB specifications all work hand-in-hand and are highly complementary.
Now, the Managed Beans specification is quite open-ended with respect to identifying exactly which classes are managed beans. It does provide the
@ManagedBean
annotation as one mechanism, but it also allows other specifications to define different mechanisms. So, for example:
The EJB specification says that a class obeying certain programming restrictions with a
@Stateless
or@Stateful
annotation deployed in an EJB jar is a managed bean.The CDI specification says that any class with an appropriate constructor deployed in a "bean deployment archive" is a managed bean.
Given that EJB and CDI provide arguably more convenient ways to identify a managed bean, you might wonder precisely what
@ManagedBean
is needed for. The answer, as alluded to by Dan, is that if you have CDI available in your environment (for example, if you are using EE6), then@ManagedBean
is just not really needed.@ManagedBean
is really there for use by people who are using JSF2 without CDI.OTOH, if you do annotate a bean
@ManagedBean
, and you do have CDI in your environment, you can still use CDI to inject stuff into your bean. It's just that the@ManagedBean
annotation is not required in this case.To summarize, if you do have CDI available to you, it provides a far superior programming model to the
@ManagedBean
/@ManagedProperty
model that JSF2 inherits from JSF1. So superior, in fact, that the EE 6 web profile does not require support for@ManagedProperty
etc. The idea being that you should just use CDI instead.
You have a choice. Either use the @ManagedBean from JSF2 to bind beans into your forms, or use the @Named annotation from CDI. If you plan on only doing JSF, you can stick to @ManagedBean, but if you want to integrate with EJB's, or make use of CDI's @ConversationScoped, then go the CDI route.
Personally I feel the next version of JSF should deprecate the @ManagedBean, and standardize on CDI. The duality is confusing to newcomers.
CDI has no view scope, because it doesn't have the notion of a view, so if you need that scope, CDI in its pure form can't do it. View scope basically means request scope + being AJAX-ready. It's not a JSF view, like a page named xyz.xhtml
, even though you see JSF <f:viewParam>
and the likes. A frequent use case with view-scoped beans is how to get GET parameters into a such a bean. Also read this.
Note that CDI rather lives at the EJB/service layer than the JSF/presentation layer. This blog has a nice overview.
As such @ManagedBean
cannot be fully replaced by CDI, again if you're using @ViewScoped
beans - at least not without extending CDI or using the Seam 3 Faces module. Using view-scoped beans is almost always going to happen when using AJAXed JSF 2-based GUI toolkits like RichFaces, PrimeFaces, IceFaces etc.
Mixing annotations from the wrong Java EE 6 packages can get you in trouble unexpectedly, again when using RichFaces or a similar API:
@javax.faces.bean.ManagedBean
@javax.faces.bean.[Jsf]Scoped
are for components used solely at the presentation layer, here by RichFaces, PrimeFaces, etc. Some rich components seem to have problems with CDI-annotated and JSF-annotated helper beans. If you get strange behavior from your beans (or beans that seem to do nothing) the wrong mix of annotations might be the cause.
Mixing JSF and CDI, like
@javax.inject.Named
@javax.faces.bean.[Jsf]Scoped
is possible and works in most cases when referenced from JSF pages, however there are some little-known issues/drawbacks, e.g. when using a JSF scope which CDI doesn't have:
Also the combination
@Named @ViewScoped
won't work as intended. The JSF-specific@ViewScoped
works in combination with JSF-specific@ManagedBean
only. Your CDI-specific@Named
will behave like@RequestScoped
this way. Either use@ManagedBean
instead of@Named
or use CDI-specific@ConversationScoped
instead of@ViewScoped
.
Then
@javax.inject.Named
@javax.faces.bean.[Cdi]Scoped
can be used for CDI beans directly referenced from your JSF pages AFAIK. I haven't had any problems with the above combinations so far, so you could consider @ManagedBean
obsolete here.
What's left is the service layer, here mostly transactional EJB service beans declared as
@javax.ejb.*
mostly @javax.ejb.Stateless. You can even annotate and use EJBs directly from JSF pages - though I'm not sure if this design is desirable. To reference (inject) any components annotated with @javax.ejb.*, e.g. @Stateless
, prefer @Inject
over @EJB
as described here. (Probably an ancestor of this answer...)
Finally, a very nice overview of Java EE 6 annotations can be found here: http://www.physics.usyd.edu.au/~rennie/javaEEReferenceSheet.html
Note: the above info is not from an expert, but simply my own take/sight from a newcomers perspective on this ridiculously confusing Java EE 6 annotations spaghetti. More insight has yet to be developed. I hope this answer can endure to be a general, practical answer to this confusion - even though it has gone a little overboard in the context of the original question.
As i Just read in the Weld Reference (p. 12), @ManagedBean is now superflous:
You can explicitly declare a managed bean by annotating the bean class @ManagedBean, but in CDI you don't need to. According to the specification, the CDI container treats any class that satisfies the following conditions as a managed bean:
- It is not a non-static inner class. It is a concrete class, or is annotated @Decorator.
- It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml.
- It does not implement javax.enterprise.inject.spi.Extension.
- It has an appropriate constructor—either:
- the class has a constructor with no parameters, or
- the class declares a constructor annotated @Inject.
精彩评论