This is an automated email from the ASF dual-hosted git repository. lihan pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new 5e39cd81d3 Fix the inconsistent state of ConnectionState 5e39cd81d3 is described below commit 5e39cd81d3fa0d084a4dec41b187967999ebc639 Author: lihan <li...@apache.org> AuthorDate: Thu Aug 3 10:11:36 2023 +0800 Fix the inconsistent state of ConnectionState (cherry picked from commit 77dcb33743d394e158aae1d538f94aaed1edd6ae) --- .../jdbc/pool/interceptor/ConnectionState.java | 27 +++++--- .../tomcat/jdbc/test/TestConnectionState.java | 72 ++++++++++++++++++++++ webapps/docs/changelog.xml | 9 +++ 3 files changed, 101 insertions(+), 7 deletions(-) diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java index dac5463c8f..fdc64fba3b 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java @@ -155,14 +155,27 @@ public class ConnectionState extends JdbcInterceptor { } } - result = super.invoke(proxy, method, args); - if (read || write) { - switch (index) { - case 0:{autoCommit = (Boolean) (read?result:args[0]); break;} - case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;} - case 2:{readOnly = (Boolean)(read?result:args[0]); break;} - case 3:{catalog = (String)(read?result:args[0]); break;} + try { + result = super.invoke(proxy, method, args); + if (read || write) { + switch (index) { + case 0:{autoCommit = (Boolean) (read?result:args[0]); break;} + case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;} + case 2:{readOnly = (Boolean)(read?result:args[0]); break;} + case 3:{catalog = (String)(read?result:args[0]); break;} + } + } + } catch (Throwable e) { + if (write) { + log.warn("Reset state to null as an exception occurred while calling method[" + name + "].", e); + switch (index) { + case 0:{autoCommit = null; break;} + case 1:{transactionIsolation = null; break;} + case 2:{readOnly = null; break;} + case 3:{catalog = null; break;} + } } + throw e; } return result; } diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java index daa8ea4967..73e1044b9f 100644 --- a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java +++ b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java @@ -17,13 +17,19 @@ package org.apache.tomcat.jdbc.test; import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import org.apache.tomcat.jdbc.test.driver.Driver; import org.junit.Assert; import org.junit.Test; import org.apache.tomcat.jdbc.pool.DataSourceProxy; import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; +import javax.sql.PooledConnection; + public class TestConnectionState extends DefaultTestCase { @Test @@ -79,4 +85,70 @@ public class TestConnectionState extends DefaultTestCase { c1 = d1.getConnection(); Assert.assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema"); } + + @Test + public void testWithException() throws SQLException { + DriverManager.registerDriver(new MockErrorDriver()); + // use our mock driver + datasource.setDriverClassName(MockErrorDriver.class.getName()); + datasource.setUrl(MockErrorDriver.url); + datasource.setDefaultAutoCommit(true); + datasource.setMinIdle(1); + datasource.setMaxIdle(1); + datasource.setMaxActive(1); + datasource.setJdbcInterceptors(ConnectionState.class.getName()); + Connection connection = datasource.getConnection(); + PooledConnection pc = (PooledConnection) connection; + MockErrorConnection c1 = (MockErrorConnection) pc.getConnection(); + Assert.assertTrue("Auto commit should be true", c1.getAutoCommit()); + connection.close(); + c1.setThrowError(true); + Connection c2 = datasource.getConnection(); + try { + c2.setAutoCommit(false); + } catch (SQLException e) { + // ignore + } + Assert.assertFalse("Auto commit should be false", c2.getAutoCommit()); + c2.close(); + DriverManager.deregisterDriver(new MockErrorDriver()); + } + public static class MockErrorDriver extends Driver { + @Override + public Connection connect(String url, Properties info) throws SQLException { + return new MockErrorConnection(info); + } + } + + public static class MockErrorConnection extends org.apache.tomcat.jdbc.test.driver.Connection { + private boolean throwError = false; + private boolean autoCommit = false; + public void setThrowError(boolean throwError) { + this.throwError = throwError; + } + + public MockErrorConnection(Properties info) { + super(info); + } + + @Override + public boolean getAutoCommit() throws SQLException { + return autoCommit; + } + + @Override + public void close() throws SQLException { + super.close(); + throwError = true; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + this.autoCommit = autoCommit; + if (throwError) { + throw new SQLException("Mock error"); + } + } + + } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 9772d22b19..5aaab8f3d5 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -162,6 +162,15 @@ </fix> </changelog> </subsection> + <subsection name="jdbc-pool"> + <changelog> + <fix> + Fix the <code>ConnectionState</code> state will be inconsistent with actual + state on the connection when an exception occurs while writing. Pull request + <pr>643</pr> provided by Wenjun Xiao. (lihan) + </fix> + </changelog> + </subsection> <subsection name="Other"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org