Problem Description
Servlet use of database connections outside of a UserTransaction has
been improved from WebSphere Application Server V4.0 to V5 releases. This
change coincides with the corresponding changes to the Web Container to
support servlet 2.3. Because there is a fundamental difference in
behavior, and because applications migrate from WebSphere Application
Server V4.0 to V5 releases without alteration and continue to function
properly, the Web Container treats 2.2 servlets differently than 2.3
servlets.
Any relational database resources used with servlet 2.2 are required to
use 4.0 data sources, whereas resources used with Servlet 2.3 are required
to use 5.0 data sources (Connection Factories). Therefore, this problem
might manifest only when migrating a servlet from servlet 2.2 to servlet
2.3, which makes use of ConnectionFactories to access resources.
Change of Servlet Support
Prior to WebSphere Application Server V5, a servlet could get a
connection to a data source, use it, and close it without committing or
rolling back the connection local transaction. This caused the connection
to go back to the free pool in a dirty state. Because this type of
programming error can lead to data integrity problems, a change was
implemented in WebSphere Application Server V5.x and Servlet 2.3 support
to fix the problem.
The solution was to enclose the use of the connection within a Local
Transaction Containment (LTC) boundary. For servlets, this boundary is
scoped to the servlet remote method invocation. Within this boundary, any
allocated connection is enlisted with the LTC, similar to a normal
UserTransaction. As long as the use of the connection within the boundary
is complete (meaning either a commit or rollback was issued) when the
boundary ends, no special processing is done. If there is still work
pending on the connection (a commit or rollback was not issued), then by
default a rollback is issued as part of the LTC Cleanup.
Side Effects
- Connections might be tied up much longer than they are actually
used.
When using shareable connections, which is the default, within an LTC, the
sharing scope is the LTC scope. Therefore, even if you commit and close
the connection, it does not return to the free connection pool until the
LTC ends. If your use of the connection or session is short compared to
the length of the servlet method in which it was obtained, the connection
is not free for another thread to use it until the method ends.
- Multiple connections can be obtained and tied up during a single
request, whereas previously only one connection was used at a time:
When 2.3 servlets do servlet includes or forward, each included servlet
starts its own LTC. If servlet A gets a connection, uses it, closes it,
and then calls servlet B, which also gets, uses, and closes a connection,
then until servlet B exits its method, two connections are tied up.
Previously, in servlet 2.2, each connection went immediately back to the
free pool when it closed.
This behavior can cause 3 side affects:
- First, as before, connections can be tied up longer then expected.
- Second, more connections are tied up at any given time.
- Third, if you don’t correspondingly increase the maximum number of
connections for your pool, you will likely deadlock.
Consider the following: maxConnections is set to 10. You have 10 client
requests the servlet A is serving. All ten of the threads have obtained a
connection in servlet A and are now trying to get a connection in servlet
B. Since there are no connections in the free pool and no threads are
going to give up their connections yet, you are deadlocked until a
connectionWaitTimeoutException occurs.
- The preceding side effects numbers 1 and 2 also apply to JMS
Sessions supplied by the WebSphere embedded messaging. This is because JMS
sessions are designed to always be shareable.
As a result, poor utilization of connection resources, the application
might get ConnectionWaitTimeoutExceptions and possible deadlocks. |