Java EE 6 @javax.annotation.ManagedBean vs. @javax.inject.Named vs. @javax.faces.ManagedBean
Asked Answered
H

3

109

I feel there is a little mess in the Java EE 6 spec. There are several sets of annotations.

We have javax.ejb annotations like @Stateful and @Stateless for creating EJBs.

There is also a @javax.annotation.ManagedBean to create a managed bean.

There are annotations in javax.enterprise.context like @SessionScoped and @RequestScoped.

What is more there are also @ManagedBean and @SessionScoped/@RequestScoped annotations in javax.faces.bean package.

And to make things event more complicated there is a package javax.inject with @Named annotation.

Can someone please describe how they are related one to another?

Where can I use @EJB, @Inject or @ManagedPropery to inject other beans?

Hoot answered 16/8, 2012 at 12:11 Comment(1)
See also: stackoverflow.com/questions/4684112/…Rosanne
A
198

First of all let me do some clarifications:

Managed bean definition : generally a managed bean is an object that its life cycle (construction, destruction, etc) is managed by a container.

In Java ee we have many containers that manage life cycle of their objects, like JSF container, EJB container, CDI container, Servlet container, etc.

All of these containers work kind of independent, they boot in application server initialization and scan classes of all artifacts including jar, ejb-jar, war and ear files in deployment time and gather and store some metadata about them, then when you need an object of a class at runtime they will give you instances of those classes and after finishing the job, they will destroy them.

So we can say that we have:

  • JSF managed beans
  • CDI managed beans
  • EJB managed beans
  • And even Servlets are managed beans because they are instantiated and destroyed by a container, which is a servlet container.

So when you see the Managed Bean word, you should ask about the context or type of it.(JSF, CDI, EJB, etc.)

Then you might ask why we have many of these containers: AFAIK, Java EE guys wanted to have a dependency injection framework, but they could not gather all requirements in one specification because they could not predict the future requirements and they made EJB 1.0 and then 2.0 and then 3.0 and now 3.1 but EJB's target was for just some requirements (transaction, distributed component model, etc).

At the same time (in parallel) they realized that they need to support JSF too, then they made JSF managed beans and another container for JSF beans and they considered it a mature DI container, but still it was not complete and mature container.

After that Gavin King and some other nice guys ;) made CDI which is the most mature DI container I've seen. CDI (inspired by Seam2, Guice and Spring) was made to fill the gap between JSF and EJB and lots of other useful stuff like pojo injection, producer methods, interceptors, decorators, integration SPI, very flexible, etc. and it can even do what EJB and JSF managed beans are doing then we can have just one mature and powerful DI container. But for some backward compatibility and political reasons Java EE guys want to keep them!!!

Here you can find the difference and use cases for each of these types:

JSF Managed Beans, CDI Beans and EJBs

JSF was initially developed with its own managed bean and dependency injection mechanism which was enhanced for JSF 2.0 to include annotation based beans. When CDI was released with Java EE 6, it was regarded as the managed bean framework for that platform and of course, EJBs outdated them all having been around for well over a decade.

The problem of course is knowing which one to use and when use them.

Let’s start with the simplest, JSF Managed beans.

JSF Managed Beans

In short, don’t use them if you are developing for Java EE 6 and using CDI. They provide a simple mechanism for dependency injection and defining backing beans for web pages, but they are far less powerful than CDI beans.

They can be defined using the @javax.faces.bean.ManagedBean annotation which takes an optional name parameter. This name can be used to reference the bean from JSF pages.

Scope can be applied to the bean using one of the different scopes defined in the javax.faces.bean package which include the request, session, application, view and custom scopes.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

JSF beans cannot be mixed with other kinds of beans without some kind of manual coding.

CDI Beans

CDI is the bean management and dependency injection framework that was released as part of Java EE 6 and it includes a complete, comprehensive managed bean facility. CDI beans are far more advanced and flexible than simple JSF managed beans. They can make use of interceptors, conversation scope, Events, type safe injection, decorators, stereotypes and producer methods.

To deploy CDI beans, you must place a file called beans.xml in a META-INF folder on the classpath. Once you do this, then every bean in the package becomes a CDI bean. There are a lot of features in CDI, too many to cover here, but as a quick reference for JSF-like features, you can define the scope of the CDI bean using one of the scopes defined in the javax.enterprise.context package (namely, request, conversation, session and application scopes). If you want to use the CDI bean from a JSF page, you can give it a name using the javax.inject.Named annotation. To inject a bean into another bean, you annotate the field with javax.inject.Inject annotation.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

Automatic injection like that defined above can be controlled through the use of Qualifiers that can help match the specific class that you want injected. If you have multiple payment types, you might add a qualifier for whether it is asynchronous or not. While you can use the @Named annotation as a qualifier, you shouldn’t as it is provided for exposing the beans in EL.

