Cameron Wallace McKenzie wrote:Create a filter for your struts servlet and start it before and after the struts servlet is inovked. That's the easiest way. It's known as the 'open session in view' pattern, and will work so long as your web and ejb tier are on the save layer.
Hibernate and JPA Open Session In View Pattern
Whatever you do, do NOT do it in your DAOs. That's a rookie mistake.
There is one further point we wish to make about the above servlet. Notice the following line of code near the top of the method doQuery():
Session session = HibernateUtil.getSessionFactory().openSession();
We could have chosen the following alternative syntax - but we would never choose to do so with Tomcat:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Why would we never use this alternative syntax with Tomcat? The difference between openSession() and getCurrentSession() is that the former, each time it is used, provides a brand new Hibernate Session. That is exactly what we want in our servlet. In contrast, getCurrentSession attempts to associate a Hibernate Session with a specific thread (the Singleton-per-Thread pattern), which Hibernate achieves via the use of an embedded (hidden) ThreadLocal. Unfortunately, Tomcat maintains a thread pool, and re-uses a given thread after a particular Http request is finished with it. Hence a brand new Http request can receive a previously used thread, which already happens to have a Hibernate Session associated with it (via the ThreadLocal), and getCurrentSession() may by chance receive an unrelated Hibernate Session when it ought to receive a brand new one. We may have a new Http session, and logically a new thread, but physically be re-using an existing thread. In this way, Tomcat 5.5.x and Hibernate 3.1 can confuse each other.
We choose to bypass the issue entirely by using SessionFactory.openSession, and avoiding the use of SessionFactory.getCurrentSession in a Tomcat environment.
The conflict we described above is readily testable. Setup a Tomcat 5.5 environment allowing only a small number of concurrent threads - say 3 or 4. (You accomplish this via an entry in Tomcat Root\conf\server.xml, namely by setting the maxThreads attribute of the applicable <Connector> element in this file to 3 or 4.) Create a couple of distinct, simplistic business transactions (conversational transactions or long-running transactions) which span Http requests. Attempt to preserve information in a ThreadLocal - any information �'�it doesn�'�t need to have anything to do with Hibernate - and do some tracing/logging in which you display the thread ID. You will see Tomcat thread pooling eventually recycle thread IDs to another business transaction, allowing inappropriate access to the ThreadLocal contents to take place.