I am going through the Java EE 6 tutorial and I am trying to understand the difference between stateless and stateful session beans. If stateless session beans do not retain their state in between method calls, why is my program acting the way it is?
package mybeans;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@LocalBean
@Stateless
public class MyBean {
private int number = 0;
public int getNumber() {
return number;
}
public void increment() {
this.number++;
}
}
The client
import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;
@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
MyBean mybean;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
mybean.increment();
out.println(mybean.getNumber());
}
}
I was expecting getNumber to return 0 every time but it is returning 1 and reloads of the servlet in my browser increase it more. The problem is with my understanding of how stateless session beans work and not with the libraries or application server, of course. Can somebody give me a simple hello world type example of a stateless session bean that behaves differently when you change it to stateful?
Stateless Session Beans (SLSB) are not tied to one client and there is no guarantee for one client to get the same instance with each method invocation (some containers may create and destroy beans with each method invocation session, this is an implementation-specific decision, but instances are typically pooled - and I don't mention clustered environments). In other words, although stateless beans may have instance variables, these fields are not specific to one client, so don't rely on them between remote calls.
In contrast, Stateful Session Beans (SFSB) are dedicated to one client for their entire life, there is no swapping or pooling of instances (it may be evicted from memory after passivation to save resources but that's another story) and maintain conversational state. This means that the instance variables of the bean can keep data relative to the client between method invocations. And this makes possible to have interdependent method calls (changes made by one method affect subsequent method calls). Multi-step processes (a registration process, a shopping cart, a booking process...) are typical use cases for SFSB.
One more thing. If you are using SFSB, then you must avoid injecting them into classes that are multithreaded in nature, such as Servlets and JSF managed beans (you don't want it to be shared by all clients). If you want to use SFSB in your web application, then you need to perform a JNDI lookup and store the returned EJB instance in the HttpSession
object for future activity. Something like that:
try {
InitialContext ctx = new InitialContext();
myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
// exception handling
}