It is currently indeed a bit confusing as there are now multiple component models in Java EE. They are CDI, EJB3 and JSF Managed Beans.
CDI is the new kid on the block. CDI beans feature dependency injection
, scoping
and an event bus
. CDI beans are the most flexible with respect to injection and scoping. The event bus is very lightweight and very well suited for even the simplest of web applications. In addition to this, CDI also exposes a very advanced feature called portable extensions
, which is a kind of plug-in mechanism for vendors to provide extra functionality to Java EE that can be made available on all implementations (Glassfish, JBoss AS, Websphere, etc).
EJB3 beans were retrofitted from the old legacy EJB2 component model* and were the first beans in Java EE to be managed beans via an annotation. EJB3 beans feature dependency injection
, declarative transactions
, declarative security
, pooling
, concurrency control
, asynchronous execution
and remoting
.
Dependency injection in EJB3 beans is not as flexible as in CDI beans and EJB3 beans have no concept of scoping. However, EJB3 beans are transactional and pooled by default**, two very useable things that CDI has chosen to leave in the domain of EJB3. The other mentioned items are also not available in CDI. EJB3 has no event bus of its own though, but it does have a special type of bean for listening to messages; the message driven bean. This can be used to receive messages from the Java Messaging System or from any other system that has a JCA resource adaptor. Using full blown messaging for simple events is far more heavyweight than the CDI event bus and EJB3 only defines a listener, not a producer API.
JSF Managed Beans have existed in Java EE ever since JSF was included. They too feature dependency injection
and scoping
. JSF Managed Beans introduced the concept of declarative scoping. Originally the scopes were rather limited and in the same version of Java EE where EJB3 beans could already be declared via annotations, JSF Managed Beans still had to be declared in XML. The current version of JSF Managed Beans are also finally declared via an annotation and the scopes are expanded with a view scope and the ability to create custom scopes. The view scope, which remembers data between requests to the same page is a unique feature of JSF Managed Beans.
Apart from the view scope, there is very little still going for JSF Managed Beans in Java EE 6. The missing view scope in CDI there is unfortunate, since otherwise CDI would have been a perfect super set of what JSF Managed Beans offer. Update: In Java EE 7/JSF 2.2 a CDI compatible @ViewScoped has been added, making CDI indeed that perfect super set. Update 2: In JSF2.3 the JSF managed beans have been deprecated in favour of CDI managed beans.
With EJB3 and CDI the situation is not that clear cut. The EJB3 component model and API offers a lot of services that CDI does not offer, so typically EJB3 cannot be replaced by CDI. On the other hand, CDI can be used in combination with EJB3 - e.g. adding scope support to EJBs.
Reza Rahman, expert group member and implementor of a CDI implementation called CanDI, has frequently hinted that the services associated with the EJB3 component model can be retrofitted as a set of CDI annotations. If that were to happen, all managed beans in Java EE could become CDI beans. This does not mean that EJB3 disappears or becomes obsolete, but just that its functionality will be exposed via CDI instead of via EJB's own annotations like @Stateless and @EJB.
Update
David Blevins of TomEE and OpenEJB fame explains the differences and similarities between CDI and EJB very well on his blog: CDI, when to break out the EJBs
*
Although it's just an increment in version number, EJB3 beans were for the most part a completely different kind of bean: a simple pojo that becomes a "managed bean" by applying a simple single annotation, vs the model in EJB2 where a heavyweight and overly verbose XML deployment descriptor was required for each and every bean, in addition to the bean being required to implement various extremely heavyweight and for the most part meaningless component interfaces.
** Stateless session beans are typically pooled, stateful session beans typically not (but they can be). For both types pooling is thus optional and the EJB spec does not mandate it either way.
You can absolutely do what you mention and use @RequestScoped
beans in an @Stateless
session bean and an @MessageDriven
bean. This is a core part of the CDI spec and TCK and guaranteed portable.
Note on MDBs
Do be aware that there is a test for a @Stateless
bean that uses a @RequestScoped
bean, but there is no test that guarantees a @MessageDriven
bean can reference @RequestScoped
beans. This was just an oversight and is already fixed for the Java EE 7 TCK. So just be aware that if it doesn't work for the MDB case, it may not be your fault :)
The workaround would be to simply have your MDB delegate to a SessionBean of any kind as @Stateless
, @Stateful
, and @Singleton
all have @RequestScoped
tests.
Making the EJB, itself, scoped
While @Stateless
, @Singleton
and @MessageDriven
can have scoped references injected via @Inject
, they cannot be @RequestScoped
or any other scope. Only the @Stateful
model is flexible enough to support scopes. In other words, you can annotate the @Stateful
bean class itself as @RequestScoped
, @SessionScoped
, etc..
In simple terms @Stateless
, @Singleton
have fixed "scopes" already. @Singleton
is essentially @ApplicationScoped
and @Stateless
would perhaps be some made-up scope like @InvocationScoped
, if that existed. The lifecycle of an @MessageDriven
bean is entirely up to the Connector that drives it and is therefore also not allowed to have user-defined scope.
Best Answer
While
@Stateless
,@Singleton
and@MessageDriven
can have scoped references injected via@Inject
, they cannot be@RequestScoped
or any other scope. Only the@Stateful
model is flexible enough to support scopes. In other words, you can annotate the@Stateful
bean class itself as@RequestScoped
,@SessionScoped
, etc..In simple terms
@Stateless
,@Singleton
have fixed "scopes" already.@Singleton
is essentially@ApplicationScoped
and@Stateless
would perhaps be some made-up scope like@InvocationScoped
, if that existed. The lifecycle of an@MessageDriven
bean is entirely up to the Connector that drives it and is therefore also not allowed to have user-defined scope.See also https://stackoverflow.com/a/8720148/190816