3

I'm new to EJB, and I'm trying to understand the diference between Stateless and Stateful bean, so I made a simple example to test them.

@Stateless
public class Service {

private int num;

    public Service(){
    }

    public int getNum() {
        return num;
    }

    public void setNum() {
        this.num++;
    }
}

@WebServlet("/Controller1")
public class Controller1 extends HttpServlet {
    @EJB
    private Service serv;

    public Controller1() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        serv.setNum();
        response.getWriter().println(serv.getNum());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

}

And the Stateful equivalent:

@Stateful
public class ServiceStateful implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int num;

    public ServiceStateful(){
    }

    public int getNum() {
        return num;
    }

    public void setNum() {
        this.num++;
    }
}

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

    @EJB
    private ServiceStateful serv;

    public Controller() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        serv.setNum();
        response.getWriter().println(serv.getNum());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

}

Both examples act exactly the same, which is surprising for me. Can someone please explain what is the deal here?

Evgeni Dimitrov
  • 21,976
  • 33
  • 120
  • 145
  • A very small nitpicking comment, but using a name like 'serv' is against most `clean code` standards. Just call it 'service' or so. Additionally, a constructor just calling `super()` is unnecessary. This will be automatically created if left out. – Arjan Tijms Oct 31 '11 at 12:46

4 Answers4

8

Your first example returns the previously set number by chance only : the get method could have been invoked on a different bean instance. It just happened to use the same instance in this particular case, but you can't count on it.

The second one is guaranteed to return you the previously set number, provided another request doesn't call the set method before the get method is called. A stateful bean should not be injected into a servlet.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • 6
    Just to add a rationale behind 'SFSB should not be injected into a servlet' - because the servlet instance is created only once for all requests, you will end with only one SFSB injected into the servlet. If you want 1 SFSB per user you should do JNDI lookup for every new user and store a reference to it in the user session. Doing the JNDI lookup for SFSB is guaranteed to return a fresh instance each time. – Piotr Nowicki Oct 30 '11 at 21:12
  • 1
    +1 for the remark that a SFSB should not be injected into a Servlet. – Arjan Tijms Oct 31 '11 at 12:44
  • @JB Nizet: You mean to say that the 2 method invocations done by serv.setNum(); response.getWriter().println(serv.getNum()) can be Invoked on 2 different STATELESS bean instances, INSIDE THE VERY SAME GET request. – Farhan stands with Palestine May 21 '16 at 11:18
  • 1
    Yes, that's what I mean. stateless beans are pooled, and you have absolutely no guarantee that the same instance is used for 2 method calls, even in the same request. – JB Nizet May 21 '16 at 13:02
3

You can use instance variables of a stateless session bean, but they're not guaranteed to be preserved across method calls. If both approaches behave the same, it simply means you're probably getting the same stateless session bean instance across method calls within the same session.

G_H
  • 11,739
  • 3
  • 38
  • 82
  • 1
    So if there were more Stateless bean instances in the pool, that would be another story... – Evgeni Dimitrov Oct 30 '11 at 17:53
  • Well, it depends on which one gets selected. I guess it'd make sense to keep one from a pool for a session within a certain time frame, or only return it if there's high demand on the pool. This could also depend on the application server that's being used. The only thing that matters is not to rely on the state of a stateless bean outside of one use. – G_H Oct 30 '11 at 17:56
0

A stateful bean maintain it initial state during the conversation with the client (on or many).

A Stateless bean state can be changed (it attributes) during the conversation with the client (doesn't affect other clients)

you can see the difference if you execute multiple times!!

superyass
  • 1
  • 2
0

You are not supposed to have member fields (aka state) in a stateless session bean. For a stateful session bean it's ok. That's the difference.

keuleJ
  • 3,418
  • 4
  • 30
  • 51
  • 4
    You may have state in a stateless bean. For example, references to other stateless beans. What you may not have is *conversational state*. – JB Nizet Oct 30 '11 at 17:50