111

I've just started reading through Core JavaServer Faces, 3rd Ed. and they say this (emphasis mine):

It is a historical accident that there are two separate mechanisms, CDI beans and JSF managed beans, for beans that can be used in JSF pages. We suggest that you use CDI beans unless your application must work on a plain servlet runner such as Tomcat.

Why? They don't provide any justification. I've been using @ManagedBean for all the beans in a prototype application running on GlassFish 3, and I haven't really noticed any issues with this. I don't especially mind migrating from @ManagedBean to @Named, but I want to know why I should bother.

Tiny
  • 24,933
  • 92
  • 299
  • 571
Matt Ball
  • 332,322
  • 92
  • 617
  • 683
  • possible duplicate of [Are @ManagedBean's obsolete in JavaEE6 - because of @Named in CDI/Weld?](http://stackoverflow.com/questions/2930889/are-managedbeans-obsolete-in-javaee6-because-of-named-in-cdi-weld) – Bozho Dec 03 '10 at 16:10
  • 4
    @Bozho: that question is pretty similar, but after reading over Pascal's answer a few times, I still don't understand _why_ CDI is far superior. **I don't know CDI** and I'm happy to learn it since it is "better." Why is it better? – Matt Ball Dec 03 '10 at 16:16
  • "unless your application must work on a plain servlet runner such as Tomcat" I only use tomcat and I strongly recommend CDI. Tomcat can support it just fine – Karl Kildén Aug 17 '12 at 19:48
  • 1
    @KarlKildén "plain servlet runner" refers to a non-CDI capable servlet container. At the time of writing Tomcat did not support CDI except with quite a bit of magic. – Thorbjørn Ravn Andersen Sep 03 '12 at 12:20

5 Answers5

176

Use CDI.

As per JSF 2.3, @ManagedBean is deprecated. See also spec issue 1417. This means that there's not anymore a reason to choose @ManagedBean over @Named. This was first implemented in Mojarra 2.3.0 beta version m06.

enter image description here


History

The core difference is, @ManagedBean is managed by JSF framework and is only via @ManagedProperty available to another JSF managed beans. @Named is managed by application server (the container) via CDI framework and is via @Inject available to any kind of a container managed artifact like @WebListener, @WebFilter, @WebServlet, @Path, @Stateless, etc and even a JSF @ManagedBean. From the other side on, @ManagedProperty does not work inside a @Named or any other container managed artifact. It works really only inside @ManagedBean.

Another difference is that CDI actually injects proxies delegating to the current instance in the target scope on a per-request/thread basis (like as how EJBs are been injected). This mechanism allows injecting a bean of a narrower scope in a bean of a broader scope, which isn't possible with JSF @ManagedProperty. JSF "injects" here the physical instance directly by invoking a setter (that's also exactly why a setter is required, while that is not required with @Inject).

While not directly a disadvantage — there are other ways — the scope of @ManagedBean is simply limited. From the other perspective, if you don't want to expose "too much" for @Inject, you can also just keep your managed beans @ManagedBean. It's like protected versus public. But that doesn't really count.

At least, in JSF 2.0/2.1, the major disadvantage of managing JSF backing beans by CDI is that there's no CDI equivalent of @ViewScoped. The @ConversationScoped comes close, but still requires manually starting and stopping and it appends an ugly cid request parameter to outcome URLs. MyFaces CODI makes it easier by fully transparently bridging JSF's javax.faces.bean.ViewScoped to CDI so you can just do @Named @ViewScoped, however that appends an ugly windowId request parameter to outcome URLs, also on plain vanilla page-to-page navigation. OmniFaces solves this all with a true CDI @ViewScoped which really ties the bean's scope to JSF view state instead of to an arbitrary request parameter.

JSF 2.2 (which is released 3 years after this question/answer) offers a new fully CDI compatible @ViewScoped annotation out the box in flavor of javax.faces.view.ViewScoped. JSF 2.2 even comes along with a CDI-only @FlowScoped which doesn't have a @ManagedBean equivalent, hereby pushing JSF users towards CDI. The expectation is that @ManagedBean and friends will be deprecated as per Java EE 8. If you're currently still using @ManagedBean, it's therefore strongly recommend to switch to CDI to be prepared for future upgrade paths. CDI is readily available in Java EE Web Profile compatible containers, such as WildFly, TomEE and GlassFish. For Tomcat, you have to install it separately, exactly as you already did for JSF. See also How to install CDI in Tomcat?

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 4
    I've created `beans.xml`, converted `@ManagedBean` backing beans to `@Named`, and converted `@ManagedProperty` to `@Inject`. All is well with the world. However, if I change my `@EJB` annotations to `@Inject`, deployment fails (`org.jboss.weld.exceptions.DeploymentException`) with message `WELD-001408 Injection point has unsatisfied dependencies`. Should I actually be using `@Inject` to inject no-interface EJBs into an `@Named` bean, or should I stick with `@EJB`? The EJBs are packaged in an EJB JAR, in the same EAR as the WAR that contains my CDI beans. – Matt Ball Dec 03 '10 at 21:22
  • It should just work. Are you still facing this problem with the current Weld version? – BalusC Apr 07 '13 at 16:56
  • Alas, I couldn't say. This question is from 2 employers and >2 years ago. Based on my old comment on Bozho's answer, I must have switched over to CDI/`@Named`. – Matt Ball Apr 07 '13 at 17:26
  • _"MyFaces CODI makes it easier by fully transparently bridging JSF's javax.faces.bean.ViewScoped to CDI so you can just do `@Named @ViewScoped`, however that appends an ugly windowId request parameter to outcome URLs, also on plain vanilla page-to-page navigation."_ Note that with DeltaSpike this no longer holds true. You can disable both the dsId and windowId URL parameters, if you don't need the Window Scope. – JanM Oct 30 '13 at 13:55
  • 1
    @Jan: And in the meanwhile, OmniFaces has also a JSF 2.2-like `@ViewScoped` for JSF 2.0/2.1: http://showcase.omnifaces.org/cdi/ViewScoped – BalusC Oct 30 '13 at 14:14
