The ZK framework uses a multithreaded event model, i.e. it spawns seperate, non-serlvet container threads to handle events from the UI. This has some interesting implications for the use of Hibernate, where the Session is not thread safe.
The incompatiblity between Hibernate’s single thread session management and ZK’s mutil-thread event model has been a serious issue. It causes Hibernate’s LazyInitializationExceptions in “Open Session In View” pattern and generates other surprises from time to time. Though Thomas Muller (Oberinspector) has proposed a new set of Hibernate utilities (see How-Tos) trying to solve these issues. However, it still got some limitations. The major issue is that developers are forced to give up the preferred factory.getCurrentSession() pattern to these new APIs and have no way to incorporate ZK into existing applications seamlessly.
[...]
Besides the servlet thread created by the servlet engine for each regular http request and/or Ajax XMLHttpRequest, ZK will create a new event thread for each handled event. This is where the issue comes from. In such multi-threads environment, Hibernate might not access to the expected “current session” that was created and bound to the ThreadLocal variable in privious thread and would create an “unwanted” new session and bound to the ThreadLocal variable in this thread (because it thought getCurrentSession() was first called).
The original reason for the ThreadLocal session pattern is that a Hibernate session is not thread safe. So if you have lazy loading turned on and have two threads traversing an object graph, you could be in a world of hurt. Remember, the Hibernate session isn’t just a “connection to the database,” but a cache as well.
The article describes an approach to working around these issues, based on an article by Thomas Muller. The article sort of speaks for itself:
To solve all above limitations in one shot, we have written some ZK listeners which intercepts the ExecutionInit, EventThreadInit, and EventThreadResume. The HibernateSessionContextListener in zkplus.jar is the example that we want to dig in this smalltalk. Basically, it copys the servlet thread bound sessionMap (the map that is used to hold the current Hibernate session) to event thread’s ThreadLocal variable whenever a new event thread is initiated or resumed. The new way is much more straitforward and works seamlessly with existing Hibernate applications as long as it follows Hibernate’s factory.getCurrentSession() pattern. All you have to do is simply put the following lines inside the application’s WEB-INF/zk.xml and it is done.
Yeah, I’m confused too. I’ll have to read some more code. If you want to have thread safe Hibernate sessions in a vanilla servlet container, just use Spring. No need to go through all of these painful gyrations. Aside from the ThreadLocal approach, Spring has a number of other ways of managing the Hibernate session. The ZK folks could have tied that into their Small Talk about Spring and ZK.
I do wonder if this spawning of non-servlet container threads is really necessary. From reading the documentation (Section 5), it’s not clear to me what they provide over regular servlet threads. If they are synchronized, i.e. threadsafe with a regular servlet request, I’m not sure why they are necessary at all. I’ll have to ask Tom Yeh for a clearer explanation.
