Skip to main content

Is @javax.faces.bean.ManagedBean Dead on Arrival?

Posted by cayhorstmann on December 23, 2009 at 5:46 PM PST

Java EE 6 has three different ways of defining “beans” that are “managed” in one way or another. Here is a quick recap.

JSR 314

JSF 2.0 introduced annotations to avoid the tedium of declaring managed beans in faces-config.xml:

@javax.faces.bean.ManagedBean(name="user")
@javax.faces.bean.SessionScoped
public class UserBean implements Serializable {
   ...
}

That's certainly nicer than

<managed-bean> 
   <managed-bean-name>user</managed-bean-name>
   <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
   <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

There is a second annotation for a rudimentary dependency injection mechanism:

public class EditBean {
   @javax.faces.bean.ManagedProperty(value="#{user}")
   private UserBean currentUser;
}

When an EditBean instance is constructed, the value expression #{user} is evaluated, and the result is passed to the setCurrentUser method (which you must also supply)

(It is a bit odd that the @ManagedProperty annotation is applied to a field when in fact the property setter is invoked. That is not how injection works elsewhere in Java EE. Let's not dwell on this oddity.)

JSR 316

There is an annotation @javax.annotation.ManagedBean, defined by JSR 316, that attempts to generalize JSF managed beans for use elsewhere in Java EE. There isn't much there. You can use the @PostConstruct and @PreDestroy annotations. You can use @Resource for injecting EE resources. You can use interceptors. For example, if you define

@javax.annotation.ManagedBean("user") public class UserBean ...

then you can construct an instance by making a JNDI lookup for java:module/user. But there is no interaction with an expression language, and there is no notion of scopes. So, perhaps this kind of managed bean isn't going to see a lot of love.

JSR 299

In an EE 6 container, you can use JSR 299 “contexts and dependency injection” (CDI), like this:

@javax.inject.Named("user")
@javax.enterprise.context.SessionScoped
public class UserBean implements Serializable {
   ...
}

Now you refer to the bean as #{user} in JSF, just like you would with JSF managed beans.

If you try this out, remember to put an empty beans.xml into web/WEB-INF to trigger the CDI implementation. This works today with GlassFish v3.

What is the advantage? Well, first off, @Named("user") is shorter than @ManagedBean(name="user"), so you are doing your part alleviating the global pixel shortage.

The advocates of CDI will tell you that they offer facilities for managing beans that go far beyond what JSF has to offer, and that is certainly true. For example, injection works with types, not EL expressions. You would use

@Inject private UserBean currentUser;

Then the CDI implementation automatically injects the UserBean of the appropriate scope. You use annotations (which you define) to control this process, such as

@Inject @LoggedIn private UserBean currentUser;

I won't go into detail here. See the documentation of Weld, the CDI reference implementation, which is very well written. For a quick intro, check out this blog by Roger Kitain.

Dependency injection is all good and well, but here is a more immediate “selling point” for a JSF programmer. CDI supports the usual request, session, and application scope, but it also provides a conversation scope, a scope whose lifetime is controlled by the application. That's a sorely needed feature to deal with two separate problems: session bloat and multiple browser windows. Again, the Weld documentation describes this quite nicely.

Now What?

So, should we ditch @javax.faces.bean.ManagedBean before too many people get used to it? If you deploy in an EE 6 container, then there is really no reason to use @ManagedBean. Just use @Named and start using CDI—it's there, so why not take advantage of it? If you use Tomcat or another servlet runner, you can also get CDI by adding the Weld implementation to your web app. According to a recent conversation on the jsr-314-open mailing list (which, sadly, doesn't seem to be archived), Spring 3.0 supports @Named as well, so that seems to be the way to go for consistent examples.

On the flip side, IDE support isn't quite there yet (see this bug—please vote for it), and there will always be some people who will want to use Tomcat without any additional libraries.

Why do I care? We have a very short window for replacing all @ManagedBean with @Named before the 3rd edition of Core JSF goes to print, and I wonder whether we should do it. Please comment! (But please, no flame wars on JSF or CDI—there is a better forum for those :-))

Related Topics >>

