This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-dbcp.git
commit fb4106db86bf66a530f655026a79b60e6956dbcf Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Mon Aug 19 12:55:35 2024 -0400 Add support for ignoring non-fatal SQL state codes #421 - Error message should contain all SQL codes in conflict - Do not use static imports (only used these in unit tests) - Javadoc: Empty line before tags - Javadoc: Add missing sentences - Javadoc: @since tag is last in new elements - Use longer lines - Reduce redundant boilerplace - Sort members - Flip error message - Use final - Less whitespace - Simpler lambdas (less boilerplate) --- .../org/apache/commons/dbcp2/BasicDataSource.java | 108 ++++++++++----------- .../org/apache/commons/dbcp2/DataSourceMXBean.java | 16 +-- .../apache/commons/dbcp2/PoolableConnection.java | 1 + .../commons/dbcp2/PoolableConnectionFactory.java | 66 ++++++------- src/main/java/org/apache/commons/dbcp2/Utils.java | 51 +++++----- .../dbcp2/managed/BasicManagedDataSource.java | 3 +- .../dbcp2/managed/PoolableManagedConnection.java | 21 ++-- .../apache/commons/dbcp2/TestBasicDataSource.java | 108 +++++++++------------ .../commons/dbcp2/TestBasicDataSourceMXBean.java | 4 +- .../dbcp2/TestDelegatingDatabaseMetaData.java | 8 +- .../commons/dbcp2/TestPoolableConnection.java | 42 ++++---- .../java/org/apache/commons/dbcp2/TestUtils.java | 64 ++++++------ .../dbcp2/cpdsadapter/TestDriverAdapterCPDS.java | 1 - 13 files changed, 238 insertions(+), 255 deletions(-) diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java index b7e3fe51..96301028 100644 --- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java @@ -16,8 +16,6 @@ */ package org.apache.commons.dbcp2; -import static org.apache.commons.dbcp2.Utils.checkForConflicts; - import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; @@ -60,7 +58,6 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; /** * Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties. - * * <p> * This is not the only way to combine the <em>commons-dbcp2</em> and <em>commons-pool2</em> packages, but provides a * one-stop solution for basic requirements. @@ -350,6 +347,7 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean /** * A collection of SQL State codes that are not considered fatal disconnection codes. + * * @since 2.13.0 */ private volatile Set<String> disconnectionIgnoreSqlCodes; @@ -861,18 +859,6 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean return this.defaultTransactionIsolation; } - /** - * Gets the set of SQL State codes considered to signal fatal conditions. - * - * @return fatal disconnection state codes - * @see #setDisconnectionSqlCodes(Collection) - * @since 2.1 - */ - public Set<String> getDisconnectionSqlCodes() { - final Set<String> result = disconnectionSqlCodes; - return result == null ? Collections.emptySet() : result; - } - /** * Gets the set of SQL State codes that are not considered fatal disconnection codes. * <p> @@ -890,23 +876,35 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean } /** - * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX. + * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX. * - * @since 2.1 + * @since 2.13.0 */ @Override - public String[] getDisconnectionSqlCodesAsArray() { - return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); + public String[] getDisconnectionIgnoreSqlCodesAsArray() { + return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); } /** - * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX. + * Gets the set of SQL State codes considered to signal fatal conditions. * - * @since 2.13.0 + * @return fatal disconnection state codes + * @see #setDisconnectionSqlCodes(Collection) + * @since 2.1 + */ + public Set<String> getDisconnectionSqlCodes() { + final Set<String> result = disconnectionSqlCodes; + return result == null ? Collections.emptySet() : result; + } + + /** + * Provides the same data as {@link #getDisconnectionSqlCodes} but in an array so it is accessible via JMX. + * + * @since 2.1 */ @Override - public String[] getDisconnectionIgnoreSqlCodesAsArray() { - return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); + public String[] getDisconnectionSqlCodesAsArray() { + return getDisconnectionSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY); } /** @@ -1980,36 +1978,6 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean this.defaultTransactionIsolation = defaultTransactionIsolation; } - /** - * Sets the SQL State codes considered to signal fatal conditions. - * <p> - * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with - * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()} - * is {@code true}, whenever connections created by this datasource generate exceptions with SQL State codes in this - * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at - * isValid or validation query). - * </p> - * <p> - * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect. - * </p> - * <p> - * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first - * time one of the following methods is invoked: {@code getConnection, setLogwriter, - * setLoginTimeout, getLoginTimeout, getLogWriter}. - * </p> - * - * @param disconnectionSqlCodes SQL State codes considered to signal fatal conditions - * @since 2.1 - * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. - */ - public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { - checkForConflicts(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes, - "disconnectionSqlCodes", "disconnectionIgnoreSqlCodes"); - final Set<String> collect = Utils.isEmpty(disconnectionSqlCodes) ? null - : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet()); - this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect; - } - /** * Sets the SQL State codes that should be ignored when determining fatal disconnection conditions. * <p> @@ -2030,17 +1998,45 @@ public class BasicDataSource implements DataSource, BasicDataSourceMXBean, MBean * </p> * * @param disconnectionIgnoreSqlCodes SQL State codes that should be ignored in disconnection checks - * @since 2.13.0 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. + * @since 2.13.0 */ public void setDisconnectionIgnoreSqlCodes(final Collection<String> disconnectionIgnoreSqlCodes) { - checkForConflicts(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes, - "disconnectionIgnoreSqlCodes", "disconnectionSqlCodes"); + Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); final Set<String> collect = Utils.isEmpty(disconnectionIgnoreSqlCodes) ? null : disconnectionIgnoreSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet()); this.disconnectionIgnoreSqlCodes = Utils.isEmpty(collect) ? null : collect; } + /** + * Sets the SQL State codes considered to signal fatal conditions. + * <p> + * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with + * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #getFastFailValidation()} + * is {@code true}, whenever connections created by this datasource generate exceptions with SQL State codes in this + * list, they will be marked as "fatally disconnected" and subsequent validations will fail fast (no attempt at + * isValid or validation query). + * </p> + * <p> + * If {@link #getFastFailValidation()} is {@code false} setting this property has no effect. + * </p> + * <p> + * Note: this method currently has no effect once the pool has been initialized. The pool is initialized the first + * time one of the following methods is invoked: {@code getConnection, setLogwriter, + * setLoginTimeout, getLoginTimeout, getLogWriter}. + * </p> + * + * @param disconnectionSqlCodes SQL State codes considered to signal fatal conditions + * @since 2.1 + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. + */ + public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { + Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); + final Set<String> collect = Utils.isEmpty(disconnectionSqlCodes) ? null + : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet()); + this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect; + } + /** * Sets the JDBC Driver instance to use for this pool. * <p> diff --git a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java index 3c55187b..c28bd1f6 100644 --- a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java +++ b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java @@ -85,14 +85,6 @@ public interface DataSourceMXBean { */ int getDefaultTransactionIsolation(); - /** - * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. - * - * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. - * @since 2.1 - */ - String[] getDisconnectionSqlCodesAsArray(); - /** * See {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}. * @@ -103,6 +95,14 @@ public interface DataSourceMXBean { return Utils.EMPTY_STRING_ARRAY; } + /** + * See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. + * + * @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}. + * @since 2.1 + */ + String[] getDisconnectionSqlCodesAsArray(); + /** * See {@link BasicDataSource#getDriverClassName()}. * diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java index 26940221..612560a3 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnection.java @@ -78,6 +78,7 @@ public class PoolableConnection extends DelegatingConnection<Connection> impleme /** * A collection of SQL State codes that are not considered fatal disconnection codes. + * * @since 2.13.0 */ private final Collection<String> disconnectionIgnoreSqlCodes; diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java index ff6d0513..c2f12d2e 100644 --- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java @@ -16,8 +16,6 @@ */ package org.apache.commons.dbcp2; -import static org.apache.commons.dbcp2.Utils.checkForConflicts; - import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; @@ -275,7 +273,22 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo } /** - * SQL State codes considered to signal fatal conditions. + * Gets the collection of SQL State codes that are not considered fatal disconnection codes. + * <p> + * This method returns the collection of SQL State codes that have been set to be ignored when + * determining if a {@link SQLException} signals a disconnection. These codes are excluded from + * being treated as fatal even if they match the typical disconnection criteria. + * </p> + * + * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks. + * @since 2.13.0 + */ + public Collection<String> getDisconnectionIgnoreSqlCodes() { + return disconnectionIgnoreSqlCodes; + } + + /** + * Gets SQL State codes considered to signal fatal conditions. * <p> * Overrides the defaults in {@link Utils#getDisconnectionSqlCodes()} (plus anything starting with * {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}). If this property is non-null and {@link #isFastFailValidation()} is @@ -294,21 +307,6 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo return disconnectionSqlCodes; } - /** - * Retrieves the collection of SQL State codes that are not considered fatal disconnection codes. - * <p> - * This method returns the collection of SQL State codes that have been set to be ignored when - * determining if a {@link SQLException} signals a disconnection. These codes are excluded from - * being treated as fatal even if they match the typical disconnection criteria. - * </p> - * - * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks. - * @since 2.13.0 - */ - public Collection<String> getDisconnectionIgnoreSqlCodes() { - return disconnectionIgnoreSqlCodes; - } - /** * Gets the Maximum connection duration. * @@ -622,6 +620,22 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo } /** + * Sets the disconnection SQL codes to ignore. + * + * @param disconnectionIgnoreSqlCodes + * The collection of SQL State codes to be ignored. + * @see #getDisconnectionIgnoreSqlCodes() + * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. + * @since 2.13.0 + */ + public void setDisconnectionIgnoreSqlCodes(Collection<String> disconnectionIgnoreSqlCodes) { + Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes); + this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; + } + + /** + * Sets the disconnection SQL codes. + * * @param disconnectionSqlCodes * The disconnection SQL codes. * @see #getDisconnectionSqlCodes() @@ -629,24 +643,10 @@ public class PoolableConnectionFactory implements PooledObjectFactory<PoolableCo * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. */ public void setDisconnectionSqlCodes(final Collection<String> disconnectionSqlCodes) { - checkForConflicts(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes, - "disconnectionSqlCodes", "disconnectionIgnoreSqlCodes"); + Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); this.disconnectionSqlCodes = disconnectionSqlCodes; } - /** - * @param disconnectionIgnoreSqlCodes - * The collection of SQL State codes to be ignored. - * @see #getDisconnectionIgnoreSqlCodes() - * @since 2.13.0 - * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}. - */ - public void setDisconnectionIgnoreSqlCodes(Collection<String> disconnectionIgnoreSqlCodes) { - checkForConflicts(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes, - "disconnectionIgnoreSqlCodes", "disconnectionSqlCodes"); - this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes; - } - /** * @param autoCommitOnReturn Whether to auto-commit on return. * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}. diff --git a/src/main/java/org/apache/commons/dbcp2/Utils.java b/src/main/java/org/apache/commons/dbcp2/Utils.java index ad927225..6f236c52 100644 --- a/src/main/java/org/apache/commons/dbcp2/Utils.java +++ b/src/main/java/org/apache/commons/dbcp2/Utils.java @@ -82,6 +82,34 @@ public final class Utils { DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error } + /** + * Checks for conflicts between two collections. + * <p> + * If any overlap is found between the two provided collections, an {@link IllegalArgumentException} is thrown. + * </p> + * + * @param codes1 The first collection of SQL state codes. + * @param codes2 The second collection of SQL state codes. + * @throws IllegalArgumentException if any codes overlap between the two collections. + * @since 2.13.0 + */ + static void checkSqlCodes(final Collection<String> codes1, final Collection<String> codes2) { +// if (codes1 != null && codes2 != null) { +// for (String code : codes1) { +// if (codes2.contains(code)) { +// throw new IllegalArgumentException(code + " cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes."); +// } +// } +// } + if (codes1 != null && codes2 != null) { + final Set<String> test = new HashSet<>(codes1); + test.retainAll(codes2); + if (!test.isEmpty()) { + throw new IllegalArgumentException(test + " cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes."); + } + } + } + /** * Clones the given char[] if not null. * @@ -138,29 +166,6 @@ public final class Utils { close(autoCloseable, null); } - /** - * Checks for conflicts between two collections. - * <p> - * If any overlap is found between the two provided collections, an {@link IllegalArgumentException} is thrown. - * </p> - * - * @param codes1 The first collection of SQL state codes. - * @param codes2 The second collection of SQL state codes. - * @param name1 The name of the first collection (for exception message). - * @param name2 The name of the second collection (for exception message). - * @since 2.13.0 - * @throws IllegalArgumentException if any codes overlap between the two collections. - */ - static void checkForConflicts(Collection<String> codes1, Collection<String> codes2, String name1, String name2) { - if (codes1 != null && codes2 != null) { - for (String code : codes1) { - if (codes2.contains(code)) { - throw new IllegalArgumentException(code + " cannot be in both " + name1 + " and " + name2 + "."); - } - } - } - } - /** * Closes the Connection (which may be null). * diff --git a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java index c293e27c..9bd1c993 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java @@ -126,8 +126,7 @@ public class BasicManagedDataSource extends BasicDataSource { throws SQLException { PoolableConnectionFactory connectionFactory = null; try { - connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, - getRegisteredJmxName()); + connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, getRegisteredJmxName()); connectionFactory.setValidationQuery(getValidationQuery()); connectionFactory.setValidationQueryTimeout(getValidationQueryTimeoutDuration()); connectionFactory.setConnectionInitSql(getConnectionInitSqls()); diff --git a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java index 5eea0397..2be2e1a4 100644 --- a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnection.java @@ -33,7 +33,7 @@ public class PoolableManagedConnection extends PoolableConnection { private final TransactionRegistry transactionRegistry; /** - * Create a PoolableManagedConnection. + * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry @@ -42,13 +42,12 @@ public class PoolableManagedConnection extends PoolableConnection { * @param pool * connection pool */ - public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, - final ObjectPool<PoolableConnection> pool) { + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool<PoolableConnection> pool) { this(transactionRegistry, conn, pool, null, true); } /** - * Create a PoolableManagedConnection. + * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry @@ -62,14 +61,13 @@ public class PoolableManagedConnection extends PoolableConnection { * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to * run query or isValid) */ - public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, - final ObjectPool<PoolableConnection> pool, final Collection<String> disconnectSqlCodes, - final boolean fastFailValidation) { + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool<PoolableConnection> pool, + final Collection<String> disconnectSqlCodes, final boolean fastFailValidation) { this(transactionRegistry, conn, pool, disconnectSqlCodes, null, fastFailValidation); } /** - * Create a PoolableManagedConnection. + * Creates a PoolableManagedConnection. * * @param transactionRegistry * transaction registry @@ -86,14 +84,15 @@ public class PoolableManagedConnection extends PoolableConnection { * run query or isValid) * @since 2.13.0 */ - public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, - final ObjectPool<PoolableConnection> pool, final Collection<String> disconnectSqlCodes, - final Collection<String> disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { + public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool<PoolableConnection> pool, + final Collection<String> disconnectSqlCodes, final Collection<String> disconnectionIgnoreSqlCodes, final boolean fastFailValidation) { super(conn, pool, null, disconnectSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation); this.transactionRegistry = transactionRegistry; } /** + * Gets the transaction registry. + * * @return The transaction registry. * @since 2.6.0 */ diff --git a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java index 3b3ec7ed..66c852d1 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java +++ b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSource.java @@ -440,6 +440,21 @@ public class TestBasicDataSource extends TestConnectionPool { } } + @Test + public void testDisconnectionIgnoreSqlCodes() throws Exception { + final ArrayList<String> disconnectionIgnoreSqlCodes = new ArrayList<>(); + disconnectionIgnoreSqlCodes.add("XXXX"); + ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); + ds.setFastFailValidation(true); + try (Connection conn = ds.getConnection()) { // Triggers initialization - pcf creation + // Make sure factory got the properties + final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory(); + assertTrue(pcf.isFastFailValidation()); + assertTrue(pcf.getDisconnectionIgnoreSqlCodes().contains("XXXX")); + assertEquals(1, pcf.getDisconnectionIgnoreSqlCodes().size()); + } + } + /** * JIRA: DBCP-437 * Verify that BasicDataSource sets disconnect codes properties. @@ -460,51 +475,6 @@ public class TestBasicDataSource extends TestConnectionPool { } } - @Test - public void testOverlapBetweenDisconnectionAndIgnoreSqlCodes() { - // Set initial disconnection SQL codes - final HashSet<String> disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); - ds.setDisconnectionSqlCodes(disconnectionSqlCodes); - - // Try setting ignore SQL codes with overlap - final HashSet<String> disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "XXX")); - - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); - }); - - assertEquals("XXX cannot be in both disconnectionIgnoreSqlCodes and disconnectionSqlCodes.", exception.getMessage()); - } - - @Test - public void testNoOverlapBetweenDisconnectionAndIgnoreSqlCodes() { - // Set disconnection SQL codes without overlap - final HashSet<String> disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); - ds.setDisconnectionSqlCodes(disconnectionSqlCodes); - - // Set ignore SQL codes without overlap - final HashSet<String> disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "AAA")); - ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); - - assertEquals(disconnectionSqlCodes, ds.getDisconnectionSqlCodes(), "Disconnection SQL codes should match the set values."); - assertEquals(disconnectionIgnoreSqlCodes, ds.getDisconnectionIgnoreSqlCodes(), "Disconnection Ignore SQL codes should match the set values."); - } - - @Test - public void testDisconnectionIgnoreSqlCodes() throws Exception { - final ArrayList<String> disconnectionIgnoreSqlCodes = new ArrayList<>(); - disconnectionIgnoreSqlCodes.add("XXXX"); - ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); - ds.setFastFailValidation(true); - try (Connection conn = ds.getConnection()) { // Triggers initialization - pcf creation - // Make sure factory got the properties - final PoolableConnectionFactory pcf = (PoolableConnectionFactory) ds.getConnectionPool().getFactory(); - assertTrue(pcf.isFastFailValidation()); - assertTrue(pcf.getDisconnectionIgnoreSqlCodes().contains("XXXX")); - assertEquals(1, pcf.getDisconnectionIgnoreSqlCodes().size()); - } - } - /** * JIRA DBCP-333: Check that a custom class loader is used. * @throws Exception @@ -628,15 +598,15 @@ public class TestBasicDataSource extends TestConnectionPool { } @Test - public void testInvalidConnectionInitSqlList() { - ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); + public void testInvalidConnectionInitSqlCollection() { + ds.setConnectionInitSqls((Collection<String>) Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @Test - public void testInvalidConnectionInitSqlCollection() { - ds.setConnectionInitSqls((Collection<String>) Arrays.asList("SELECT 1", "invalid")); + public void testInvalidConnectionInitSqlList() { + ds.setConnectionInitSqls(Arrays.asList("SELECT 1", "invalid")); final SQLException e = assertThrows(SQLException.class, ds::getConnection); assertTrue(e.toString().contains("invalid")); } @@ -704,23 +674,14 @@ public class TestBasicDataSource extends TestConnectionPool { @Test public void testJmxDoesNotExposePassword() throws Exception { final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - try (Connection c = ds.getConnection()) { // nothing } final ObjectName objectName = new ObjectName(ds.getJmxName()); - final MBeanAttributeInfo[] attributes = mbs.getMBeanInfo(objectName).getAttributes(); - assertTrue(attributes != null && attributes.length > 0); - - Arrays.asList(attributes).forEach(attrInfo -> { - assertFalse("password".equalsIgnoreCase(attrInfo.getName())); - }); - - assertThrows(AttributeNotFoundException.class, () -> { - mbs.getAttribute(objectName, "Password"); - }); + Arrays.asList(attributes).forEach(attrInfo -> assertFalse("password".equalsIgnoreCase(attrInfo.getName()))); + assertThrows(AttributeNotFoundException.class, () -> mbs.getAttribute(objectName, "Password")); } @Test @@ -830,6 +791,33 @@ public class TestBasicDataSource extends TestConnectionPool { } } + @Test + public void testNoOverlapBetweenDisconnectionAndIgnoreSqlCodes() { + // Set disconnection SQL codes without overlap + final HashSet<String> disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); + ds.setDisconnectionSqlCodes(disconnectionSqlCodes); + + // Set ignore SQL codes without overlap + final HashSet<String> disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "AAA")); + ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes); + + assertEquals(disconnectionSqlCodes, ds.getDisconnectionSqlCodes(), "Disconnection SQL codes should match the set values."); + assertEquals(disconnectionIgnoreSqlCodes, ds.getDisconnectionIgnoreSqlCodes(), "Disconnection Ignore SQL codes should match the set values."); + } + + @Test + public void testOverlapBetweenDisconnectionAndIgnoreSqlCodes() { + // Set initial disconnection SQL codes + final HashSet<String> disconnectionSqlCodes = new HashSet<>(Arrays.asList("XXX", "ZZZ")); + ds.setDisconnectionSqlCodes(disconnectionSqlCodes); + // Try setting ignore SQL codes with overlap + final HashSet<String> disconnectionIgnoreSqlCodes = new HashSet<>(Arrays.asList("YYY", "XXX")); + + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> ds.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes)); + assertEquals("[XXX] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); + } + /** * Verifies correct handling of exceptions generated by the underlying pool as it closes * connections in response to BDS#close. Exceptions have to be either swallowed by the diff --git a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java index d1227b0d..56b78fc7 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java +++ b/src/test/java/org/apache/commons/dbcp2/TestBasicDataSourceMXBean.java @@ -79,12 +79,12 @@ public class TestBasicDataSourceMXBean { } @Override - public String[] getDisconnectionSqlCodesAsArray() { + public String[] getDisconnectionIgnoreSqlCodesAsArray() { return null; } @Override - public String[] getDisconnectionIgnoreSqlCodesAsArray() { + public String[] getDisconnectionSqlCodesAsArray() { return null; } diff --git a/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java b/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java index 74886ccc..05fed114 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDelegatingDatabaseMetaData.java @@ -772,12 +772,8 @@ public class TestDelegatingDatabaseMetaData { @Test public void testNullArguments() throws Exception { - assertThrows(NullPointerException.class, () -> { - new DelegatingDatabaseMetaData(null, null); - }); - assertThrows(NullPointerException.class, () -> { - new DelegatingDatabaseMetaData(new DelegatingConnection(null), null); - }); + assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(null, null)); + assertThrows(NullPointerException.class, () -> new DelegatingDatabaseMetaData(new DelegatingConnection(null), null)); } @Test diff --git a/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java b/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java index 4b7681fe..d36e1ff4 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TestPoolableConnection.java @@ -90,6 +90,27 @@ public class TestPoolableConnection { assertEquals(0, pool.getNumActive(), "There should now be zero active objects in the pool"); } + @Test + public void testDisconnectionIgnoreSqlCodes() throws Exception { + pool.setTestOnReturn(true); + final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); + factory.setFastFailValidation(true); + factory.setDisconnectionIgnoreSqlCodes(Arrays.asList("08S02", "08007")); + + final PoolableConnection conn = pool.borrowObject(); + final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); + + // set up non-fatal exception + nativeConnection.setFailure(new SQLException("Non-fatal connection error.", "08S02")); + assertThrows(SQLException.class, conn::createStatement); + nativeConnection.setFailure(null); + + // verify that non-fatal connection is returned to the pool + conn.close(); + assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); + assertEquals(1, pool.getNumIdle(), "The pool should have one idle connection"); + } + @Test public void testFastFailValidation() throws Exception { pool.setTestOnReturn(true); @@ -183,27 +204,6 @@ public class TestPoolableConnection { TestBasicDataSourceMXBean.testMXBeanCompliance(PoolableConnectionMXBean.class); } - @Test - public void testDisconnectionIgnoreSqlCodes() throws Exception { - pool.setTestOnReturn(true); - final PoolableConnectionFactory factory = (PoolableConnectionFactory) pool.getFactory(); - factory.setFastFailValidation(true); - factory.setDisconnectionIgnoreSqlCodes(Arrays.asList("08S02", "08007")); - - final PoolableConnection conn = pool.borrowObject(); - final TesterConnection nativeConnection = (TesterConnection) conn.getInnermostDelegate(); - - // set up non-fatal exception - nativeConnection.setFailure(new SQLException("Non-fatal connection error.", "08S02")); - assertThrows(SQLException.class, conn::createStatement); - nativeConnection.setFailure(null); - - // verify that non-fatal connection is returned to the pool - conn.close(); - assertEquals(0, pool.getNumActive(), "The pool should have no active connections"); - assertEquals(1, pool.getNumIdle(), "The pool should have one idle connection"); - } - // Bugzilla Bug 33591: PoolableConnection leaks connections if the // delegated connection closes itself. @Test diff --git a/src/test/java/org/apache/commons/dbcp2/TestUtils.java b/src/test/java/org/apache/commons/dbcp2/TestUtils.java index 30bd8715..79d06eb0 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestUtils.java +++ b/src/test/java/org/apache/commons/dbcp2/TestUtils.java @@ -17,16 +17,16 @@ package org.apache.commons.dbcp2; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; public class TestUtils { @@ -35,52 +35,52 @@ public class TestUtils { } @Test - public void testCheckForConflictsWithOverlap() { - Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); - Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08006")); - - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - Utils.checkForConflicts(codes1, codes2, "codes1", "codes2"); - }); - - assertEquals("08006 cannot be in both codes1 and codes2.", exception.getMessage()); + public void testCheckForConflictsBothCollectionsNull() { + assertDoesNotThrow(() -> Utils.checkSqlCodes(null, null)); } @Test - public void testCheckForConflictsNoOverlap() { - Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); - Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08007")); - - assertDoesNotThrow(() -> Utils.checkForConflicts(codes1, codes2, "codes1", "codes2")); + public void testCheckForConflictsEmptyCollections() { + final Collection<String> codes1 = Collections.emptySet(); + final Collection<String> codes2 = Collections.emptySet(); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsFirstCollectionNull() { - Collection<String> codes1 = null; - Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08007")); + final Collection<String> codes1 = null; + final Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08007")); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); + } - assertDoesNotThrow(() -> Utils.checkForConflicts(codes1, codes2, "codes1", "codes2")); + @Test + public void testCheckForConflictsNoOverlap() { + final Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08007")); + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test public void testCheckForConflictsSecondCollectionNull() { - Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); - Collection<String> codes2 = null; - - assertDoesNotThrow(() -> Utils.checkForConflicts(codes1, codes2, "codes1", "codes2")); + final Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection<String> codes2 = null; + assertDoesNotThrow(() -> Utils.checkSqlCodes(codes1, codes2)); } @Test - public void testCheckForConflictsBothCollectionsNull() { - assertDoesNotThrow(() -> Utils.checkForConflicts(null, null, "codes1", "codes2")); + public void testCheckForConflictsWith1Overlap() { + final Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006")); + final Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08006")); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); + assertEquals("[08006] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); } @Test - public void testCheckForConflictsEmptyCollections() { - Collection<String> codes1 = Collections.emptySet(); - Collection<String> codes2 = Collections.emptySet(); - - assertDoesNotThrow(() -> Utils.checkForConflicts(codes1, codes2, "codes1", "codes2")); + public void testCheckForConflictsWith2Overlap() { + final Collection<String> codes1 = new HashSet<>(Arrays.asList("08003", "08006", "08007")); + final Collection<String> codes2 = new HashSet<>(Arrays.asList("08005", "08006", "08007")); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Utils.checkSqlCodes(codes1, codes2)); + assertEquals("[08006, 08007] cannot be in both disconnectionSqlCodes and disconnectionIgnoreSqlCodes.", exception.getMessage()); } @Test diff --git a/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java b/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java index 68573f42..73746669 100644 --- a/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java +++ b/src/test/java/org/apache/commons/dbcp2/cpdsadapter/TestDriverAdapterCPDS.java @@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import java.io.PrintWriter; import java.sql.Connection;