geronimo-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Quintin Beukes <quin...@skywalk.co.za>
Subject Re: Stateful session bean has no state
Date Tue, 13 Oct 2009 11:45:34 GMT
Hey,

I made a mistake in the example code - I forgot to update the session,
please replace into it the following method:
public void doGet(....)
{
 HttpSession session = request.getSession();
 MyApplication app = session.getAttribute("MyApplication");
 if (app == null)
 {
   app = new MyApplication();
   new InitialContent().bind("inject", app);
   session.setAttribute("MyApplication", app);
 }
 app.handleCartRequest(request, response);
}

Quintin Beukes



On Tue, Oct 13, 2009 at 1:43 PM, Quintin Beukes <quintin@skywalk.co.za> wrote:
> No problem. Your question and intentions are completely valid.
>
> See my answers below.
>
>> Thank you once again. Now it has state, the problem now is that it has the
>> same state for everybody. I used two browsers at a time, a Firefox and an
>> IE. They both had the same state, if I refreshed one of them then the number
>> had been incremented for the other one. By the way, I used @EJB annotations
>> to have my SFSB injected in my servlet (in case it helps).
>
> Most servlet containers only have one instance of the servlet. So when
> you inject via the @EJB annotation, all clients will receive the exact
> same instance, because only one injection is made when the servlet
> class is instantiated. In general, remember this, you should not store
> ANY client specific data as member fields in the servlet, because
> those fields will be shared by the client. If you need client specific
> data, store it in a separate object attached to one of the servlet
> contexts unique to the client (request/session).
>
> Some servlet containers create more than one instance of the servlet
> class, but still a single instance may be shared, so never keep any
> type of state other than page/application state as fields in the
> servlet class.
>
>> Just in case you were about to reply that I have to look for my SFSB in my
>> session and if there's no SFSB there I have to look up via JNDI, right?
>> Well, however, it seems I will have to do all the work to keep an object
>> (the SFSB) per session, so... what's the use of Stateful Session Beans? If I
>> will have to do all the work by myself, I can create an object (not a EJB,
>> but a simple POJO) and avoid using complicated EJBs. I mean, I though
>> container was responsible of assigning a SFSB to each session.
>
> Unfortunately a lookup via JNDI is the case if you want client
> specific instances. I recommend doing something like a simple facade:
> private MyStatefulEjbLocal getEjb(HttpSession session)
> {
>  MyStatefulEjbLocal ejb =session.getAttribute("MyStatefulEjb");
>  if (ejb == null)
>  {
>     ejb = new InitialContext().lookup("MyStatefulEjbLocal");
>     session.setAttribute("MyStatefulEjb", ejb);
>  }
>  return ejb;
> }
>
> Then you can retrieve the EJB at anytime using getEjb(), only passing
> in the session (or another object from which the session can be
> retrieved).
>
> And sure, you can use a simple POJO as well. The reason for using EJBs
> are more than ease of use. In fact, the first 2 EJBs specs were
> anything but easy. You use EJBs to wrap code in container managed
> transactions, or more easily run it on clusters or remote servers -
> enterprise stuff. If you merely want to keep state throughout a
> session and don't care for these EJB specific features, then a POJO
> might be a much better option, and much more light weight. Though
> using EJBs you do have the potential flexibility and power of EJBs at
> your disposal.
>
>> Please, don't see me as an EJB detractor, I'm only asking because I really
>> liked the fact that using Stateful Session Beans I could forget about
>> managing objects in session as the container was doing that work for me. I
>> only want to know.
>
> Not at all, it's good to want to know. I do hope this clears things up
> for you. Sorry about that.
>
> Here is something you could try. Create a class called
> "MyApplication". From now on, this will be where you're actual logic
> takes place - and the servlet will delegate requests to it.
> So, your doGet() or doPost() method changes to this:
> public void doGet(....)
> {
>  HttpSession session = request.getSession();
>  MyApplication app = session.getAttribute("MyApplication");
>  if (app == null)
>  {
>    app = new MyApplication();
>    new InitialContent().bind("inject", app);
>  }
>  app.handleCartRequest(request, response);
> }
>
> And your MyApplication class will be:
> @LocalClient
> public class MyApplication
> {
>  @EJB MyStatefulCartEjb cart;
>
>  public void handleCartRequest(HttpSerlvetRequest request,
> HttpServletResponse response)
>  {
>    // move your cart handling logic here
>  }
> }
>
> Then remember to add an ejb-jar.xml (with contents = "<ejb-jar/>") to
> your war's META-INF directory as well (for the @LocalClient to work).
>
> Obviously it doesn't need to be exactly like this. The important thing
> is to have a separate class with your @EJB annotations, which itself
> needs to be annotated @LocalClient and the ejb-jar.xml in the WAR's
> META-INF directory. Then the initialContext.bind("inject", obj) call
> will cause the injections to happen. You can read more about it over
> here: http://openejb.apache.org/3.0/local-client-injection.html
>
> So the above gives a unique instance to every client, which itself is
> stored in the session and retrieved with every request. So all your
> servlets would have such code in their doPost/doGet methods, and all
> of them work on a session object instance.
>
> Q
>

Mime
View raw message