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.
Related
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.
Is there any relationship between stateful session bean and HTTP session ?
What are the use cases where we would require a stateful session bean and what use cases requires HTTP Session.
Can i expose a stateful session bean as a restful web service ?
HTTP is a stateless protocol Which means that it is actual transport protocol between the server and the client -- is "stateless because it remembers nothing between invocationsNow First read this what is HTTPSession and what is Session Bean (keep in mind that session beans are use to maintain the data state across multiple request so mostly a session bean is a stateful session bean because it holds data across whole session)
HTTP Session
An HttpSession object can hold conversational state across multiple requests from the same client. In other words, it persists for an entire session with a specific client.
We can use it to store everything we get back from the client in all the requests the client makes during a session.
Session Bean from wiki
In the Java Platform, Enterprise Edition specifications, a Session Bean is a type of Enterprise Bean.A session bean performs operations, such as calculations or database access, for the client. Although a session bean can be transactional, it is not recoverable should a system crash occur. Session bean objects either can be stateless or can maintain conversational state across methods and transactions. If a session bean maintains state, then the EJB container manages this state if the object must be removed from memory. However, the session bean object itself must manage its own persistent data.
In Simple words
Session tracking is the process of maintaining information, or state, about Web site visitors as they move from page to page. It requires some work on the part of the Web developer since there's no built-in mechanism for it. The connection from a browser to a Web server occurs over the stateless Hypertext Transfer Protocol (HTTP) AND
SFSB's are designed for managed client state over multiple calls to the same session bean (i.e. a conversation). If you look at JBoss Seam, you will see that there is very heavy use of SFSB's for conversation context.In EJB3, there is no such thing as "stateless is better than stateful session beans". For example, one provides a service like a credit card processor (stateless) and one provides processing for a multi-screen wizard use case (stateful). In My opinion Managing state using HttpSession and stateless session beans is very difficult and problematic.
EDIT: HTTPSession is use to keep the session tracking like A user sessionFor example You want to create a Login , Logout mechanism then You must need the HTTPSession because when The user will start navigation between different pages then this HTTPsession will remember that WHO is asking for the pages otherwise it is not possible(because HTTP is a stateless protocol) Now In session you just set the session of username and password and you are checking on every page that if this session exists then show the pageNow what if , You have to send a lot of information of this user across multiple requests? In this scenario, You will set all this info in a Stateful session bean But now a days , In modern frameworks session as well as information , everything is stored in Session beans because From session bean it is easy to manage them. HTTPSession was used when we were purely on Servlet and somehow JSP technologies
I've got an error that looks like this:
Could not initialize proxy - no Session
I'm working with java, hibernate and spring. This error comes up when trying to generate a PDF document, and I'm following the next steps to generate it on the fly and store in the database.
I sent a request to the app through a POST method. This generates the PDF on the fly and shows to the user.
Just after that request I send another, but through an ajax a request. This will generate the same PDF but will save it in the DB.
The error shows that a query could not be executed due to "could not initialize proxy - no Session" error.
Is there something that am I doing wrong, calling the same methods twice from the same user session? Could it be that the session is closed before both requests have finished?
Hope someone can help me to understand what is happening.
Your problem is that the hibernate Session lives only for one request. It opens in the start of the request and closes at the end. You guessed the answer: Hibernate session is closed before both requests are finished.
Exactly what is happening? Your entity objects live during both requests. How? They are stored in the HTTP session (which is a different thing called session) You don't give much information about the framework you are using, so I can't give you more details, but it is certain that the framework you are using somehow keeps your entities in the HTTP session. This is how the framework makes it easy for you to work with the same objects for more than one requests.
When the processing of the second request starts, the code is trying to access some entity (usually an element of a collection) that is lazily initialized by hibernate. The entity is not attached to a hibernate session, and so hibernate can't initialize the hibernate proxy before reading it. You should open a session and re-attach your entity to it at the beginning of the ajax request processing.
EDIT:
I will try to give a brief explanation of what is happening behind the scene. All java web frameworks have one or more servlets that handle the requests. The servlet handles each request (HttpRequest) by creating a new thread that will finally produce the response (HttpResponse). The method that processes each request is executed inside this thread.
At the beginning of the request processing your application should allocate the resources that it needs for processing (Transaction, Hibernate session etc). At the end of the processing cycle these resources are released (Transaction is committed, hibernate session is closed, JDBC connections are released etc). Lifecycle of these resources could be managed by your framework, or could be done by your code.
In order to support application state in a stateless protocol as HTTP, we have the HttpSession object. We (or the frameworks) put on HttpSession the information that remains relevant between different request cycles of the same client.
During the processing of the first request hibernate reads (lazily) an entity from the database. Due to lazy initialization some parts of this object's structure are hibernate proxy objects. These objects are associated with the hibernate session that created them.
The framework finds the entity from the previous request in the HttpSession object when you try to process the second request. Then it is trying to access a property from a child entity that was lazily initialized and now is a hibernate proxy object. The hibernate proxy object is an imitation of the real object that will ask its hibernate session to fill it with information from the database when someone tries to access one of its properties. This what your hibernate proxy is trying to do. But its session was closed at the end of the previous request processing, so now it doesn't have a hibernate session to use in order to be hydrated (filled with real info).
Note that it is possible that you have already opened a hibernate session at the beginning of the second request, but it isn't aware of the entity that contains the proxy object because this entity was read by a different hibernate sesion. You should re-attach the entity to the new hibernate session.
There is a lot of discussion about how to re-attach a detached entity, but the simplest approach right now is session.update(entity).
Hope it helps.
When a Hibernate session is opened (sessionFactory.openSession()) it might be closed. It is ok. In case it is missed to close an opened session which is used to retrieve data (not to save or update or delete) any where in the application, how to close opened sessions if exists?
(Let's say when a JFrame is closed, if there are opened sessions available, they must be closed. Closing sessions can be done by going through the codes one by one, but I mean here, without checking codes, is there any way to close sessions which are missed to close with some piece of code).
Why dont you close the session when your database operation finished?
I mean, In DAO classes you get opened session perform database operation. And in finally block, Close your session.
You can close session like :
finally {
if(session!=null){
session.close();
}
}
OR
You can get the current session using
Session sess = sessionFactory.getCurrentSession();
And close session on closing event of JFrame.
I get following lines from this link
The main contract here is the creation of Session instances. Usually
an application has a single SessionFactory instance and threads
servicing client requests obtain Session instances from this factory.
The internal state of a SessionFactory is immutable. Once it is
created this internal state is set. This internal state includes all
of the metadata about Object/Relational Mapping.
Implementors must be threadsafe.
And it is our duty to close session when finished the operation or transaction. When we close sessionfactory all resources(connection pools etc) are released properly.
A new corporate policy on Secure Coding was recently put into effect. The initial audit assessment tagged me deficient for:
Session state must be managed such that a session will withstand replay-attacks.
I'm not exactly sure what this statement means or why I am defecient in it. I'm developing a Java Web application and set a session as such:
session.setMaxInactiveInterval(36000);
Session state must be managed such that a session will withstand replay-attacks.
The statement is way too confusing. Rewording it would yield:
The session management framework must protect the application against replay of session IDs.
It is less confusing (hopefully), and continues to carry the same meaning as the former (again, hopefully).
Typically, if one were to implement a home-grown session management framework instead of relying on the one provided by the container for instance, then it is quite possible that the session management feature of the application would be susceptible to a replay attack.
A session replay attack would involve the scenario where the session ID is replayed back in a request, after the session has expired. A well written session management framework would recognize that the provided session ID is not a valid session ID. However, there have been instances where a vulnerable session management framework accepted the now-expired session ID, and recreated the contents of the session. In worser scenarios, the session management framework did not destroy the session at all, on session expiry, resulting in the scenario where a session ID replay resulting in requests being processed.
It must be remembered that even normal users of the application may unintentionally perform session-replay attacks, if they are able to browse to protected pages in the application without logging in. This is an indication of a failure in the authentication and the session management features of the application, for the app should ideally allow users to browse protected pages only after successful authentication, which would yield a token (a session ID) that may be used for a certain duration to access the site without further authentication. If you are using persistent cookies for authentication, you may have unintentionally introduced a hole.
Going by the above, one can protect any application from session replay attacks by:
Ensure that you are using the container provided session management features. From the use of the session.setMaxInactiveInterval I would assume that you are it. But, to be sure, verify if you are creating session IDs using other means, or for that matter, verify if you are using identifiers that are equivalent to session IDs. In simpler words, ensure that your application relies only on the value of the JSESSIONID cookie (or the equivalent as configured in the container) to communicate session IDs to the browser. Also, verify if persistent cookie are in use (refer the above posted scenario).
Invalidate the session after a certain idle period. If you do not invalidate the session, then an attacker has a larger time window to brute force the session ID. From the point of view of session-replay attacks, this is worse since the attacker can replay back a compromised session ID at any point in time, and still get access to a valid user session. You would also want to revisit the duration specified in the session.setMaxInactiveInterval for the value you are using currently is 10 hours. I would consider that to be insecure. Most applications do not require a rolling window of session expiry beyond 30 minutes, with 10 minutes being the value recommended for high-value apps.
Destroy the server-side session and it's contents on expiry. In a servlet container, this is typically done by invoking session.invalidate() in a logout page/link. Ensure that you have provided users with a link to logout from the application in the first place, so that the logout request can be processed to invalidate the session using the before-mentioned API call. If you do not perform this activity, the server-side session object will be destroyed only on session expiry (which will occur after 10 hours of inactivity by the user; now you see why 10 hours is a bad idea).
this is to do with something similar to session hijacking.. where the auth token is held by a hacker to login at a later stage..
in my projects i've added a simple filter which does the following.
every jsp page which is responded would be given an attribute called id (the token is generated using UUID().. the same token is placed in the session..
when a page is posted, the filter (which is configured to filter all requests) checks for the equality of these tokens & proceeds only if the values match.
we also added a timestamp in the session & the database, whenever a page is submitted we check the time stamps in the session with the db.. if the number is within 10 ms then the request passes, else the user is redirected...