CDI handles the injection of beans with mismatched scopes through the use of proxies. Because of this you can inject a request scoped bean into a session scoped bean and the reference will still be valid on each request because for each request, the proxy re-connects to a live instance of the request scoped bean.

CDI also has support for interceptors, events, the new conversation scope and many other features which makes it a much better choice over JSF managed beans.

EJB

EJBs predate CDI beans and are in someways similar to CDI beans and in other ways very different. Primarily, the differences between CDI beans and EJBs is that EJBs are :

  • Transactional
  • Remote or local
  • Able to passivate stateful beans freeing up resources
  • Able to make use of timers
  • Can be asynchronous

The two types of EJBs are called stateless and stateful. Stateless EJBs can be thought of as thread safe single-use beans that don’t maintain any state between two web requests. Stateful EJBs do hold state and can be created and sit around for as long as they are needed until they are disposed of.

Defining an EJB is simple, you just add either a javax.ejb.Stateless or javax.ejb.Stateful annotation to the class.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Stateless beans must have a dependent scope while a stateful session bean can have any scope. By default they are transactional, but you can use the transaction attribute annotation.

While EJBs and CDI beans are very different in terms of features, writing the code to integrate them is very similar since CDI beans can be injected into EJBs and EJBs can be injected into CDI beans. There is no need to make any distinction when injecting one into the other. Again, the different scopes are handled by CDI through the use of proxying. One exception to this is that CDI does not support the injection of remote EJBs but that can be implemented by writing a simple producer method for it.

The javax.inject.Named annotation as well as any Qualifiers can be used on an EJB to match it to an injection point.

When to use which bean

How do you know when to use which bean? Simple.

Never use JSF managed beans unless you are working in a servlet container and don’t want to try and get CDI working in Tomcat (although there are some Maven archetypes for that so there’s no excuse).

In general, you should use CDI beans unless you need the advanced functionality available in the EJBs such as transactional functions. You can write your own interceptor to make CDI beans transactional, but for now, it's simpler to use an EJB until CDI gets transactional CDI beans which is just around the corner. If you are stuck in a servlet container and are using CDI, then either hand written transactions or your own transaction interceptor is the only option without EJBs.

If you need to use @ViewScoped in CDI you should

  • use seam-faces or MyFaces CODI module. just add one of them to your classpath and @ViewScoped will work in CDI. MyFaces CODI has an even more solid support of @ViewScoped
  • use MyFaces CODI's @ViewAccessScoped, it is an extension written on top of CDI by Apache, just download it and use @ViewAccessScoped annotation instead of @ViewScoped.
  • Use CDI @ConversationScoped and make it long running. See here for more info.
  • Use Omnifaces @ViewScoped annotation

Some parts pilfered from here.

