diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java index 99a9face827b..4d1aabf08bff 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java @@ -911,6 +911,12 @@ protected boolean terminateTransaction(PooledConnection con) { protected boolean shouldClose(PooledConnection con, int action) { if (con.getConnectionVersion() < getPoolVersion()) return true; if (con.isDiscarded()) return true; + try { + if (con.isClosed()) return true; + } catch (SQLException e) { + log.warn("Unable to check if connection is closed", e); + return true; + } if (isClosed()) return true; if (!con.validate(action)) return true; if (!terminateTransaction(con)) return true; diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java index a557b82e2c7e..61955d5d8246 100644 --- a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java +++ b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java @@ -19,6 +19,7 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.Savepoint; @@ -141,6 +142,29 @@ public void testOnConnectValidationWithValidationSQLDoesNotOccurWhenDisabled() t Assert.assertFalse("No transaction must be running after connection is obtained", getMock(cxn).isRunningTransaction()); } + @Test + public void returnClosedConnection() throws SQLException { + datasource.setDriverClassName("org.h2.Driver"); + datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE"); + Assert.assertFalse(datasource.getPoolProperties().isTestOnBorrow()); + Assert.assertFalse(datasource.getPoolProperties().isTestOnReturn()); + Assert.assertFalse(datasource.getPoolProperties().isTestWhileIdle()); + try (Connection connection = datasource.getConnection()) { + // this gets the real connection and closes it to simulate close by driver because of I/O error + final Connection realConnection = connection.getMetaData().getConnection(); + Assert.assertNotSame(connection, realConnection); + realConnection.close(); + } + try (Connection connection = datasource.getConnection()) { + try (Statement statement = connection.createStatement()) { + try (ResultSet resultSet = statement.executeQuery("select 1")) { + Assert.assertTrue(resultSet.next()); + Assert.assertEquals(1, resultSet.getInt(1)); + } + } + } + } + @Test public void testOnConnectValidationSuccessWithValidationQueryAndAutoCommitEnabled() throws SQLException { checkOnConnectValidationWithOutcome(ValidationOutcome.SUCCESS, WITHVALIDATIONQUERY, WITHAUTOCOMMIT);