64

CDI is preferred over plain JSF because CDI allows for JavaEE-wide dependency injection. You can also inject POJOs and let them be managed. With JSF you can only inject a subset of what you can with CDI.

Bozho
  • 554,002
  • 136
  • 1,025
  • 1,121
  • So basically, I can inject an instance of almost any class (provided it has "the right stuff" - _what is it, just a no-arg constructor?_) with CDI, while I have to use `@ManagedBean` if I want to inject it with plain JSF? – Matt Ball Dec 03 '10 at 16:41
  • 3
    @MattBall Matt after you years, can you comment on this migration? – Koray Tugay May 06 '13 at 10:11
  • 5
    @KorayTugay I haven't touched this code since June 2011 but I had switched to CDI and things worked just fine. I'm happy to answer any specific questions to the best of my memory if you've got them. – Matt Ball May 06 '13 at 13:33
17

With Java EE 6 and CDI you have different option for Managed Beans

  • @javax.faces.bean.ManagedBean is refer to JSR 314 and was introduced with JSF 2.0. The main goal was to avoid the configuration in the faces-config.xml file to use the bean inside an JSF Page.
  • @javax.annotation.ManagedBean(“myBean”) is defined by JSR 316. It generalizes the JSF managed beans for use elsewhere in Java EE
  • @javax.inject.Named(“myBean”) are almost the same, as that one above, except you need a beans.xml file in the web/WEB-INF Folder to activate CDI.
h2mch
  • 511
  • 5
  • 23
  • 1
    What is the difference between the first two? – Matt Ball Dec 09 '10 at 14:33
  • The goal of the first annotation is/was to replace the bean configuration in the faces-config.xml for the usage in JSF. The second one copy the concept into the "java ee 6 container". It has more functions (like @PostConstruct and @PreDestroy annotations), but is also reachable by the JSF Page (with Expression Language). – h2mch Dec 14 '10 at 11:54
  • @h2mch Thank you for this great answer! – Koray Tugay May 26 '13 at 21:28
  • 1
    why do you need a `beans.xml` file? Is this still true today? – Thufir Oct 29 '14 at 13:49
  • 2
    No, with JavaEE7 you don't need the beans.xml any more. see https://docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm – h2mch Nov 24 '14 at 18:06
  • 1
    With JavaEE7 you don't need the beans.xml: https://docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (correct link) https://blogs.oracle.com/theaquarium/entry/default_cdi_enablement_in_java (Default CDI Enablement in Java EE 7) – M. Atif Riaz Oct 31 '16 at 11:21
2

I was using CDI in GlassFish 3.0.1, but to get it to work I had to import the Seam 3 framework (Weld). That worked pretty well.

In GlassFish 3.1 CDI stopped working, and the Seam Weld stopped working with it. I opened a bug on this but haven't seen it fixed yet. I had to convert all my code to using the javax.faces.* annotations but I plan to move back to CDI once they get it working.

I agree you should use CDI, but one issue that I haven't seen resolved yet is what to do with the @ViewScoped annotation. I have a lot of code that depends on it. It is not clear whether @ViewScoped works if you are not using @ManagedBean with it. If anyone can clarify this I would appreciate it.

AlanObject
  • 8,408
  • 18
  • 72
  • 122
-1

One good reason to move to CDI: you could have a common session-scoped resource (user profile for example) @Inject'ed into both JSF managed beans and REST services (i.e., Jersey/JAX-RS).

On the other hand, @ViewScoped is a compelling reason to stick with JSF @ManagedBean - especially for anything with significant AJAX. There is no standard replacement for this in CDI.

Seems that it may have some support for a @ViewScoped-like annotation for CDI beans, but I haven't played with it personally.

http://seamframework.org/Seam3/FacesModule

Tom11
  • 2,199
  • 6
  • 26
  • 50
wrschneider
  • 15,487
  • 10
  • 70
  • 152