CDI enriches the EJB specification (Session beans to be specific) by providing contextual life cycle management. Session beans are not ‘contextual’ instances in general.
If you are comfortable with CDI in general, the idea of ‘being contextual’ should be pretty clear.
Here are the valid permutations and combinations of EJB session beans and corresponding CDI scopes (Application, Session or Request)
- Stateless beans can only belong to the @Dependent scope i.e. you can either choose to use the @Dependent pseudo-scope explicitly or just flow with the @Stateless annotation in which case the CDI container will pretty much use @Dependent by default (convention).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//This is valid | |
@Stateless | |
@Dependent | |
public class EJB1 { | |
@PostConstruct | |
public void init(){ | |
System.out.println(EJB1.class.getName() + " constructed successfully on "+ new Date().toString()); | |
} | |
} | |
//This is NOT valid | |
@Stateless | |
@RequestScoped | |
public class EJB1 { | |
@PostConstruct | |
public void init(){ | |
System.out.println(EJB1.class.getName() + " constructed successfully on "+ new Date().toString()); | |
} | |
} | |
//CDI container will complain | |
Caused by: org.jboss.weld.exceptions.DefinitionException: WELD–000082: Scope interface javax.enterprise.context.RequestScoped is not allowed on stateless enterprise beans for class cdi.ejb.integration.EJB1. Only @Dependent is allowed on stateless session beans. | |
at org.jboss.weld.bean.SessionBean.checkScopeAllowed(SessionBean.java:122) | |
at org.jboss.weld.bean.SessionBean.internalInitialize(SessionBean.java:101) | |
at org.jboss.weld.bean.RIBean.initialize(RIBean.java:66) | |
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$5.doWork(ConcurrentBeanDeployer.java:118) | |
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$5.doWork(ConcurrentBeanDeployer.java:115) | |
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:59) | |
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:52) | |
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_25] | |
… 3 more |
The CDI container will not let you get away with any other annotation and the end result would be a deployment failure
- With Singleton beans, @ApplicationScoped is the only valid CDI scope (@Dependent is the default in case you do not use any other explicit CDI scope)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//This is legal | |
@Singleton | |
@Startup | |
@ApplicationScoped | |
public class Singleton1 { | |
@PostConstruct | |
public void init(){ | |
System.out.println(Singleton1.class.getName() + " constructed successfully on "+ new Date().toString()); | |
} | |
} | |
//CDI container will not be happy seeing this | |
@Singleton | |
@Startup | |
@RequestScoped | |
public class Singleton1 { | |
@PostConstruct | |
public void init(){ | |
System.out.println(Singleton1.class.getName() + " constructed successfully on "+ new Date().toString()); | |
} | |
} | |
Caused by: org.jboss.weld.exceptions.DefinitionException: WELD–000083: Scope interface javax.enterprise.context.RequestScoped is not allowed on singleton enterprise beans for class cdi.ejb.integration.Singleton1. Only @Dependent and @ApplicationScoped is allowed on singleton session beans. | |
at org.jboss.weld.bean.SessionBean.checkScopeAllowed(SessionBean.java:125) | |
at org.jboss.weld.bean.SessionBean.internalInitialize(SessionBean.java:101) | |
at org.jboss.weld.bean.RIBean.initialize(RIBean.java:66) | |
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$5.doWork(ConcurrentBeanDeployer.java:118) | |
at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$5.doWork(ConcurrentBeanDeployer.java:115) | |
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:59) | |
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:52) | |
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_25] | |
… 3 more |
Again, any other scope annotation and the CDI god will crush your WAR/EAR !
- Stateful EJBs can have any scope – no restrictions whatsoever! (although I do not see too much value in using @ApplicationScoped for Stateful beans – but that’s just me! feel free to chime in case you think otherwise)
Stay safe !
Cheers 😉
Nice post !
LikeLike
Thanks for reading Verison. Really glad you liked it ! 🙂
LikeLike
Thanks, this post filled a gap and was exactly what I was looking for!
I’m not sure if I have understood correctly but why don’t you see any point with @Stateful combined with @ApplicationScoped? Do you mean that it’s practically the same as @Singleton (possibly combined with @ApplicationScoped)?
I made a fast experiment. I have a @ViewScoped bean injecting a service into it:
Service with just @Stateful: The service defaults to view scope.
Service with @Stateful and @ApplicationScoped: The service becomes application scoped.
So @ApplicationScoped changes things here, so why don’t you recommend that combination?
Cheers,
Patrik
LikeLike