Lookup returns new instance of Stateful session bean
Asked Answered
D

1

5

I am using Java EE 5, EJB 3.0, Jboss AS 4.3.2.
I have simplest Stateful bean

@Local
public interface IStateBean 
{
}
@Stateful
public class StateBean implements IStateBean
{  
   private static int number = 0;

   @PostConstruct
   void init()
   {
      number++;
      System.out.println("@PostConstruct: " + number);
   }

   @PreDestroy
   void destroy()
   {
      number--;
      System.out.println("@PreDestroy: " + number);  
   }
}

I do lookup in servlet for this bean

public class MyServlet extends HttpServlet
{  
   @Override
   public void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException
   {  
      IStateBean bean = new InitialContext().lookup("app-ear/StateBean/local");
      // ...
   }
}  

But each time new instance of StateBean is created.
I can call lookup twice but new instance of StateBean is created again

   @Override
   public void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException
   {  
      IStateBean bean1 = new InitialContext().lookup("app-ear/StateBean/local"); 
      IStateBean bean2 = new InitialContext().lookup("app-ear/StateBean/local"); // new instance is created
      // ...
   }  

I expect the same instance in the same http-session

Servlet mapping in web.xml

   <servlet>
      <servlet-name>MyServlet</servlet-name>
      <servlet-class>com.package.MyServlet</servlet-class>
   </servlet>  
   <servlet-mapping>
      <servlet-name>MyServlet</servlet-name>
      <url-pattern>*.html</url-pattern>
   </servlet-mapping>
Docilla answered 11/11, 2013 at 10:33 Comment(0)
F
9

The EJB spec does not say, that multiple lookups will return the same instance of a stateful session bean. In opposite: It is even required for the server to create two different instances, to guarantee that every client gets his own instance on the server.

The EJB spec only says that while you're referencing a stateful session bean, it retains its internal state across multiple method invocations:

IStateBean bean = new InitialContext().lookup("app-ear/StateBean/local");
bean.myMethod1();
bean.myMethod2(); // affects the same EJB instance on the server

Note that this might NOT be the case when using stateless session beans. Here, the two method calls shown above might go to different instances on the server!

Falsify answered 11/11, 2013 at 10:45 Comment(5)
I agree... to solve the problem you should store the reference to the statefull bean on the client side (e.g. in the caller's HTTPSession) and always use this reference for accessing the EJBMatamoros
I wonder if there is a resource somewhere that properly (clearly) explains this to link to in these cases; this must be the most misunderstood thing about stateful beans ever.Dardanus
@Matamoros Yes, that would solve the problem. But it might have negative impacts on scalability. I always try to NOT use SFSB at all or at least not use SFSB across user conversations.Falsify
@Falsify but this is exactly what you should use SFSB for... to keep state during a conversation with the client. As long as you dispose your beans appropriately usually you don't run into resource problems as long as you dont serve a massive amount of clients on a "small" server. If you don't want to use SFSB you need to pass the state from the client to a SLSB via parametersMatamoros
@Matamoros I agree. Maybe I'm a little bit paranoiac concerning that topic. Until now most of the time I could avoid server side client state using a RESTful approach in combination with rich clients (where holding state is not an issue). Of course, pure web apps are another story...Falsify

© 2022 - 2024 — McMap. All rights reserved.