Using a Stateful Session Bean to track an user's session - session

it's my first question here and I hope that I'm doing it right.
I need to work on a Java EE project, so, before starting, I'm trying to do something simple and see if I can do that.
I'm stuck with Stateful Session Beans.
Here's the question :
How can I use a SFSB to track an user's session?
All the examples that I saw, ended up in "putting" the SFSB into a HttpSession attribute.
But I don't understand why!
I mean, if the bean is STATEFUL, why do I have to use the HttpSession to keep it?
Isn't an EJB Container's task to return the right SFSB to the client?
I've tried with a simple counter bean.
Without using the session, two different browsers have the same counter bean (clicking on "increment" changed the value for both of them).
Using session, I have two different values, each for every browser (clicking on "increment" on Firefox, added one just to Firefox's bean).
But my teacher told that a SFSB keeps the "conversational state with a client", so why it doesn't just work without using a HttpSession ?
If I understood correctly , isn't using HttpSession with a SFSB the same of doing it with a SLSB instead?
I hope that my question(s) is clear and that my English is not that poor!
EDIT :
I'm working on a login system.
Everything goes fine and after completing the login it takes me to a profile page that show user's data.
But reloading the page makes my data disappear!
I've tried adding HttpSession while logging but doing in this way makes the data stay even after the logout!

A Stateful Session Bean (SFSB) has to be combined with the HTTP session in a web environment, since it's a pure business bean that itself knows nothing about the web layer.
Traditionally EJBs even mandatory lived inside their own module (the EJB module), that couldn't even access web artifacts if they wanted to. This is an aspect of layered systems. See Packaging EJB in JavaEE 6 WAR vs EAR for more information about that.
The original clients for Stateful Session Beans were among others Swing desktop applications, that communicated with the remote EJB server via a binary protocol. A Swing application would obtain a connection to a remote Stateful Session Bean via a proxy/stub object. Embedded in this proxy is an ID of some kind that the server can associate with a specific SFSB. By holding on to this proxy object, the Swing client can make repeated calls to it and those will go to the same bean instance. This will thus create a session between the client and the server.
In the case of a web application, when a browser makes an initial request to a Java EE web application it gets a JSESSIONID that the server can associate with a specific HTTPSession instance. By holding on to this JSESSIONID, the browser can provide it with each followup request and this will activate the same http session server-side.
So, those concepts are very similar, but they do not automatically map to each other.
The browser only gets the JSESSIONID and has no knowledge about any SFSB ID. Unlike the Swing application, the browser communicates with web pages, not directly with Java beans.
For mapping the client's request to a specific stateful session bean, the EJB container only cares about the ID provided via the SFSB proxy. It can't see if the call happened to originate from code in the web module and can't/shouldn't really access any HTTP contexts.
The web layer being the client code that accesses the SFSB must 'hold on' to a specific proxy reference. Holding on to something in the web layer typically means storing it in the HTTP session.
There is however a bridge technology called CDI that can make this automatic connection. If you annotate your SFSB with CDI's #SessionScoped and obtain a reference to the SFSB via CDI (e.g. using #Inject), you don't have to manually put your SFSB into the http session. However, behind the scenes CDI will do exactly that anyway.

You need to define the bean with #SessionScoped instead of #RequestScoped (if you are looking for HttpSession equivalent solution)
something like
#SessionScoped
public class SessionInfo implements Serializable{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Have a look at following (explained in detail)
http://www.oracle.com/technetwork/articles/java/cdi-javaee-bien-225152.html

Related

Real World use case of bean scopes

I am learning Spring, I learned about bean scopes - what are the real world use cases for each of them, I am not able to get any help. please help when to use Singleton, Prototype , Request and Session scopes in Spring.
Singleton: It returns a single bean instance per Spring IoC container.This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. If no bean scope is specified in the configuration file, singleton is default. Real world example: connection to a database
Prototype: It returns a new bean instance each time it is requested. It does not store any cache version like singleton. Real world example: declare configured form elements (a textbox configured to validate names, e-mail addresses for example) and get "living" instances of them for every form being created
Request: It returns a single bean instance per HTTP request. Real world example: information that should only be valid on one page like the result of a search or the confirmation of an order. The bean will be valid until the page is reloaded.
Session: It returns a single bean instance per HTTP session (User level session). Real world example: to hold authentication information getting invalidated when the session is closed (by timeout or logout). You can store other user information that you don't want to reload with every request here as well.
GlobalSession: It returns a single bean instance per global HTTP session. It is only valid in the context of a web-aware Spring ApplicationContext (Application level session). It is similar to the Session scope and really only makes sense in the context of portlet-based web applications. The portlet specification defines the notion of a global Session that is shared among all of the various portlets that make up a single portlet web application. Beans defined at the global session scope are bound to the lifetime of the global portlet Session.

Associating a user with a session after authentication in JSF [duplicate]

Suppose, I have a webserver which holds numerous servlets. For information passing among those servlets I am setting session and instance variables.
Now, if 2 or more users send request to this server then what happens to the session variables?
Will they all be common for all the users or they will be different for each user?
If they are different, then how was the server able to differentiate between different users?
One more similar question, if there are n users accessing a particular servlet, then this servlet gets instantiated only the first time the first user accessed it or does it get instantiated for all the users separately?
In other words, what happens to the instance variables?
ServletContext
When the servlet container (like Apache Tomcat) starts up, it will deploy and load all its web applications. When a web application is loaded, the servlet container creates the ServletContext once and keeps it in the server's memory. The web app's web.xml and all of included web-fragment.xml files is parsed, and each <servlet>, <filter> and <listener> found (or each class annotated with #WebServlet, #WebFilter and #WebListener respectively) will be instantiated once and be kept in the server's memory as well, registred via the ServletContext. For each instantiated filter, its init() method is invoked with a new FilterConfig argument which in turn contains the involved ServletContext.
When a Servlet has a <servlet><load-on-startup> or #WebServlet(loadOnStartup) value greater than 0, then its init() method is also invoked during startup with a new ServletConfig argument which in turn contains the involved ServletContext. Those servlets are initialized in the same order specified by that value (1 is 1st, 2 is 2nd, etc). If the same value is specified for more than one servlet, then each of those servlets is loaded in the same order as they appear in the web.xml, web-fragment.xml, or #WebServlet classloading. In the event the "load-on-startup" value is absent, the init() method will be invoked whenever the HTTP request hits that servlet for the very first time.
When the servlet container is finished with all of the above described initialization steps, then the ServletContextListener#contextInitialized() will be invoked with a ServletContextEvent argument which in turn contains the involved ServletContext. This will allow the developer the opportunity to programmatically register yet another Servlet, Filter or Listener.
When the servlet container shuts down, it unloads all web applications, invokes the destroy() method of all its initialized servlets and filters, and all Servlet, Filter and Listener instances registered via the ServletContext are trashed. Finally the ServletContextListener#contextDestroyed() will be invoked and the ServletContext itself will be trashed.
HttpServletRequest and HttpServletResponse
The servlet container is attached to a web server that listens for HTTP requests on a certain port number (port 8080 is usually used during development and port 80 in production). When a client (e.g. user with a web browser, or programmatically using URLConnection) sends an HTTP request, the servlet container creates new HttpServletRequest and HttpServletResponse objects and passes them through any defined Filter in the chain and, eventually, the Servlet instance.
In the case of filters, the doFilter() method is invoked. When the servlet container's code calls chain.doFilter(request, response), the request and response continue on to the next filter, or hit the servlet if there are no remaining filters.
In the case of servlets, the service() method is invoked. By default, this method determines which one of the doXxx() methods to invoke based off of request.getMethod(). If the determined method is absent from the servlet, then an HTTP 405 error is returned in the response.
The request object provides access to all of the information about the HTTP request, such as its URL, headers, query string and body. The response object provides the ability to control and send the HTTP response the way you want by, for instance, allowing you to set the headers and the body (usually with generated HTML content from a JSP file). When the HTTP response is committed and finished, both the request and response objects are recycled and made available for reuse.
HttpSession
When a client visits the webapp for the first time and/or the HttpSession is obtained for the first time via request.getSession(), the servlet container creates a new HttpSession object, generates a long and unique ID (which you can get by session.getId()), and stores it in the server's memory. The servlet container also sets a Cookie in the Set-Cookie header of the HTTP response with JSESSIONID as its name and the unique session ID as its value.
As per the HTTP cookie specification (a contract any decent web browser and web server must adhere to), the client (the web browser) is required to send this cookie back in subsequent requests in the Cookie header for as long as the cookie is valid (i.e. the unique ID must refer to an unexpired session and the domain and path are correct). Using your browser's built-in HTTP traffic monitor, you can verify that the cookie is valid (press F12 in Chrome / Firefox 23+ / IE9+, and check the Net/Network tab). The servlet container will check the Cookie header of every incoming HTTP request for the presence of the cookie with the name JSESSIONID and use its value (the session ID) to get the associated HttpSession from server's memory.
The HttpSession stays alive until it has been idle (i.e. not used in a request) for more than the timeout value specified in <session-timeout>, a setting in web.xml. The timeout value defaults to 30 minutes. So, when the client doesn't visit the web app for longer than the time specified, the servlet container trashes the session. Every subsequent request, even with the cookie specified, will not have access to the same session anymore; the servlet container will create a new session.
On the client side, the session cookie stays alive for as long as the browser instance is running. So, if the client closes the browser instance (all tabs/windows), then the session is trashed on the client's side. In a new browser instance, the cookie associated with the session wouldn't exist, so it would no longer be sent. This causes an entirely new HttpSession to be created, with an entirely new session cookie being used.
In a nutshell
The ServletContext lives for as long as the web app lives. It is shared among all requests in all sessions.
The HttpSession lives for as long as the client is interacting with the web app with the same browser instance, and the session hasn't timed out at the server side. It is shared among all requests in the same session.
The HttpServletRequest and HttpServletResponse live from the time the servlet receives an HTTP request from the client, until the complete response (the web page) has arrived. It is not shared elsewhere.
All Servlet, Filter and Listener instances live as long as the web app lives. They are shared among all requests in all sessions.
Any attribute that is defined in ServletContext, HttpServletRequest and HttpSession will live as long as the object in question lives. The object itself represents the "scope" in bean management frameworks such as JSF, CDI, Spring, etc. Those frameworks store their scoped beans as an attribute of its closest matching scope.
Thread Safety
That said, your major concern is possibly thread safety. You should now know that servlets and filters are shared among all requests. That's the nice thing about Java, it's multithreaded and different threads (read: HTTP requests) can make use of the same instance. It would otherwise be too expensive to recreate, init() and destroy() them for every single request.
You should also realize that you should never assign any request or session scoped data as an instance variable of a servlet or filter. It will be shared among all other requests in other sessions. That's not thread-safe! The below example illustrates this:
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
See also:
What is the difference between JSF, Servlet and JSP?
Best option for Session management in Java
Difference between / and /* in servlet mapping url pattern
doGet and doPost in Servlets
Servlet seems to handle multiple concurrent browser requests synchronously
Why Servlets are not thread Safe?
Sessions
In short: the web server issues a unique identifier to each visitor on his first visit. The visitor must bring back that ID for him to be recognised next time around. This identifier also allows the server to properly segregate objects owned by one session against that of another.
Servlet Instantiation
If load-on-startup is false:
If load-on-startup is true:
Once he's on the service mode and on the groove, the same servlet will work on the requests from all other clients.
Why isn't it a good idea to have one instance per client? Think about this: Will you hire one pizza guy for every order that came? Do that and you'd be out of business in no time.
It comes with a small risk though. Remember: this single guy holds all the order information in his pocket: so if you're not cautious about thread safety on servlets, he may end up giving the wrong order to a certain client.
Session in Java servlets is the same as session in other languages such as PHP. It is unique to the user. The server can keep track of it in different ways such as cookies, url rewriting etc. This Java doc article explains it in the context of Java servlets and indicates that exactly how session is maintained is an implementation detail left to the designers of the server. The specification only stipulates that it must be maintained as unique to a user across multiple connections to the server. Check out this article from Oracle for more information about both of your questions.
Edit There is an excellent tutorial here on how to work with session inside of servlets. And here is a chapter from Sun about Java Servlets, what they are and how to use them. Between those two articles, you should be able to answer all of your questions.
When the servlet container (like Apache Tomcat) starts up, it will read from the web.xml file (only one per application) if anything goes wrong or shows up an error at container side console, otherwise, it will deploy and load all web applications by using web.xml (so named it as deployment descriptor).
During instantiation phase of the servlet, servlet instance is ready but it cannot serve the client request because it is missing with two pieces of information:
1: context information
2: initial configuration information
Servlet engine creates servletConfig interface object encapsulating the above missing information into it
servlet engine calls init() of the servlet by supplying servletConfig object references as an argument. Once init() is completely executed servlet is ready to serve the client request.
Q) In the lifetime of servlet how many times instantiation and initialization happens ??
A)only once (for every client request a new thread is created)
only one instance of the servlet serves any number of the client request ie, after serving one client request server does not die. It waits for other client requests ie what CGI (for every client request a new process is created) limitation is overcome with the servlet (internally servlet engine creates the thread).
Q)How session concept works?
A)whenever getSession() is called on HttpServletRequest object
Step 1: request object is evaluated for incoming session ID.
Step 2: if ID not available a brand new HttpSession object is created and its corresponding session ID is generated (ie of HashTable) session ID is stored into httpservlet response object and the reference of HttpSession object is returned to the servlet (doGet/doPost).
Step 3: if ID available brand new session object is not created session ID is picked up from the request object search is made in the collection of sessions by using session ID as the key.
Once the search is successful session ID is stored into HttpServletResponse and the existing session object references are returned to the doGet() or doPost() of UserDefineservlet.
Note:
1)when control leaves from servlet code to client don't forget that session object is being held by servlet container ie, the servlet engine
2)multithreading is left to servlet developers people for implementing ie., handle the multiple requests of client nothing to bother about multithread code
Inshort form:
A servlet is created when the application starts (it is deployed on the servlet container) or when it is first accessed (depending on the load-on-startup setting)
when the servlet is instantiated, the init() method of the servlet is called
then the servlet (its one and only instance) handles all requests (its service() method being called by multiple threads). That's why it is not advisable to have any synchronization in it, and you should avoid instance variables of the servlet
when the application is undeployed (the servlet container stops), the destroy() method is called.
Sessions - what Chris Thompson said.
Instantiation - a servlet is instantiated when the container receives the first request mapped to the servlet (unless the servlet is configured to load on startup with the <load-on-startup> element in web.xml). The same instance is used to serve subsequent requests.
The Servlet Specification JSR-315 clearly defines the web container behavior in the service (and doGet, doPost, doPut etc.) methods (2.3.3.1 Multithreading Issues, Page 9):
A servlet container may send concurrent requests through the service
method of the servlet. To handle the requests, the Servlet Developer
must make adequate provisions for concurrent processing with multiple
threads in the service method.
Although it is not recommended, an alternative for the Developer is to
implement the SingleThreadModel interface which requires the container
to guarantee that there is only one request thread at a time in the
service method. A servlet container may satisfy this requirement by
serializing requests on a servlet, or by maintaining a pool of servlet
instances. If the servlet is part of a Web application that has been
marked as distributable, the container may maintain a pool of servlet
instances in each JVM that the application is distributed across.
For servlets not implementing the SingleThreadModel interface, if the
service method (or methods such as doGet or doPost which are
dispatched to the service method of the HttpServlet abstract class)
has been defined with the synchronized keyword, the servlet container
cannot use the instance pool approach, but must serialize requests
through it. It is strongly recommended that Developers not synchronize
the service method (or methods dispatched to it) in these
circumstances because of detrimental effects on performance
No. Servlets are not Thread safe
This is allows accessing more than one threads at a time
if u want to make it Servlet as Thread safe ., U can go for
Implement SingleThreadInterface(i)
which is a blank Interface there is no
methods
or we can go for synchronize methods
we can make whole service method as synchronized by using synchronized
keyword in front of method
Example::
public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException
or we can the put block of the code in the Synchronized block
Example::
Synchronized(Object)
{
----Instructions-----
}
I feel that Synchronized block is better than making the whole method
Synchronized
As is clear from above explanations, by implementing the SingleThreadModel, a servlet can be assured thread-safety by the servlet container. The container implementation can do this in 2 ways:
1) Serializing requests (queuing) to a single instance - this is similar to a servlet NOT implementing SingleThreadModel BUT synchronizing the service/ doXXX methods; OR
2) Creating a pool of instances - which's a better option and a trade-off between the boot-up/initialization effort/time of the servlet as against the restrictive parameters (memory/ CPU time) of the environment hosting the servlet.

Struts 2 tomcat request/session contamination

I am using Struts 2 v 2.3.16.3 with tomcat 6.
A user will click on an action which finds an object by id and the page displays it. I have encountered a sporadic bug where the user will all of a sudden get the id of another lookup from another user on another machine. So effectively they are both calling the same action but passing different id to the request, but both end up viewing the same id.
This is obviously disastrous, and the data is totally corrupted as both users think they are editing a different record. Any ideas how make sure session/request activity is kept secure to each session?
I am also using spring and am using the #Transactional annotation in my Service layer, which returns the objects from the DAO. Is there something I need to do with this annotation to make it secure for each session ?
I am using org.springframework.orm.hibernate3.HibernateTransactionManager
Classic Thread-UnSafe problem.
Since you nominated Spring, my first guess is that you have not specified the right scope for your action beans in Spring xml configuration.
Be sure you are using scope="prototype" because otherwise the default scope of Spring is Singleton, and you don't want a single(ton) instance of an Action, that would not be ThreadLocal (and hence ThreadSafe) anymore.
If it is not that, it could be something on an Interceptor (that, differently from an action, is not Thread Safe), or you are using something static (in your Business / DAO layer, or in the Action itself) that should be not.

Stateless session bean maintaining state

I deployed a web application on the localhost GlassFish server. This application takes order information from user and stores it in a List type variable in a Stateless Session Bean.The list object is created in the constructor.
I open the order page and add multiple orders in it. When I open the show orders page in different tabs and different browsers, it displays all the order information bean correctly, as though the state is maintained in a Stateless Bean!
I think this behavior is wrong as each browser/tab should create different session with the server and new order information should be shown for each browser/tab. How can this behavior be explained?
Your use case is precisely what a stateful session bean is for, if you want your List object to be maintained across method invocations, and if you want each session to be assigned its own bean.
Stateless session beans are pooled and made available to any session. But your instance fields are not guaranteed to be cleared, so you can't depend on them being cleared. The behavior that you are seeing is not unexpected. Even if you were successful in creating separate sessions in multiple tabs, those sessions could very well have been (and apparently were) assigned the same session bean. That's because the associated method invocations occurred at different points in time. Now if the associated method invocations occurred simultaneously instead, then the platform would have assigned a different stateless bean to each invocation (session). In that case, you'd see different behavior.
See also;
conversational state of session beans
and
Stateless and Stateful Enterprise Java Beans
Never let what you can't do get in the way of what you can do.
Problem: Stateful Session Bean was not maintaining separate state per client. In the example I tried, I input orders from the JSP page, which were stored in a List in a Stateful Session Bean. When I called the same URL from a different browser (i.e. a different session), the list of orders input in the previous session were visible. The same EJB was getting referenced in both sessions. (Verified by sysouts)
It's like saying, the shopping cart of some other user was directly visible to me as if they were my orders!!
Solution: Used an HttpSessionListener and got the dependency of the Stateful EJB through JNDI, in sessionCreated(HttpSessionEvent se) method. Next, added the stateful EJB in an HttpSession and accessed the EJB through session in servlet.
Suggestions for using JNDI, instead of DI, for Stateful Session Bean and Adding EJB to HttpSession are given in the answer above. Don't know if it is the proper way to go, but it works!!

How to move data from Session's attributes to application context in a spring web application?

There is a web application that I am working on currently and it has to be extended to expose web services. In the current project - when the application context is loaded at startup - database queries are made and static data like role names is set as variables at the session level.
Like this:
private void loadRoles(ServletContext acontext) {
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(acontext);
IMyDataService myDataService = (IMyDataService ) appContext.getBean("myDataService");
List<Roles> rolesList = myDataService.listRoles();
acontext.setAttribute(MyAppConstants.ROLES, rolesList);
}
This value stored in the session attribute is used as follows in other places of the application:
public boolean checkAccess(HttpServletRequest arequest) {
HttpSession session = arequest.getSession();
List<Role> roles = (List<Roles>)session.getServletContext().getAttribute(MyAppConstants.ROLES);
.....
}
If I want to enhance the application to expose web services - my understanding is that I will no longer be having a ServletSession or HttpServletRequest available with me. So I want to move this static data from session variables to another place so that they are available in the context.
Is there a way in which I can achieve this?
I tried getting rid of storing data in session variables all together, but could not do that because there are just too many references.
Is there a better approach?
There is a difference between the session and the servlet context. I think that you are confuse because you are using the session object to get the servlet context. Your data is clearly set in the servlet context in this example. Even if you are using web services, you will have a servlet context provided by the servlet container.
Now I don't know which technologies you are using, but there's many other ways to make static data available to all your web services. For example, using a cache mechanism might be a better solution for data that is stored in the database...
More info :
A Servlet Session is a very different thing from a Servlet Context.
An HttpSession is a mechanism used to simulate and maintain a
continuous user Session between a Web Browser and Web Application,
largely managed by the Servlet Container. The HTTP protocol is
stateless, it is essentially a request-response scheme, so Servlet
Sessions are maintained by passing a unique HTTP cookie value for each
request, or by dynamically including an identifier in Servlet URLs,
known as URL-rewriting.
A ServletContext object represents the overall configuration of the
Servlet Container and has several methods to get configuration
parameters, exchange data amongst Servlets, forward requests and load
resources. The Servlet Context is usually obtained indirectly through
the ServletConfig object, passed to a Servlet's init(ServletConfig)
method, or from the Servlet getServletConfig() method.
Javadoc definition for ServletContext :
Defines a set of methods that a servlet uses to communicate with its
servlet container, for example, to get the MIME type of a file,
dispatch requests, or write to a log file.
There is one context per "web application" per Java Virtual Machine.
(A "web application" is a collection of servlets and content installed
under a specific subset of the server's URL namespace such as /catalog
and possibly installed via a .war file.)
EDIT
To get the ServletContext object in a Spring application, use the #Autowired annotation. Note that the object should be managed by the Spring container, it will be the case if you are using controllers for you REST services.
#Autowired
ServletContext servletContext;
Here an example :
#Controller
#RequestMapping("/foo")
public class RESTController {
#Autowired
ServletContext servletContext;
#ResponseBody
#RequestMapping(value="/bar", method = RequestMethod.GET)
public List<Roles> getRoles() {
return servletContext.getAttribute(MyAppConstants.ROLES);
}
}
Refactor your code by removing MyAppConstants.ROLES and by relying on Spring DI. There are much better ways to store static data than putting them in HTTP session or servlet context... (ex. create a list bean, use cache abstraction, use FactoryBean etc.).

Resources