Artichoke answered 17/8, 2012 at 20:20 Comment(17)
This is great! Thanks! To be complete, just tell how to inject CDI or EJB bean into JSF bean. Is the @ManagedProperty("#{someBean})" the proper way?Hoot
Nope! it won't work. just turn your jsf managed bean to CDI managed bean by annotating it using @Named and @javax.enterprise.context.RequestScoped and use CDI injection using @Inject annotation. don't use jsf managed beans if you don't have to ;).Artichoke
@ConversationScoped provided by MyFaces CODI are a lot better. There are interesting slides, but I don't have the link now.Geothermal
MyFaces CODI has a more solid implementation for @ViewScopedGeothermal
>JEE guys want to keep them!!! - It's a bit more subtle than that. CDI finished rather late in the Java EE 6 cycle and both JSF 2 & JAX-RS were already done. They had enhanced resp. introduced their own managed bean facility already. Had CDI been available a little earlier, things might have looked differently. In Java EE 7, JSF will adopt CDI and the javax.faces.bean will eventually be deprecated (deprecation is a slow process in Java EE though, which is both good and bad).Rosanne
As for EJB, CDI has explicitly limited its scope and does not say anything about transaction management, remoting, job scheduling, pooling, etc. Had CDI included those topics, it would have been impossible to finish in time (remember, it was already late), so this was left to EJB. For Java EE 7, several EG members aim to do away with the EJB component model and retrofit its core services as CDI based annotations (see 'decoupling issues at java.net/jira/browse/EJB_SPEC)Rosanne
@Arjan Tijms - You are right, if we had CDI available sooner things might have looked different, but unfortunately it was not! we had many parallel efforts in JEE specifications! and this was wasting the time! All EJB features can now be handled with some well defined CDI Extensions. in my opinion CDI container can play the role of all containers and we can have a unified DI in JEE. CDI EG and developers would like to see that CDI will replace jsf manged beans and EJB but there are still objections. I hope to see this in near future.Artichoke
Originally it didn't seem too much like parallel efforts. JSF 1 (2004) needed its own lightweight DI/Managed Beans since in EJB 2, EJB was unusable. During Java EE 6, the JSF effort was minimal. They really only introduced annotations for their existing XML based configuration. Only late in the game it became known what the scope of CDI was; originally it was called WebBeans and had a much narrower scope (a seam between JSF and EJB). The EJB 3 model already existed as well, the changes for EJB 3.1 in Java EE 6 weren't too big. So, I personally don't saw a lot of wasted parallel efforts.Rosanne
>will replace jsf manged beans and EJB but there are still objections - Who is objecting against JSF managed beans being replaced by CDI?Rosanne
Actually this objection is mostly related to deprecating EJBs not JSF manage beans. they were promoting this component model and after a decade how can they announce that they want to deprecate EJB ;). Have you seen any officially announcement about their deprecation? If they wanted to deprecate them they should have announced it sooner! But I believe that they will do that maybe it would take a little bit more that JSF manage beans. first step was the @Transactional annotation to deprecate EJBs ;) waiting to see the next step!Artichoke
>Who is objecting against JSF managed beans being replaced by CDI?- if you ask EG to deprecate them and stop developing them and completely replace them with CDI beans, will they do that? of course for backward compatibility reasons they should put deprecated stuff in JEE stack until JEE7 or JEE8. I see most JEE developers want to see this but still there is no plans, and may be there are some plans but no announcements. Deprecating EJB will be a great decision because there a many misconception in developers minds, they are thinking about EJB 1 and 2! and don't even look at EJB 3.1 any more!Artichoke
This discussion is interesting, but SO is not the place for it, so this will be my last reply. >will they do that? - Yes, they will. It has already been announced. See java.net/projects/javaserverfaces-spec-public/lists/… >deprecate EJB - That's a strong word. EJB services will live on, but the component model will probably change. With CDI as a base, other specs can contribute extensions. CDI will e.g. not get a view scope, but JSF will contribute a CDI compatible view scope instead. A subtle but important difference.Rosanne
Absolutely you are right. I didn't mean just deprecate EJB and JSF scopes!! I mean they should provide the same services using CDI DI container. In my comments I mentioned that all EJB and JSF services can be served with some well defined extensions. ;)Artichoke
When you say: To deploy CDI beans, you must place a file called beans.xml in a META-INF folder on the classpath. Once you do this, then every bean in the package becomes a CDI bean. Do you mean every bean also becomes a CDI bean in addition to what it was? What if I have JSF ManagedBeans with ManagedBean and ViewScoped. They are still JSF Managed Beans right?Marilumarilyn
Do I really need EJB transaction handling? What about the @Transactional attribute? Shouldn't we use it to make those CDI beans transactional?Downgrade
If you don't use EJB and you want transaction, you can use CDI @ Transactional annotation. But if you are using EJB it is by default transactional and no need to use @ Transactional annotation.Artichoke
Someone able to do an update for Java EE 7 on this great article?Anguiano
P
7

Yep, this can be confusing.

For some ehm historical reasons JSF and CDI are using the same annotations for scopes, but from different packages.

As you are probably guessing those from javax.faces.bean are from the JSF spec, and are not related to CDI. Do not use them unless you have a very good reason to do so. And do never ever mix them with CDI annotations from javax.ejb. This will produce a sheer endless lists of bugs and subtle anomalies.

I generally recommend that you skim the first few (or even more) pages of the excellent Weld documentation. This should put you on track for Java EE 6.

And feel free to post further questions here.

Pampa answered 16/8, 2012 at 13:43 Comment(2)
Actually I have two questions: 1. I often find view scope very useful. I need to use JSF annotations then? 2. It means that @javax.annotation.ManagedBean is useless as CDI treats all classes as managed beans, am I right?Hoot
Not quite. You will need to bridge JSF scopes to CDI with e.g. Seam Faces. And yes, @ManagedBeans are not needed if you have a beans.xml in the relevant jar-file. Oh, and if you have further questions it's better to start a new thread before we loose ourselves in the comment section.Pampa
S
5

Since there are no replies specifically about @javax.annotation.ManagedBean, here's a link to the answer of a similar question: Backing beans (@ManagedBean) or CDI Beans (@Named)?. The spec can be found at http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/. So it looks to me that @javax.annotation.ManagedBean was meant to be a generalization of @javax.faces.bean.ManagedBean.

From what I gathered, JSF Managed Beans are being phased out in favour of CDI Beans (maybe getting deprecated from JSF 2.3?), so I guess @javax.annotation.ManagedBean is all the more becoming obsolete now.

Soapwort answered 17/6, 2014 at 11:19 Comment(2)
@Named will replace @ManagedBean in the future?Listless
I've read several statements by different Java EE experts who predict that the CDI @Named beans will replace JSF @ManagedBeans, e.g. in stackoverflow.com/questions/4347374/…, BalusC says "The expectation is that @ManagedBean and friends will be deprecated as per Java EE 8.".Bangle

© 2022 - 2024 — McMap. All rights reserved.