Comments

Managed Beans

Three separate concepts is confusing at best. If the Faces managed bean annotations are truly necessary, they should have been prefixed with Faces like FacesValidator and FacesConverter to avoid confusion. That said, why can't JSF use the javax.enterprise.context annotations and be adaptive to whether CDI is currently in use, like it's adaptiveness to whether Bean Validation is available?

I've been using CDI with JSF 2, Facelets 1.1.15 and RichFaces 3.3.3-BETA1 for the past month or so, and @Named is beautifully simple. @ConversationScope and @ViewScope (had to look around for that one) are wonderful too.

I still have yet to understand @javax.annotation.ManagedBean does. The spec says that any class meeting certain criteria is automatically a managed bean, so what is the annotation for? The spec says a managed bean must have a no-arg constructor - does this include the default constructor that is automatically created if I don't define one myself? I've had situations while trying to grind through learning this where I annotation a class as a managed bean, inject an EntityManager with @Resource, then come to find that not only was the EntityManager not injected, but the container doesn't tell me that - for what ever reason - it didn't make the @ManagedBean class a managed bean.

On the whole I'm in love Java EE 6, but I'm looking forward to MR1 to polish out some of these issues.

Please make the switch.

@ManagedBean and @ManagedProperty are a step sideways, CDI is a leap forward!

"We have a very short window

"We have a very short window for replacing all @ManagedBean with @Named before the 3rd edition of Core JSF goes to print, and I wonder whether we should do it."

Yes, you should do that before to print the book.. otherwise you take the risk to deliver an obsolete book even before it is on the bookshelves... :)

 

Definitely

Absolutely, make the switch!

The @javax.annotation.ManagedBean should be considered a low-level construct in Java EE and never exposed to the end developer. All CDI-recognized beans are technically managed beans, but they are also scoped, able to support qualifiers (for type-safe injection) and available to the EL (if annotated @Named). It's just inhibitive to use the low-level @javax.annotation.ManagedBean, or to even show it.

As for the JSF managed bean annotations, JSF has no business managing beans. It should worry about the UI. That's complex enough.

I agree

If @ManagedBean is used, everytime I open the book I have to remember to convert all @ManagedBean to @Named.

Use pruning

Hi Cay, first of all, @javax.annotation.ManagedBean, is in JSR 250, not 316. The ManagedBean specification is part of 316, but not the annotation itself. I think @javax.faces.bean.ManagedBean should be prunned ASAP (why not in a JSF 2.1 maintenance release of the spec). Pruning has been introduced with Java EE 6 (EJB CMP, JAX-R, JAX-RPC and JSR 88). Other specifications could benefit from that, and I agree with you, people should stop using @javax.annotation.ManagedBean, pruning is a strong message to do so.

CDI should be the core programming model

To my opinion it's a very bad choice to have 3 ways to define managed beans. It makes it hard to understand for people new to the platform, while there are no advantages of not using CDI. Yes, JSF can now be used in a Servlet environment instead of a full JEE 6 (Web profile) environment, but this shouldn't be promoted by the platform. JEE should have a single, clear, programming model. CDI should be the core of this programming model, and provide a uniform way to deal with managed beans and dependency injection. I'm dealing with the same problem as you Cay, I'm a teacher, so what should we learn people to use? I have a strong preference to get as much people to use CDI.

3 ways

I'm not sure that it's a very bad choice to have 3 ways to define managed beans. Maybe It makes it hard to understand for people new to the platform, but the most important thing that JSF can now be used in a Servlet environment and it would be a big advantage for this model.

I plan to use @Named instead

I plan to use @Named instead of @ManagedBean from JSF 2.0. The fist time I started working on Java EE 6 I found it difficult to decide if I should use javax.annotation.ManagedBean or javax.faces.bean.ManagedBean. I think I'll stick with CDI.

Yes, prefer CDI to JSF managed beans

I'd recommend going ahead and switching out the @ManagedBean examples etc with @Named. I think there are very few good reasons to develop a (new) JSF application without CDI. I really believe you'll be doing your readers a favor. (Full disclosure: I'm on the JSR 299 EG.)