Hello
all,
I wanted to
share a hairy issue we discovered recently and see if people had other
solutions, experiences or enhancement ideas. I recently joined a
Servlet project using iBatis and Hibernate. When iBatis statements were
needed, they would attach the current Connection object to the SqlMapClient
object using setUserTransaction and execute insert/update, etc. This worked
great.
One of the
first things I had to do was to test the app in Websphere.
In Tomcat everything worked great, but we found that the app would
hang in WAS after a while. After much pulling of hair, an IBM support
engineer showed us how to dump the JVM state to disk. We found
that after WAS hung, all the Servlet threads were in the wait state inside
the class common.util.Throttle. Apparently, if you simply call
setUserConnection and not openSession, the client *implicitly* creates a
SqlMapSession and stores it in a ThreadLocal variable (and hence its thread-safe
internally). The problem was that nothing would call the close method on this
after it was created! Because of this, each new Thread object would cause a new
SqlMapSession to be created and stored. Once we hit the magic number of 129
distinct threads over time, the app would hang. (The default number of active
sessions is 128.) As it turns out, WAS continuously creates new threads, whereas
Tomcat does so much less often. The Thread creation logic was even more rapid is
WAS 6.0.
My fix was to
instead call openSession(Conn) and then call session.close at the end of the
request to "checkin" the SqlMapSession an decrement the Throttle counter for
SqlMapSessions. I couldn't figure out how to close the implicit session using
the SqlMapClient interface. Perhaps it would be useful to
add a method to SqlMapClient such as "closeImplicitThreadSession" or something
like that?
Thanks
much,
Steve