Comparing JSF Beans, CDI Beans and EJBs
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.
3 thoughts on “Comparing JSF Beans, CDI Beans and EJBs”
Comments are closed.
short and concise, thanks !
Hi Andy, Very nice article.
By the way using using extension libraries like seam3, DeltaSpike (currently under heavy development) or myfaces codi is recommended because they will add some nice features and utilities and integration with other technologies like Logging, Exception handling, security, etc.
And if you are limited to servlet container and are not able to use EJBs seam3 can help you to make transactional beans and methods using @Transactional annotations.
Hey Andy, I don’t see you in DeltaSpike mailing list!!
—
Share your knowledge and enjoy hacking JEE.
Nice Article, thanks!
I think there is one drawback that should be mentioned by using CDI instead of JSF managed beans – ViewScope is not supported out of the box. I think when developing more modern JSF 2 web applications, this scope is quite important. In conjunction with ViewParams for navigation you can avoid a lot of trouble having mutltiple browser tabs or browser-back issues. For this reason we are using spring 3 beans (with CDI injection), that allowed us to use ViewScope via CustomScopeConfigurer.