There’s still a lot of confusion over the difference types of managed beans provided in Java EE 6 with EJBs, CDI beans and JSF managed beans all being available. This article aims to clear up some of the differences between the them and define when to use them.

A number of people assume that there is some meaning to all these different types of beans that they just don’t understand. However, the problem is down to the different APIs overlapping which is unfortunate.

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, but they all involve the same process. Typically a class has to be identified as a managed bean, and where necessary, will need a scope,qualifiers and a name if it is to be used in JSF. What follows is a brief description of the different types of managed beans and how and when to 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, applicaion, 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 feaures, 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 I have a Maven archetype 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, its 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.