I've fixed the problem and I'll be committing it within minutes.
Clinton
Thanks for all the debugging efforts. With this information, it should be a snap to fix.
Cheers,
ClintonOn 10/27/06, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:Yes, if I disable logging all together the error does not occur. I'm guessing that this is something that you have seen before.
From: "Jeff Butler" <[EMAIL PROTECTED]> [mailto:"Jeff Butler" <[EMAIL PROTECTED]>]
Sent: Friday, October 27, 2006 12:40 PM
To: [email protected]
Subject: Re: Statements being closed when they shouldn't beMaybe.Chris - can you verify whether the behavior changes if you disable logging?Also, you can disable caching completely by altering the methods in com.ibatis.sqlmap.engine.scope.SessionScope to always return false.Jeff Butler
On 10/27/06, Clinton Begin <[EMAIL PROTECTED]> wrote:Yeah, let's open a JIRA issue....
JEFF: Could this be the same problem with the prepared statement caching when logging is enabled?
Cheers,
Clinton
On 10/27/06, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:Hi Clinton,I've run into a bit of a snag in the SqlExecutor class, closeStatement method. (Line 501) It seems that this class caches statements within the session object. In the closeStatement method there is an evaluation:if (!session.hasPreparedStatement(ps)) {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
// ignore
}
}
}The problem that I'm seeing is that the PreparedStatement is being closed every time. This is due to the fact that the actual PreparedStatement is wrapped within a PreparedStatementLogProxy object. When the evaluation is made above, session.hasPreparedStatement(ps), the session is asking the preparedStatements HashMap if it contains a value, namely the PreparedStatementLogProxy. When the map iterates through the objects it contains the equals() method is invoked on each object. This is where the problem lies.Invoking equals() causes the invoke method of the PreparedStatementLogProxy to intercept the call. Evaluations are made within this method until the following method is invoked, allowing the underlying equals method on the PreparedStatement to be invoked.return method.invoke(statement, params);
The problem here is that the actual PreparedStatement is being passed in for comparison with an instance of PreparedStatementLogProxy. This always results in evaluating to false. Even if you were to compare an instance of the Proxy with itself, ps.equals(ps), the result will be false. I verified this by setting a breakpoint in the SqlExecutor class and ran this evaluation which resulted in false.
I don't have a solution to this unfortunately. I first thought a simple comparison of the parameter object being an instanceof PreparedStatementLogProxy, but that also returns false, as does PreparedStatementLogProxy.class.isAssignableFrom(params[0].getClass()).
My problem is that the Statements are always being close when they should not be and this is resulting in errors being raised from the JDBC layer because the Statement is being closed more than once. This is because when SqlMapSessionImpl.close() is called the delegate, SqlMapExecutorDelegate pushSession method is called. In here session.reset() is called which closes any PreparedStatements that it contains. Effectively closing the PreparedStatement twice.
Should I open an JIRA on this?
Chris Mathrusse(925) 236-5553
