I'm sure this is a much asked question, but I have just tried to put a Stateful bean using EJB3.0 into practice and have had some difficulties understanding their point!
I'm writing a simple webapp to allow a user to register their details, redirect to a 'confirmation' page, then if they click 'submit' the details are upload to a database. Then the user can return to the login page and login as an existing user, this is being done via EJB3.0 (obviously) and good ol fashioned JSP/Servlets (none of that Struts or JSF)... Simple!
Initially I used a standard Java bean, from the registration JSP to the Servlet, populated the bean vis 'request.getParameter', then put the bean into the HttpSession.
redirected to the confirmation page, click 'submit' and redirect to the Servlet again.
Got thye bean back from the HttpSession and populated an EntityBean with the detals, which in turn updated the database.
All worked fine!
Then I thought "Surely I should be using an EJB Stateful bean not a standard java bean in the HttpSession?"
So I changed my codce, created a Stateful bean, populated that from the request.getParameter, redirected to the confirmation page, click 'submit' back to the Servlet and....
Lots and errors about NULL values!
Now my understanding was that a stateful bean remained intact for the duration of the session unless 'destroyed', so I was expecting the Servlet to natrually pickup the bean still containing the data provided from the previous JSP, but it seems (I'm guessing) that at the point of redirecting from the confirmation page back to the Servlet I'm creating a NEW Stateful bean, therefore the values for name, email etc are all NULL, rather than collectinig the existing bean.
Which begs my question..
How would I 'grab' my existing Stateful bean? Why would I use a Stateful bean over my original solution of simply stickinng a standrad Java bean into the HttpSession (and using session.removeAttribute when I'm done)?
Unless you are using Seam/JCDI, the EJB "session" and the HTTP session do not know about each other. The solution in your case would be to look-up the stateful session bean when you first need it, store the bean reference in the HTTP session and remove it from the HTTP session when you don't need it, calling the destroy method to also remove the EJB session.
This is a common misconception originating from equating all "sessions" to the HTTP session. It is important to remember that EJB is not web application centric. For example, stateful session beans can be used to maintain server-side sessions for clients such as AWT/Swing, Applets or even CORBA.
Hope it helps,
Independent Consultant — Author, EJB 3 in Action — Expert Group Member, Java EE 6 and EJB 3.1
Kevin P Smith
Joined: Feb 18, 2005
I guess I've completely mis-understood the purpose of a stateful bean then. My understanding was it was 'alive' as long as the session (browser) was open and once created, could be called upon whenever.
Much like the ShoppingCart example you see so often, I presumed, once the bean had been created, you could add/remove/view the bean as often as you like until the browser is closed (session lost) at which point your ShoppingCart is lost.
So if you need to add the bean to the HttpSession in the same manner as a standard java bean... Other than the @Stateful annotation, what is the difference/advantage of a Stateful Bean over a Standard bean?
Joined: Feb 01, 2005
A standard bean would not have EJB container services. For a comprehensive list of such services, feel free to check out the first chapter of EJB 3 in Action. In this particular case, I imagine the most pertinent ones would be transactions, passivation, dependency injection, replication, fail-over, runtime-monitoring, etc. If this particular component does not need these services, there isn't a reason to make it an EJB.
What you think should be possible is done via JSF/Seam(JCDI). EJBs are automatically bound to HTTP specific scopes such as request, session and conversation as well as being accessible by name from web tier components (Facelets or JSPs).