13

If I want to keep track of a conversational state with each client using my web application, which is the better alternative - a Session Bean or a HTTP Session - to use?

Using HTTP Session:

//request is a variable of the class javax.servlet.http.HttpServletRequest
//UserState is a POJO
HttpSession session = request.getSession(true);
UserState state = (UserState)(session.getAttribute("UserState"));
if (state == null) { //create default value .. }
String uid = state.getUID();
//now do things with the user id

Using Session EJB:

In the implementation of ServletContextListener registered as a Web Application Listener in WEB-INF/web.xml:

//UserState NOT a POJO this this time, it is
//the interface of the UserStateBean Stateful Session EJB
@EJB
private UserState userStateBean;

public void contextInitialized(ServletContextEvent sce) {
    ServletContext servletContext = sce.getServletContext();
    servletContext.setAttribute("UserState", userStateBean);
    ...

In a JSP:

public void jspInit() {
    UserState state = (UserState)(getServletContext().getAttribute("UserState"));
    ...
}

Elsewhere in the body of the same JSP:

String uid = state.getUID();
//now do things with the user id

It seems to me that the they are almost the same, with the main difference being that the UserState instance is being transported in the HttpRequest.HttpSession in the former, and in a ServletContext in the case of the latter.

Which of the two methods is more robust, and why?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
bguiz
  • 27,371
  • 47
  • 154
  • 243
  • Why did you remove the servlets tag? This is more related to servlet API than the EJB being stateful. In fact, the JSP tag is also irrelevant. – BalusC May 11 '10 at 13:22
  • @BalusC : Cos jsps get compiled to servlets and are effectively the same thing. Also, my question is about stateful session EJBs. – bguiz May 11 '10 at 13:30
  • Cos? Anyway, The `ServletContext` and `HttpSession` are part of Servlet API, not JSP API. The root cause of your problem is exactly there in the Servlet API (actually, the ignorance of the Servlet API). – BalusC May 11 '10 at 13:37

3 Answers3

11

As @BalusC pointed out, in your example the EJB would be the same for all clients -- not what you want.

You can still change that and have one EJB per client, if for instance you create the EJB when the user logs in and store it in the session, or something similar.

But there are other more subtle differences between using the HttpSession and a stateful session bean (SFSB). Especially these two ones:

  1. Exception handling. If a transaction fails in the EJB, the bean is invalidated and can not be used any longer. This can complicate the error handling strategy in the web application.
  2. Concurrency. The same SFSB can not be accessed concurrently, so you will need to synchronize that in the web layer. Again, this can complicate the design.

See this answer for more details: Correct usage of SFSB with Servlets

In summary: I would advise going for the HttpSession approach and against the SFSB in your case; use SFSB only if it provides something you can't do with HttpSession, which isn't the case.

Community
  • 1
  • 1
ewernli
  • 38,045
  • 5
  • 92
  • 123
  • 1
    So my mistake in the code above is that in order to get the Stateful Session EJB to be one instance per client, I have to store them in a `HttpSession` instead of a `ServletContext`? – bguiz May 11 '10 at 13:39
  • 2
    Exactly. The session scope is for exactly this purpose. Storing and tracking client-specific information. – BalusC May 11 '10 at 13:43
3

The ServletContext represents the application scope. Application scoped attributes are shared among all requests in all sessions. It are "application wide globals". You don't want to store client (thus, session) specific information in there. If a new client logs in, the existing EJB in the application scope will be overridden with the client-specific one and be reflected to all clients.

The session scope is exactly for this purpose. Make use of it.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Don't Session EJB's store the conversational state with each client? As in one session bean instance is associated with one client, and retains is client-specific state for the duration of the session... Or have I understood this wrong? – bguiz May 11 '10 at 13:25
  • Yes, they do. But you're overridding the client-specific EJB everytime in the application scope. It will work for 1 client. But with multiple clients, the EJB of the *last* client will be used by all clients. – BalusC May 11 '10 at 13:30
2

Just to clearify a bit: The ServletContext is initialized when a servlet is created (see Servlet Specs) and is unique to that very instance. A servlet uses multiple threads to handle concurrent client requests. The servlet container decides when to create or destroy servlets and delegates the client requests.

This is why you might end up having 1 servlet handling the request for n users (n >= 1) and thus in the above sample code using ServletContext every user would end up sharing the session bean of the user who caused creation of the servlet.

bennidi
  • 2,092
  • 21
  • 27