|
| Apache Geronimo > Discussion Forums | User List | Dev List | Wiki | Issue Tracker |
|
View:
New views
9 Messages
—
Rating Filter:
Alert me
|
|
|
Stateful session bean has no stateHello again!
I made a stateful sessiob bean and it's working the same way my stateless beans do: they forget their state. Here's my code: @Stateful public class CartBean implements CartLocal { private Integer number = new Integer(0); public void setNumber(Integer number) { this.number = number; } public Integer getNumber() { return this.number; } @Override public Integer getNumberService() { this.number += 10; return this.number; } } My jsp uses CartLocal interface wich only shows "getNumberService()" method. When requesting the jsp with my web browser it always shows ten. when refreshing the page it should show 20, but once again shows 10. What am I doing wrong? Thank you very much! |
|
|
Re: Stateful session bean has no stateAre you storing your session bean instance in the servlet/JSP session context?
Quintin Beukes On Mon, Oct 12, 2009 at 8:48 PM, Antonio Fornié <sitaronocturnal@...> wrote: > > Hello again! > > I made a stateful sessiob bean and it's working the same way my stateless > beans do: they forget their state. Here's my code: > > @Stateful > public class CartBean implements CartLocal { > > private Integer number = new Integer(0); > > public void setNumber(Integer number) { > this.number = number; > } > > public Integer getNumber() { > return this.number; > } > > @Override > public Integer getNumberService() { > this.number += 10; > return this.productNumber; > } > > } > > My jsp uses CartLocal interface wich only shows "getNumberService()" method. > When requesting the jsp with my web browser it always shows ten. when > refreshing the page it should show 20, but once again shows 10. What am I > doing wrong? > > Thank you very much! > -- > View this message in context: http://www.nabble.com/Stateful-session-bean-has-no-state-tp25861132s134p25861132.html > Sent from the Apache Geronimo - Users mailing list archive at Nabble.com. > > |
|
|
Re: Stateful session bean has no stateJust to clarify.
An EJB is referenced through a "proxy". When you get the instance to the session bean, you actually obtain a reference to a proxy class which implements the EJB's business interface (the one annotated with @Local or @Remote). So any methods you invoke are done so on the proxy, and the proxy does the work of communicating with the actual EJB instance. So, with a Stateless bean, every invocation on the obtained instance (ie. the proxy), can happen on a different physical instance. So it's at the whim of the implementation/provider, and therefore you can never rely on any member values being the same in between method calls. Literally, this code could work with 2 separate physical instances, or it could work with one - you can never be sure - it's a stateless EJB. public void someEjbInvocation(); { MyStatelessEjbLocal myEjb = initialContext.lookup("MyStatelessEjbLocal"); myEjb.callMethod1(); myEjb.callMethod2(); } With a Stateful bean, when you get a reference via the InitialContext or injection, it will still be via a proxy as above, but this time it will always be to the same physical bean instance. So any method invocations like in the example above will be guaranteed to happen on the same object instance, and therefore you can store values in it's member fields and know that it will be there next time. Everytime you do a lookup to the Stateful bean via the InitialContext, you will get a reference to a proxy pointing to a new/fresh EJB instance of that bean. So the following will be 2 separate instances of the same stateful EJB: public void someEjbInvocation(); { MyStatefulEjbLocal myEjbInstance1 = initialContext.lookup("MyStatefulEjbLocal"); myEjbInstance1.callMethod1(); MyStatefulEjbLocal myEjbInstance2 = initialContext.lookup("MyStatefulEjbLocal"); myEjbInstance2.callMethod1(); } So if you want to do your invocations on the same instance, ie. keep the state, you need to be sure that you keep the reference somewhere, like in the session object (HttpSession) of the servlet/JSP. Otherwise you will keep getting a new instance and you're state won't be saved. Just a tip: Further, when you're done with the session bean (like when the client logs out), call it's remove method (any empty method on the bean annotated with @javax.ejb.Remove - it must be exposed via the interfaces as well). This will cause the bean to be garbage collected. The alternative is to have it timeout, but in a very busy system with long timeouts this could potentially waste a lot of resources. I hope this solves your problem. Quintin Beukes On Mon, Oct 12, 2009 at 9:50 PM, Quintin Beukes <quintin@...> wrote: > Are you storing your session bean instance in the servlet/JSP session context? > > Quintin Beukes > > > > On Mon, Oct 12, 2009 at 8:48 PM, Antonio Fornié > <sitaronocturnal@...> wrote: >> >> Hello again! >> >> I made a stateful sessiob bean and it's working the same way my stateless >> beans do: they forget their state. Here's my code: >> >> @Stateful >> public class CartBean implements CartLocal { >> >> private Integer number = new Integer(0); >> >> public void setNumber(Integer number) { >> this.number = number; >> } >> >> public Integer getNumber() { >> return this.number; >> } >> >> @Override >> public Integer getNumberService() { >> this.number += 10; >> return this.productNumber; >> } >> >> } >> >> My jsp uses CartLocal interface wich only shows "getNumberService()" method. >> When requesting the jsp with my web browser it always shows ten. when >> refreshing the page it should show 20, but once again shows 10. What am I >> doing wrong? >> >> Thank you very much! >> -- >> View this message in context: http://www.nabble.com/Stateful-session-bean-has-no-state-tp25861132s134p25861132.html >> Sent from the Apache Geronimo - Users mailing list archive at Nabble.com. >> >> > |
|
|
Re: Stateful session bean has no stateThank 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).
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 and store it in session, well, 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. Of course, if the only advantage was to have an object (the implementation) knowing only the interface, I can use a Factory Method Pattern or many other solutions. 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. In fact I'm sure it won't be necessary to do all that job, and it suffices to have a servlet property annotated, but if so why my two browsers got the same SFSB? Thank you very much. |
|
|
Re: Stateful session bean has no stateNo 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 |
|
|
Re: Stateful session bean has no stateHey,
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@...> 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 > |
|
|
Re: Stateful session bean has no stateYes, each Servlet it's created only once. I think that's true for ALL Servlet Containers, in fact is part of the specs, that's why so much has been written about about thread safe Servlets, against and in favor (do you remember there was a time when everybody tried to use thread safe servlets, and some years later everybody forgot about it just to remove critical code from the servlets in order not to lose performance?).
I though that it could be like you say, having to manage myself the one-EFSB-per-session matters, but I didn't want to believe. I knew that using EJB had those benefits (transactional, distributed...) and that EJB prior to version 3.0 was rather complex (I've read the famous Rod Johnson book about development without EJB) and that's why I've been working with Spring for years... Now that I was trying to get involved in EJB 3 I find that EJB 3.0 is much better, but in the case of Stateful Beans it's been a surprise: I don't understand why to use the @EJB annotation for a SFSB. It's only valid for the first user session, right? I though that being EJB 3 a response to Spring, managing objects per session would be a little easier. Anyway I will use your recommendation and have a class to make sure I always have one and only one SFSB per session. I didn't know about @LocalClient annotation. Thank you very much for your detailed answer. By the way, and only to learn, what would you answer to people who think EJB 3 is still far more complex than other alternatives. Thank you very much! |
|
|
Re: Stateful session bean has no state> Thank you very much for your detailed answer. By the way, and only to learn,
> what would you answer to people who think EJB 3 is still far more complex > than other alternatives. To tell you the truth, I wouldn't know what to say. The only other alternative I know of is Spring, and it's a completely different approach.Re. complexity I would say Spring is more complex. With flexibility I would say Spring is far more flexible. But more than this the person stating it's more complex needs to be more specific, because I can't see how it's complex at all. > Thank you very much! Glad to be of service. |
|
|
Re: Stateful session bean has no stateOn Oct 13, 2009, at 11:40 AM, Antonio Fornié wrote: > > Thank you very much! +1. Thanks Quintin! --kevan |
| Free embeddable forum powered by Nabble | Forum Help |
