What does tomcat do when session expires?
Does it set the session object invalidated?
Does it unlink all references to the session object so that I may not be able to get the expired session object by calling request.getSession(false) ?
I'm using Servlet 2.5 spec. Thanks.
There is no internal session garbage collector thread. Session are removed during getSession() invocations.
If request.getSession() is invoked and the session is no longer valid (its idle time is greater than maxInactiveInterval) then internal expire() method will be called. This method removes session from the Manager and fires appropriate events on the HttpSessionListener.
One can manually invalidate the session using its invalidate() method, which is a wrapper for the expire().
Tomcat (and every other container) will call HttpSession.invalidate()
From the documentation:
Invalidates this session then unbinds any objects bound to it.
Afterwards, request.getSession(false) will return null.
Related:
Best Practice: Releasing and invalidating HTTP sessions
Related
What's the difference between ManagedSessionContext and ThreadLocalSessionContext both has a ThreadLocal in their implementation for maintaining sessions
ThreadLocalSessionContext - It takes care of the hibernate session management activities like :
Creating a session if one doesn't already exist.
Binding the session to the ThreadLocal, so that sessionFactory.getCurrentSession() returns this bound session and unbinds it once the transaction is completed.
Flush and close the session at the end of transaction complete.
ManagedSessionContext - Responsibility of session management activities like above are handled by some external entity (generally some form of interceptor, etc).
In both the cases the session is stored in the ThreadLocal though.
But the call to bind/unbind of the session and especially when to call flush and close on the session are defined via the external entity.
This gives more flexibility, for example, in the case of ThreadLocalSessionContext, the session is closed automatically when the transaction ends and it is not possible to leave the session open for multi-request conversation type of requirements.
In case of ManagedSessionContext, we can implement multi-request conversation (a.k.a session-per-conversation model) the same session needs to be kept open and should be reused across the user requests. So in the first user request we insert/update/delete some entities and in the next request we do some more operations and finally at the end of third interaction we want to commit the data.
Quoting from Managing the current Session section
When a conversation starts, a new Session must be opened and bound with ManagedSessionContext.bind() to serve the first request in the conversation. You also have to set FlushMode.MANUAL on that new Session, because you don’t want any persistence context synchronization to occur behind your back.
All data-access code that now calls sessionFactory.getCurrentSession() receives the Session you bound.
When a request in the conversation completes, you need to call Managed-SessionContext.unbind() and store the now disconnected Session somewhere until the next request in the conversation is made. Or, if this was the last request in the conversation, you need to flush and close the Session.
To represent that pictorially,
Session scoping with ThreadLocalSessionContext
Session scoping implemented for Session-per-conversation using ManagedSessionContext
You can go through the Listing 11.5 of this link for a sample implementation an interceptor that manages the session for session-per-conversation model.
I want to change the session ID without invalidating the session after every request to the server and preserve all the session variable without invalidating it.
As i am using single login to restrict the user from multiple login by changing a flag is_login to true at session creation and to false when session is destroyed with the help of session listener. and after every request i am invalidating the session for generation of new session ID. can i change the session without invalidating it in JAVA.
Since Java EE 7 and Servlet API 3.1 (Tomcat 8) you can use HttpServletRequest.changeSessionId() to achieve such behaviour.
There is also a listener HttpSessionIdListener which will be invoked after each change.
From the docs - http://docs.spring.io/spring-framework/docs/2.0.x/api/org/springframework/orm/hibernate/HibernateTransactionManager.html
HibernateTransactionManager - Binds a Hibernate Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory
OpenSessionInViewFilter - This filter makes Hibernate Sessions available via the current thread, which will be autodetected by transaction managers.
What is the difference between both of them and at what scenarios should they be used ?
OpenSessionInViewFilter
Now when you are using OpenSessionInViewFilter, by default the session's flush mode is set to NEVER. So when you try to save something in your action using hibenate and commit it, it wont be reflected in your database. To solve this you need to flush the session in your action class or extend OpenSessionInViewFilter and override closeSession(Session session, SessionFactory sessionFactory).
Now it is also possible that you are maintaining a single transaction for per request. In your action you edit the attributes of a object and update it using session.update(object). But it is not yet commited as some other processing is remaining. At the same time, some other request is invoking a action which tries to retrieve the object which you were updating. Since the object is not yet commited the other request will get the old object. To solve this you need to begin a transaction before you load object and commit the transaction after you update the object. So that as soon as the object is saved/updated it is commited. With this there can be many transaction in single user request but only one session.
The OpenSessionInView pattern only guarantees that the session is open during one single thread execution.
When the page has been rendered and has been returned to the browser, the session gets closed by the filter.
So subsequent requests (e.g. navigation request) require another new session which will be opened by the OpenSessionInViewFilter. But as the "old" person object is not connected to the "new" session, it is considered as disconnected object which's references cannot be loaded lazily.
Httpsession is per browser.Ideally should we reset the session variables on logout otherwise it will always be available for that Browser even user login again.Is that correct?
You can just invalidate the session by calling HttpSession.invalidate() which will clear all the attributes as well as destroy the session itself.
You don't need to reset all session variables. You just need to call session.invalidate() and servlet framework will take care of the rest.
Is HttpSession in java servlet is created only after
HttpSession s = request.getSession();
?
In my code I didn't write that, but when I use if (request.getSession(false) == null) ..., it doesn't work. Why?
A HttpSession is created when calling request.getSession().
But if you access a JSP by default it will automatically create a session.This behaviour can be disabled by using: <%# page session="false">
Are you using JSP?
Read JavaDocs, it says clearly:
This says, request.getSession()
Returns the current session associated with this request, or if the request does not have a session, creates one.
And the other variant request.getSession(isCreate)
Returns the current HttpSession associated with this request or, if there is no current session and create is true, returns a new session.
If create is false and the request has no valid HttpSession, this method returns null.
To make sure the session is properly maintained, you must call this method before the response is committed. If the container is using cookies to maintain session integrity and is asked to create a new session when the response is committed, an IllegalStateException is thrown.
Update
On a bit research, I have found that Session is not created unless request.getSession() is called somewhere. Since, The servlet container uses this interface to create a session between an HTTP client and an HTTP server. There are good chances that your Servlet container creates the Session for you by default.
refer:
Java Doc HttpSession
Discussion on JavaRaunch: is HttpSession created automatically?
But, to be safer side, use request.getSession() to get session, and use request.getSession(false) only when you need to verify if a session has already been created.
In addition to Nishant's answer note that session can be created implicitly by JSP pages unless you configured them not to create a session with <%# page session = "false" %>.
To make it complete:
session is not created, unless you call request.getSession(), in your servlet, use request.getSession(false) to get existing session without creating new session
if you use JSP page, session is automatically created for you - variable session - unless you specify <%# page session="false" %>
even if your session is created automatically, you can use session.isNew() to find out, if it has been newly created
Try to remove session cookies from browser and make another test. If it does not work then some other component is creating a new session before that call.