Java EE component life cycle and concurrency related details might not be new for seasoned professionals, but it is something which can take time to sink in for beginners.
As far as EJBs are concerned, understanding their life cycle (and related concurrency scenarios) is extremely critical in order to ensure appropriate usage and solution design using EJBs. It’s easy to misuse them !
I’ll quickly cover Stateless and Stateful beans in this post and skip Lima Beans for the time being 😉
- Stateful Session Beans – life cycle + concurrency handling
- Stateless beans – concurrency model only, since I had briefly covered the lifecycle in one of my previous posts.
What are the distinct states in the life cycle of a Stateful Session Bean?
- Does Not Exist
- Ready
- Passivated
How do the states change? What triggers them?
Here is a quick tabular snap shot and a high level diagram. For more details, read on . . .
Note: DNE – Does Not Exist, R – Ready, P – Passivated, SFSB – Statelful Session Bean
State Transition | Triggers | Callbacks |
---|---|---|
DNE to R | When a SFSB instance is first accessed via JNDI or DI | @PostConstruct |
R to DNE | Container shuts down, client invokes method annotated with @Remove, the bean reaches idle time out threshold designated by DD or @StatefulTimeout | @PreDestroy |
R to P | The EJB container passivates idle beans and removes them from active memory based on specific algorithms | @PrePassivate |
P to DNE | The bean reaches idle time out threshold designated by DD or @StatefulTimeout | Note: @PreDestroy annotated method is NOT invoked |
P to R | When the client invokes a SFSB instance after it is passivated but has not timed out yet | @PostActivate |
Note: If a SFSB throws an exception during request processing, its instance is destroyed i.e. it goes to a DNE state. The @PreDestroy annotated method is not invoked in this case
Now that we have some idea about the life cycle of a SFSB, let’s try to take a look at how do these beans behave under load i.e. when the application is used by multiple users at a time which translates into concurrent access of SFSB instances
Stateful Session Beans: Concurrency Management
Thread safety is one of the core features of EJBs. The point to be noted is that this thread safety is free of cost and does not need any concurrency related constructs to be coded in by the bean developer himself (there are a few exceptions). As far as SFSB are concerned, the EJB container ensures that only one thread can access a bean instance at a particular time.
In this example, we are trying to simulate concurrent access to a single instance of a SFSB by invoking a test Servlet via JMeter. The Servlet injects the bean via DI and calls a method on it. The SFSB method just uses a Thread.sleep() to pretend as if it’s executing something.
package com.abhirockzz.wordpress.ejb.lifecycle.stateful; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateful; @Stateful public class MyStatefulBean { public MyStatefulBean() { } public void act() { System.out.println("Entered MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); try { Thread.sleep(2000); } catch (InterruptedException ex) { Logger.getLogger(MyStatefulBean.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Exit MyStatefulBean/act() on " + new Date().toString() + " . SFSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); } }
package com.abhirockzz.wordpress.ejb.lifecycle.stateful; import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "SFSBTestServlet", urlPatterns = {"/SFSBTestServlet"}) public class SFSBTestServlet extends HttpServlet { public SFSBTestServlet() { } @Inject MyStatefulBean mySFSB; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Entered SFSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); mySFSB.act(); } }
Observations
- Since a Servlet itself is not thread safe, multiple threads will in fact enter the doGet() method
- A single instance of the SFSB (evident via the hashCode result) in being accessed concurrently (see the thread names in the logged statements)
- Only one thread will be able to access the SFSB instance though – other threads wait for their turn while the SFSB method returns. This delay is noticeable via the log statements on the console
What about Stateless Beans?
These beans are inherently thread safe. Why? It is because by default, the container makes sure that each new request is served by a new instance of the bean. Remember, that a client can obtain a reference to stateless bean in 3 possible ways – DI, JNDI or via a remote interface (RMI). In all these cases, it is the container (proxy) which intercepts the call – thus, even if multiple threads are seemingly accessing the same bean instance, its actually not the same one 😉
package com.abhirockzz.wordpress.ejb.lifecycle.stateless; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateless; @Stateless public class MyStatelesslBean { public void act() { System.out.println("Entered MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); try { Thread.sleep(2000); } catch (InterruptedException ex) { Logger.getLogger(MyStatelesslBean.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Exit MyStatelesslBean/act() on " + new Date().toString() + " . SLSB instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); } }
package com.abhirockzz.wordpress.ejb.lifecycle.stateless; import java.io.IOException; import java.util.Date; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "SLSBTestServlet", urlPatterns = {"/SLSBTestServlet"}) public class SLSBTestServlet extends HttpServlet { @Inject MyStatelesslBean slsb; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Entered SLSBTestServlet/doGet() on " + new Date().toString() + " . Servlet instance " + this.hashCode() + " Thread : " + Thread.currentThread().getName()); slsb.act(); } }
Observations
- Since a Servlet itself is not thread safe, multiple threads will in fact enter the doGet() method
- Different instances of the SLSB (evident via the hashCode result) are being picked by the container to manage concurrent requests (see the thread names in the logged statements).
- In spite of concurrent requests, each request thread is getting serviced by a new instance
That’s all for now! I am planning to cover Singleton Session beans in a future post. Stay tuned . . . .
Thanks for reading! 🙂
Pingback: EJB 3.x : Lifecycle and Concurrency models (part 2) | Object Oriented . .
Thanks. This is a great post !! I want to a question if you don’t mind. In my internship I was developing Restful Web Services on Jboss application container. The issue was we had’t been using any @Stateful or @Stateless annotations. We were only using annotations for java’s own CDI which like @Named, @Inject, @PostConstruct etc. And were weren’t using any java synchronization modifiers also. When I asked my senior how we handle with concurrency issues for transactions, he told me hat JBoss automatically distributes requests to threads from thread pool, and those threads are handles with concurrency. Is that totally true ?
LikeLike
Thank you for reading and really glad you liked the content!
Concurrency and transactions are really different topics in my opinion. I am not going to mix them up….
JBoss is an application server, but to be honest, JBoss or any application server does not do anything automatically. What I mean to say is that services like concurrency (thread safety), transactions etc are provided by components of a container (or maybe you can call them sub containers, virtual containers or simply run time environments) e,g. the EJB container, CDI container etc. So its really the container which renders these services to you if you ask for it. You cannot expect a plain old java class executing in an application server to be thread safe 🙂 What you can do is request the container to do so – in Java EE its best achieved by use of annotations specific to that container e.g. @Stateless in case of EJBs
Coming to your scenario of a Restful Web Service
Just to repeat my point – nothing is done automatically. You need to give some hint to the container (mostly in the form of annotations) and you are good to go!
Hope this helped. All the best!
LikeLike
Sorry for late reply (: I understand more clear after your answer. Thanks !
LikeLike
Pingback: Java Weekly #9: Money, retired DTOs, JSR for MVC, JDK tools aand more... - Thoughts on Java -
Thank you very much for all your writing! I am starting to learn Java EE and reading some your articles has been very helpful in understanding concepts for which I had found no useful information anywhere else. However, there are some scenarios for which the lifecycle of the EJBs is still not clear to me and I would like to ask you some questions about this.
Could you please shed some light on the definitions of a ‘client request’ and a ‘session’?
I ask because I would like to inject some session beans into a singleton EJB and am not sure what their lifecycle would be in this case. All the information I have found mentions client requests (as in remote applications or servlet-type calls) but I have not been able to find what exactly constitutes such ‘clients’, ‘requests’, and ‘sessions’. Hence, my next question:
What would be the lifecycle of a SFSB or a SLSB when it is injected into a singleton EJB? Considering that, as I understand, one instance of the singleton is always active, would the session beans that it instantiates remain always active as well? Would a ‘client request’ to the session beans be their injection as an instance variable of the singleton or a call to one of their methods?
In your example of the SLSB, would it make sense (is it possible? would it make a difference?) to inject the SLSB as a local variable inside the doGet method, as opposed to as an instance variable of the servlet class (since each call uses a different instance)? Would it make sense to do it with a session bean injection into a singleton?
LikeLike
Thanks for reading the post and glad you found it useful. I’ll try and answer this in short
Stateless beans: if you inject them (using @Inject @EJB), the container can give you ANY instance from the pool (which is free) e.g. two consecutive requests might result in you getting the same instance (from JVM heap) or they might be different instances – hence the name Stateless ( you cant depend on the instance specific state). It is the same even if you inject it in Servlet or Singleton EJB
Stateful: In this case, its a unique instance per client. Now what’s a client ? It ‘s the component which in using/injecting the Stateful bean instance e.g. if a Singleton bean injects a Stateful bean, it will ALWAYS be attached to the same instance of the Stateful bean since the client (Singleton bean) itself is the same – as I said, unique instance per client. E.g. if you inject a Stateful bean in a request scoped JSF managed bean, you’ll get a unique instance of the Stateful bean per invocation of the JSF managed bean (since its request scoped)
As far as injecting vs. using a SLSB instance in servlet is concerned – it does not make sense to localize the use of a SLSB within a servlet method (but its definitely possible). The entire point of using the SLSB is to get behaviour ‘without’ state
You can also refer my free ebook on EJBs 🙂 This might sound like a shameless plug, but I am just pointing it out not because it perfect, but because it’s free and simple (specially for beginners). Mind you, there are other awesome resources out there ! 🙂
HTH
Cheers!
LikeLike
There is a wrong titile or wrong picture for a stateless bean lifecycle – it cannot be passivated. Container can passivate statefull beans only
LikeLiked by 1 person