2
votes

I created Stateful, Stateless and singleton bean classes and trying to access them two different servlet. And running project on JBoss server.

When I access Stateful bean from each servlet two different bean object will be created and different states(data) are preserved for them. But stateless bean object is shared between both servlet. Singleton bean also behaves same way as stateless bean.

My question is why stateful and stateless bean behaves in opposite way? Is lifecycle of session bean is same as lifecycle of servlet?

FirstServlet.java

@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@EJB
StatelessBean statelessBean;

@EJB
StateFullBean statefulBean;

@EJB
SingletonBean singletonBean;

protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    String message = "Beans not injected.";

    String beanType = request.getParameter("beanType");

    if ("Stateless".equals(beanType)) {
        if (statelessBean != null) {
            message = statelessBean.getHits();
        } else {
            message = "Stateless bean not injected.";
        }
    }

    if ("Stateful".equals(beanType)) {
        if (statefulBean != null) {
            message = statefulBean.getHits();
        } else {
            message = "Stateful bean not injected.";
        }
    }

    if ("Singleton".equals(beanType)) {
        if (singletonBean != null) {
            message = singletonBean.getHits();
        } else {
            message = "Singleton bean not injected.";
        }
    }

    response.setContentType("text/html");
    response.getWriter().print("<h1>" + message + "</h1>");
}
}

Similarly, I created one more servlet DemoServlet.java.

StateFullBean.java

@Stateful
public class StateFullBean{

int hits=0;

public String getHits() {
    hits++;
    return "StateFullBean number of hits " + hits;
}

public StateFullBean() {
    System.out.println("StateFullBean created.");
}
}

StatelessBean.java

@Stateless
public class StatelessBean{

int hits=0;

public String getHits() {
    hits++;
    return "StatelessBean number of hits " + hits;
}

public StatelessBean() {
    System.out.println("StatelessBean created.");
}
}

SingletonBean.java

@Startup
@Singleton(name="SingletonBean")
public class SingletonBean {

int hits=0;

public SingletonBean() {
    System.out.println("SingletonBean created.");
}

public String getHits() {
    hits++;
    return "Singleton bean number of hits " + hits;
}
}

Am I missed something in code?

1

1 Answers

1
votes

Everything is behaving as specified.

A stateless EJB delegates the call further to currently available instance in the pool. Apparently there's only one which is not used concurrently (yet) and therefore all clients have the same chance to access the same instance in the pool. If you fire more HTTP requests concurrently on the servlet(s), then chances increase that there's no available instance anymore and the container will create a new instance in the pool.

A stateful EJB is tied to its client (in your case, the web servlet instance). In other words, each servlet has its own stateful EJB instance which is not shared elsewhere.

A singleton bean is application wide and shared across all clients. In other words, each servlet will share the same singleton EJB instance.

Do note that the terms "client" and "session" in EJB context are absolutely not the same as those in WAR context and this is where many starters fall over. The EJB client is not the webbrowser, but the instance of the class where the EJB is injected (in your case, the web servlet instance). The EJB session is not the HTTP session, but the EJB-client session.

See also: