diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 13dec553b3..8a163a4770 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -46,10 +46,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- persist-credentials: false
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+ - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -58,7 +58,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8
+ uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -69,7 +69,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8
+ uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -83,4 +83,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8
+ uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
deleted file mode 100644
index 178f5a32a9..0000000000
--- a/.github/workflows/coverage.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-name: Coverage
-
-on:
- workflow_dispatch: #Allows to run workflow manually
- push:
- branches:
- - master
- - 'DBCP_2_**'
- pull_request:
-
-permissions:
- contents: read
-
-jobs:
- build:
- if: false
-
- runs-on: ubuntu-latest
- strategy:
- matrix:
- java: [ 8 ]
-
- steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- persist-credentials: false
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven-
- - name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
- with:
- distribution: 'temurin'
- java-version: ${{ matrix.java }}
- - name: Build with Maven
- run: mvn --show-version --batch-mode --no-transfer-progress test jacoco:report
-
- - name: Upload coverage to Codecov
- uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
- with:
- files: ./target/site/jacoco/jacoco.xml
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 0000000000..c6ece650e2
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,31 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: 'Dependency Review'
+on: [pull_request]
+
+permissions:
+ contents: read
+
+jobs:
+ dependency-review:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Checkout Repository'
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - name: 'Dependency Review PR'
+ uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index ab2e52876a..7129611314 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -33,24 +33,24 @@ jobs:
continue-on-error: ${{ matrix.experimental }}
strategy:
matrix:
- java: [ 11, 17, 21 ]
+ java: [ 11, 17, 21, 23 ]
experimental: [false]
-# include:
-# - java: 22-ea
-# experimental: true
+ include:
+ - java: 24-ea
+ experimental: true
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- persist-credentials: false
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ with:
+ persist-credentials: false
+ - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
+ uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index a1580a2f8e..8e3eb3fa72 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -41,12 +41,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # 2.3.3
+ uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # 2.4.0
with:
results_file: results.sarif
results_format: sarif
@@ -58,13 +58,13 @@ jobs:
publish_results: true
- name: "Upload artifact"
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3
+ uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # 3.25.8
+ uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # 3.27.5
with:
sarif_file: results.sarif
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cf9b8149fd..5f23f94fbe 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -41,9 +41,8 @@
Contributing to Apache Commons DBCP
======================
-You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to
-the open source community. Before you dig right into the code there are a few guidelines that we need contributors to
-follow so that we can have a chance of keeping on top of things.
+Have you found a bug or have an idea for a cool new feature? Contributing code is a great way to give something back to the open-source community.
+Before you dig right into the code, we need contributors to follow a few guidelines to have a chance of keeping on top of things.
Getting Started
---------------
@@ -62,7 +61,7 @@ Making Changes
+ Create a _topic branch_ for your isolated work.
* Usually you should base your branch on the `master` branch.
- * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `DBCP-123-InputStream`.
+ * A good topic branch name can be the JIRA bug ID plus a keyword, e.g. `DBCP-123-InputStream`.
* If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.
+ Make commits of logical units.
* Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.
@@ -72,7 +71,7 @@ Making Changes
+ Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.
+ Check for unnecessary whitespace with `git diff` -- check before committing.
+ Make sure you have added the necessary tests for your changes, typically in `src/test/java`.
-+ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.
++ Run all the tests with `mvn clean verify` to ensure nothing else was accidentally broken.
Making Trivial Changes
----------------------
diff --git a/NOTICE.txt b/NOTICE.txt
index d4901a2c38..75a281ea6c 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
-Apache Commons DBCP
-Copyright 2001-2024 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (https://www.apache.org/).
+Apache Commons DBCP
+Copyright 2001-2024 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (https://www.apache.org/).
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 9bee95bd41..642e0405ac 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,4 +1,56 @@
Apache Commons DBCP
+Version 2.13.0
+RELEASE NOTES
+
+The Apache Commons DBCP team is pleased to announce the release of Apache Commons DBCP 2.13.0.
+
+Apache Commons DBCP software implements Database Connection Pooling.
+
+This is a minor release, including bug fixes and enhancements.
+
+Changes
+-------
+New features:
+* Add support for ignoring non-fatal SQL state codes #421. Thanks to Johno Crawford, Gary Gregory.
+* Add @FunctionalInterface to SwallowedExceptionListener. Thanks to Johno Crawford, Gary Gregory.
+* Add missing Javadoc comments and descriptions. Thanks to Gary Gregory.
+* Add tests, raise the bar for JaCoCo checks. Thanks to Gary Gregory.
+
+Fixed Bugs
+----------
+* Avoid object creation when invoking isDisconnectionSqlException #422. Thanks to Johno Crawford.
+* DBCP-599: PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge Thanks to denixx baykin, Phil Steitz, Gary Gregory.
+* DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge. Thanks to Gary Gregory.
+* Fix possible NullPointerException in PoolingConnection.close(). Thanks to Gary Gregory.
+* PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException. Thanks to Gary Gregory.
+* Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace. Thanks to Gary Gregory.
+* Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement. Thanks to Gary Gregory.
+* Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement. Thanks to Gary Gregory.
+* Fix PMD UnnecessaryFullyQualifiedName in Utils. Thanks to Gary Gregory.
+* Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory. Thanks to Gary Gregory.
+* Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource. Thanks to Gary Gregory.
+* Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource. Thanks to Gary Gregory.
+
+Changes
+-------
+* Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449. Thanks to Gary Gregory.
+* Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423. Thanks to Gary Gregory, Dependabot.
+* Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427. Thanks to Gary Gregory, Dependabot.
+* Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410. Thanks to Gary Gregory, Dependabot.
+* Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418. Thanks to Gary Gregory, Dependabot.
+
+
+The list of changes is here: https://commons.apache.org/proper/commons-dbcp/changes-report.html
+
+For complete information on Apache Commons DBCP, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons DBCP website:
+
+https://commons.apache.org/proper/commons-dbcp/
+
+Download page: https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
+
+-----------------------------------------------------------------------------
+Apache Commons DBCP
Version 2.12.0
RELEASE NOTES
diff --git a/pom.xml b/pom.xml
index 4a9f85e499..8df87657b3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,11 +22,11 @@
org.apache.commonscommons-parent
- 71
+ 784.0.0commons-dbcp2
- 2.12.1-NX02-SNAPSHOT
+ 2.13.0Apache Commons DBCP2001
@@ -59,40 +59,28 @@
commons-pool2${commons.pool.version}
-
commons-loggingcommons-logging
- 1.3.2
+ 1.3.4
-
org.junit.jupiterjunit-jupitertest
-
-
- org.hamcrest
- hamcrest
- 2.2
- test
-
-
org.mockitomockito-core4.11.0test
-
org.apache.commonscommons-lang3
- 3.14.0
+ 3.17.0test
-
jakarta.transaction
@@ -111,7 +99,6 @@
2.0.1true
-
tomcat
@@ -119,14 +106,12 @@
5.0.28test
-
tomcatnaming-java5.0.28test
-
org.apache.geronimo.components
@@ -147,7 +132,7 @@
org.slf4jslf4j-simple
- 2.0.13
+ 2.0.16test
@@ -187,15 +172,15 @@
UTF-8UTF-8
- 2024-06-12T11:33:27Z
+ 2024-11-23T22:28:37Z1.81.8dbcpRC1org.apache.commons.dbcp2
- 2.12.0
- 2.12.1
+ 2.13.0
+ 2.13.1for JDBC 4.2 on Java 8sha512
@@ -213,7 +198,7 @@
javax.transaction;version="1.1.0",javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial,*true
- 2.11.0
+ 2.12.0truefalsefalse
@@ -223,12 +208,13 @@
true
+
0.98
- 0.68
- 0.87
+ 0.74
+ 0.890.660.62
- 0.76
+ 0.78clean verify apache-rat:check checkstyle:check spotbugs:check pmd:check pmd:cpd-check javadoc:javadoc
@@ -267,9 +253,8 @@
${commons.javadoc.version}
- http://docs.oracle.com/javase/8/docs/api
https://commons.apache.org/proper/commons-pool/apidocs
- http://docs.oracle.com/javaee/7/api/
+ ${commons.javadoc.javaee.link}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index bbbafc3ade..f005fccec6 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -62,19 +62,31 @@ The type attribute can be add,update,fix,remove.
EvictionTimer
-->
-
+
- Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace.
- Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement.
- Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement.
- Fix PMD UnnecessaryFullyQualifiedName in Utils.
- Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory.
- Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource.
- Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource.
+ Avoid object creation when invoking isDisconnectionSqlException #422.
+ PoolableConnectionFactory.destroyObject() method behaves incorrectly on ABANDONED connection, issue with unhandled AbstractMethodError. DelegatingConnection.abort(Executor) should delegate to Jdbc41Bridge
+ DelegatingConnection.setSchema(String) should delegate to Jdbc41Bridge.
+ Fix possible NullPointerException in PoolingConnection.close().
+ PerUserPoolDataSource.registerPool() incorrectly replacing a CPDSConnectionFactory into managers map before throwing an IllegalStateException.
+ Fix PMD UnnecessaryFullyQualifiedName in AbandonedTrace.
+ Fix PMD UnnecessaryFullyQualifiedName in PoolableCallableStatement.
+ Fix PMD UnnecessaryFullyQualifiedName in PoolablePreparedStatement.
+ Fix PMD UnnecessaryFullyQualifiedName in Utils.
+ Fix PMD UnnecessaryFullyQualifiedName in LocalXAConnectionFactory.
+ Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in PerUserPoolDataSource.
+ Fix SpotBugs MC_OVERRIDABLE_METHOD_CALL_IN_READ_OBJECT in SharedPoolDataSource.
+ Add support for ignoring non-fatal SQL state codes #421.
+ Add @FunctionalInterface to SwallowedExceptionListener.
+ Add missing Javadoc comments and descriptions.
+ Add tests, raise the bar for JaCoCo checks.
- Bump org.apache.commons:commons-parent from 66 to 71 #360, #371, #395.
- Bump commons-logging:commons-logging from 1.3.0 to 1.3.2 #368.
+ Bump org.apache.commons:commons-parent from 66 to 78 #360, #371, #395, #420, #426, #436, #441, #449.
+ Bump commons-logging:commons-logging from 1.3.0 to 1.3.4 #368, #399, #423.
+ Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #404, #412, #427.
+ Bump org.hamcrest:hamcrest from 2.2 to 3.0 #410.
+ Bump org.slf4j:slf4j-simple from 2.0.13 to 2.0.16 #413, #418.
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
index ed58c7aef2..259835df2f 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSource.java
@@ -30,12 +30,14 @@
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.logging.Logger;
+import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -58,7 +60,6 @@
/**
* Basic implementation of {@code javax.sql.DataSource} that is configured via JavaBeans properties.
- *
*
* This is not the only way to combine the commons-dbcp2 and commons-pool2 packages, but provides a
* one-stop solution for basic requirements.
@@ -346,6 +347,13 @@ protected static void validateConnectionFactory(final PoolableConnectionFactory
private volatile Set disconnectionSqlCodes;
+ /**
+ * A collection of SQL State codes that are not considered fatal disconnection codes.
+ *
+ * @since 2.13.0
+ */
+ private volatile Set disconnectionIgnoreSqlCodes;
+
private boolean fastFailValidation;
/**
@@ -629,6 +637,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec
connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
connectionFactory.setFastFailValidation(fastFailValidation);
connectionFactory.setDisconnectionSqlCodes(disconnectionSqlCodes);
+ connectionFactory.setDisconnectionIgnoreSqlCodes(disconnectionIgnoreSqlCodes);
validateConnectionFactory(connectionFactory);
} catch (final RuntimeException e) {
throw e;
@@ -853,7 +862,33 @@ public int getDefaultTransactionIsolation() {
}
/**
- * Gets the set of SQL_STATE codes considered to signal fatal conditions.
+ * Gets the set of SQL State codes that are not considered fatal disconnection codes.
+ *
+ * This method returns the set of SQL State codes that have been specified to be ignored
+ * when determining if a {@link SQLException} signals a disconnection. These codes will not
+ * trigger a disconnection even if they match other disconnection criteria.
+ *
+ *
+ * @return a set of SQL State codes that should be ignored for disconnection checks, or an empty set if none have been specified.
+ * @since 2.13.0
+ */
+ public Set getDisconnectionIgnoreSqlCodes() {
+ final Set result = disconnectionIgnoreSqlCodes;
+ return result == null ? Collections.emptySet() : result;
+ }
+
+ /**
+ * Provides the same data as {@link #getDisconnectionIgnoreSqlCodes()} but in an array, so it is accessible via JMX.
+ *
+ * @since 2.13.0
+ */
+ @Override
+ public String[] getDisconnectionIgnoreSqlCodesAsArray() {
+ return getDisconnectionIgnoreSqlCodes().toArray(Utils.EMPTY_STRING_ARRAY);
+ }
+
+ /**
+ * Gets the set of SQL State codes considered to signal fatal conditions.
*
* @return fatal disconnection state codes
* @see #setDisconnectionSqlCodes(Collection)
@@ -950,10 +985,11 @@ public synchronized String getEvictionPolicyClassName() {
/**
* True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
- * SQL_STATE indicating fatal disconnection errors.
+ * SQL State indicating fatal disconnection errors.
*
* @return true if connections created by this datasource will fast fail validation.
* @see #setDisconnectionSqlCodes(Collection)
+ * @see #setDisconnectionIgnoreSqlCodes(Collection)
* @since 2.1
*/
@Override
@@ -1445,7 +1481,7 @@ public synchronized String getUrl() {
* Gets the JDBC connection {code userName} property.
*
* @return the {code userName} passed to the JDBC driver to establish connections
- * @deprecated
+ * @deprecated Use {@link #getUserName()}.
*/
@Deprecated
@Override
@@ -1608,10 +1644,10 @@ protected void log(final String message) {
}
/**
- * Logs the given throwable.
- * @param message TODO
- * @param throwable the throwable.
+ * Logs the given message and throwable.
*
+ * @param message value to be log.
+ * @param throwable the throwable.
* @since 2.7.0
*/
protected void log(final String message, final Throwable throwable) {
@@ -1729,8 +1765,8 @@ public void setAbandonedUsageTracking(final boolean usageTracking) {
* the underlying connection. (Default: false)
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param allow Access to the underlying connection is granted when true.
@@ -1786,8 +1822,8 @@ public void setConnectionFactoryClassName(final String connectionFactoryClassNam
* Sets the collection of SQL statements to be executed when a physical connection is first created.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param connectionInitSqls Collection of SQL statements to execute on connection creation
@@ -1802,8 +1838,8 @@ public void setConnectionInitSqls(final Collection connectionInitSqls) {
* Sets the list of SQL statements to be executed when a physical connection is first created.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param connectionInitSqls List of SQL statements to execute on connection creation
@@ -1853,8 +1889,8 @@ public void setConnectionProperties(final String connectionProperties) {
* Sets default auto-commit state of connections returned by this datasource.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param defaultAutoCommit default auto-commit value
@@ -1867,8 +1903,8 @@ public void setDefaultAutoCommit(final Boolean defaultAutoCommit) {
* Sets the default catalog.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param defaultReadOnly default read-only value
@@ -1918,8 +1954,8 @@ public void setDefaultReadOnly(final Boolean defaultReadOnly) {
* Sets the default schema.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param defaultSchema the default catalog
@@ -1933,8 +1969,8 @@ public void setDefaultSchema(final String defaultSchema) {
* Sets the default transaction isolation state for returned connections.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param defaultTransactionIsolation the default transaction isolation state
@@ -1945,11 +1981,41 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation
}
/**
- * Sets the SQL_STATE codes considered to signal fatal conditions.
+ * Sets the SQL State codes that should be ignored when determining fatal disconnection conditions.
+ *
+ * This method allows you to specify a collection of SQL State codes that will be excluded from
+ * disconnection checks. These codes will not trigger the "fatally disconnected" status even if they
+ * match the typical disconnection criteria. This can be useful in scenarios where certain SQL State
+ * codes (e.g., specific codes starting with "08") are known to be non-fatal in your environment.
+ *
+ *
+ * The effect of this method is similar to the one described in {@link #setDisconnectionSqlCodes(Collection)},
+ * but instead of setting codes that signal fatal disconnections, it defines codes that should be ignored
+ * during such checks.
+ *
+ *
+ * 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}.
+ *
+ *
+ * @param disconnectionIgnoreSqlCodes SQL State codes that should be ignored in disconnection checks
+ * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionSqlCodes}.
+ * @since 2.13.0
+ */
+ public void setDisconnectionIgnoreSqlCodes(final Collection disconnectionIgnoreSqlCodes) {
+ Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes);
+ final Set collect = Utils.isEmpty(disconnectionIgnoreSqlCodes) ? null
+ : disconnectionIgnoreSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet());
+ this.disconnectionIgnoreSqlCodes = Utils.isEmpty(collect) ? null : collect;
+ }
+
+ /**
+ * Sets the SQL State codes considered to signal fatal conditions.
*
* 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
+ * 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).
*
@@ -1962,12 +2028,14 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation
* setLoginTimeout, getLoginTimeout, getLogWriter}.
*
*
- * @param disconnectionSqlCodes SQL_STATE codes considered to signal fatal conditions
+ * @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 disconnectionSqlCodes) {
+ Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes);
final Set collect = Utils.isEmpty(disconnectionSqlCodes) ? null
- : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(Collectors.toSet());
+ : disconnectionSqlCodes.stream().filter(s -> !isEmpty(s)).collect(toLinkedHashSet());
this.disconnectionSqlCodes = Utils.isEmpty(collect) ? null : collect;
}
@@ -1975,8 +2043,8 @@ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCo
* Sets the JDBC Driver instance to use for this pool.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param driver The JDBC Driver instance to use for this pool.
@@ -1989,8 +2057,8 @@ public synchronized void setDriver(final Driver driver) {
* Sets the class loader to be used to load the JDBC driver.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param driverClassLoader the class loader with which to load the JDBC driver
@@ -2003,8 +2071,8 @@ public synchronized void setDriverClassLoader(final ClassLoader driverClassLoade
* Sets the JDBC driver class name.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param driverClassName the class name of the JDBC driver
@@ -2062,8 +2130,8 @@ public void setFastFailValidation(final boolean fastFailValidation) {
* Sets the initial size of the connection pool.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param initialSize the number of connections created when the pool is initialized
@@ -2155,8 +2223,8 @@ public void setLogWriter(final PrintWriter logWriter) throws SQLException {
* infinite lifetime.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param maxConnDuration The maximum permitted lifetime of a connection.
@@ -2171,8 +2239,8 @@ public void setMaxConn(final Duration maxConnDuration) {
* infinite lifetime.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds.
@@ -2199,8 +2267,8 @@ public synchronized void setMaxIdle(final int maxIdle) {
* Sets the value of the {@code maxOpenPreparedStatements} property.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param maxOpenStatements the new maximum number of prepared statements
@@ -2297,8 +2365,8 @@ public synchronized void setNumTestsPerEvictionRun(final int numTestsPerEviction
* Sets the {code password}.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param password new value for the password
@@ -2311,8 +2379,8 @@ public void setPassword(final String password) {
* Sets whether to pool statements or not.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param poolingStatements pooling on or off
@@ -2483,8 +2551,8 @@ public synchronized void setTimeBetweenEvictionRunsMillis(final long timeBetween
* Sets the {code connection string}.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param connectionString the new value for the JDBC connection connectionString
@@ -2497,8 +2565,8 @@ public synchronized void setUrl(final String connectionString) {
* Sets the {code userName}.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param userName the new value for the JDBC connection user name
@@ -2511,8 +2579,8 @@ public void setUsername(final String userName) {
* Sets the {code validationQuery}.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param validationQuery the new value for the validation query
@@ -2526,8 +2594,8 @@ public void setValidationQuery(final String validationQuery) {
* response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param validationQueryTimeoutDuration new validation query timeout value in seconds
@@ -2542,8 +2610,8 @@ public void setValidationQueryTimeout(final Duration validationQueryTimeoutDurat
* response from the database when executing a validation query. Use a value less than or equal to 0 for no timeout.
*
* 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * time one of the following methods is invoked: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)},
+ * {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()}, {@link #getLogWriter()}.
*
*
* @param validationQueryTimeoutSeconds new validation query timeout value in seconds
@@ -2586,6 +2654,10 @@ protected void startPoolMaintenance() {
}
}
+ private Collector> toLinkedHashSet() {
+ return Collectors.toCollection(LinkedHashSet::new);
+ }
+
@Override
public T unwrap(final Class iface) throws SQLException {
if (isWrapperFor(iface)) {
diff --git a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
index a28b21bf52..11a154c90a 100644
--- a/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/BasicDataSourceFactory.java
@@ -120,6 +120,18 @@ public class BasicDataSourceFactory implements ObjectFactory {
*/
private static final String PROP_DISCONNECTION_SQL_CODES = "disconnectionSqlCodes";
+ /**
+ * Property key for specifying the SQL State codes that should be ignored during disconnection checks.
+ *
+ * The value for this property must be a comma-separated string of SQL State codes, where each code represents
+ * a state that will be excluded from being treated as a fatal disconnection. The expected format is a series
+ * of SQL State codes separated by commas, with no spaces between them (e.g., "08003,08004").
+ *
+ * @since 2.13.0
+ */
+ private static final String PROP_DISCONNECTION_IGNORE_SQL_CODES = "disconnectionIgnoreSqlCodes";
+
+
/*
* Block with obsolete properties from DBCP 1.x. Warn users that these are ignored and they should use the 2.x
* properties.
@@ -149,8 +161,8 @@ public class BasicDataSourceFactory implements ObjectFactory {
PROP_CLEAR_STATEMENT_POOL_ON_RETURN,
PROP_MAX_OPEN_PREPARED_STATEMENTS, PROP_CONNECTION_PROPERTIES, PROP_MAX_CONN_LIFETIME_MILLIS,
PROP_LOG_EXPIRED_CONNECTIONS, PROP_ROLLBACK_ON_RETURN, PROP_ENABLE_AUTO_COMMIT_ON_RETURN,
- PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_JMX_NAME,
- PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME);
+ PROP_DEFAULT_QUERY_TIMEOUT, PROP_FAST_FAIL_VALIDATION, PROP_DISCONNECTION_SQL_CODES, PROP_DISCONNECTION_IGNORE_SQL_CODES,
+ PROP_JMX_NAME, PROP_REGISTER_CONNECTION_MBEAN, PROP_CONNECTION_FACTORY_CLASS_NAME);
/**
* Obsolete properties from DBCP 1.x. with warning strings suggesting new properties. LinkedHashMap will guarantee
@@ -227,17 +239,23 @@ public static BasicDataSource createDataSource(final Properties properties) thro
getOptional(properties, PROP_DEFAULT_TRANSACTION_ISOLATION).ifPresent(value -> {
value = value.toUpperCase(Locale.ROOT);
int level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION;
- if ("NONE".equals(value)) {
+ switch (value) {
+ case "NONE":
level = Connection.TRANSACTION_NONE;
- } else if ("READ_COMMITTED".equals(value)) {
+ break;
+ case "READ_COMMITTED":
level = Connection.TRANSACTION_READ_COMMITTED;
- } else if ("READ_UNCOMMITTED".equals(value)) {
+ break;
+ case "READ_UNCOMMITTED":
level = Connection.TRANSACTION_READ_UNCOMMITTED;
- } else if ("REPEATABLE_READ".equals(value)) {
+ break;
+ case "REPEATABLE_READ":
level = Connection.TRANSACTION_REPEATABLE_READ;
- } else if ("SERIALIZABLE".equals(value)) {
+ break;
+ case "SERIALIZABLE":
level = Connection.TRANSACTION_SERIALIZABLE;
- } else {
+ break;
+ default:
try {
level = Integer.parseInt(value);
} catch (final NumberFormatException e) {
@@ -246,6 +264,7 @@ public static BasicDataSource createDataSource(final Properties properties) thro
System.err.println("using default value of database driver");
level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION;
}
+ break;
}
dataSource.setDefaultTransactionIsolation(level);
});
@@ -302,6 +321,7 @@ public static BasicDataSource createDataSource(final Properties properties) thro
acceptDurationOfSeconds(properties, PROP_DEFAULT_QUERY_TIMEOUT, dataSource::setDefaultQueryTimeout);
acceptBoolean(properties, PROP_FAST_FAIL_VALIDATION, dataSource::setFastFailValidation);
getOptional(properties, PROP_DISCONNECTION_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionSqlCodes(parseList(v, ',')));
+ getOptional(properties, PROP_DISCONNECTION_IGNORE_SQL_CODES).ifPresent(v -> dataSource.setDisconnectionIgnoreSqlCodes(parseList(v, ',')));
acceptString(properties, PROP_CONNECTION_FACTORY_CLASS_NAME, dataSource::setConnectionFactoryClassName);
// DBCP-215
diff --git a/src/main/java/org/apache/commons/dbcp2/Constants.java b/src/main/java/org/apache/commons/dbcp2/Constants.java
index 26bf3df1a1..7094d62498 100644
--- a/src/main/java/org/apache/commons/dbcp2/Constants.java
+++ b/src/main/java/org/apache/commons/dbcp2/Constants.java
@@ -23,13 +23,29 @@
*/
public class Constants {
+ /**
+ * Constant used to build JMX strings.
+ */
public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool=";
+
+ /**
+ * Constant used to build JMX strings.
+ */
public static final String JMX_CONNECTION_POOL_PREFIX = "connections";
- public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX
- + ",connection=";
+ /**
+ * Constant used to build JMX strings.
+ */
+ public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX + ",connection=";
+ /**
+ * Constant used to build JMX strings.
+ */
public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT;
+
+ /**
+ * Constant used to build JMX strings.
+ */
public static final String JMX_STATEMENT_POOL_PREFIX = ",statementpool=statements";
/**
diff --git a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
index d3208c20f5..c28bd1f616 100644
--- a/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
+++ b/src/main/java/org/apache/commons/dbcp2/DataSourceMXBean.java
@@ -85,6 +85,16 @@ default String getDefaultSchema() {
*/
int getDefaultTransactionIsolation();
+ /**
+ * See {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}.
+ *
+ * @return {@link BasicDataSource#getDisconnectionIgnoreSqlCodesAsArray()}.
+ * @since 2.13.0
+ */
+ default String[] getDisconnectionIgnoreSqlCodesAsArray() {
+ return Utils.EMPTY_STRING_ARRAY;
+ }
+
/**
* See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}.
*
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
index 9231246a4d..996d31f2b4 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java
@@ -95,6 +95,9 @@ public void abort(final Executor executor) throws SQLException {
}
}
+ /**
+ * Marks this instance as used and delegates to a wrapped {@link DelegatingConnection#activate()}.
+ */
protected void activate() {
closed = false;
setLastUsed();
@@ -103,6 +106,11 @@ protected void activate() {
}
}
+ /**
+ * Throws a SQLException if this connection is not open.
+ *
+ * @throws SQLException Thrown if this connection is not open.
+ */
protected void checkOpen() throws SQLException {
if (closed) {
if (null != connection) {
@@ -317,7 +325,13 @@ public boolean getAutoCommit() throws SQLException {
}
/**
- * Returns the state caching flag.
+ * Gets whether to cache properties. The cached properties are:
+ *
+ *
auto-commit
+ *
catalog
+ *
schema
+ *
read-only
+ *
*
* @return the state caching flag
*/
@@ -578,6 +592,11 @@ public boolean isClosed() throws SQLException {
return closed || connection == null || connection.isClosed();
}
+ /**
+ * Tests the raw internal closed state.
+ *
+ * @return the raw internal closed state.
+ */
protected boolean isClosedInternal() {
return closed;
}
@@ -649,6 +668,11 @@ public String nativeSQL(final String sql) throws SQLException {
}
}
+ /**
+ * Clears the list of objects being traced by this object.
+ *
+ * @throws SQLException Thrown if not all traced objects were closed.
+ */
protected void passivate() throws SQLException {
// The JDBC specification requires that a Connection close any open
// Statements when it is closed.
@@ -826,10 +850,15 @@ public void setAutoCommit(final boolean autoCommit) throws SQLException {
}
/**
- * Sets the state caching flag.
+ * Sets whether to cache properties. The cached properties are:
+ *
+ *
auto-commit
+ *
catalog
+ *
schema
+ *
read-only
+ *
*
- * @param cacheState
- * The new value for the state caching flag
+ * @param cacheState The new value for the state caching flag
*/
public void setCacheState(final boolean cacheState) {
this.cacheState = cacheState;
@@ -873,6 +902,11 @@ public void setClientInfo(final String name, final String value) throws SQLClien
}
}
+ /**
+ * Sets the raw internal closed state.
+ *
+ * @param closed the raw internal closed state.
+ */
protected void setClosedInternal(final boolean closed) {
this.closed = closed;
}
@@ -974,7 +1008,7 @@ public void setSchema(final String schema) throws SQLException {
try {
Jdbc41Bridge.setSchema(connection, schema);
if (cacheState) {
- cachedSchema = connection.getSchema();
+ cachedSchema = Jdbc41Bridge.getSchema(connection);
}
} catch (final SQLException e) {
cachedSchema = null;
diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java b/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java
index ccbc52bbac..d77ab697de 100644
--- a/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java
+++ b/src/main/java/org/apache/commons/dbcp2/DelegatingDatabaseMetaData.java
@@ -22,14 +22,15 @@
import java.sql.RowIdLifetime;
import java.sql.SQLException;
import java.util.Objects;
+import java.util.concurrent.Callable;
/**
*
* A base delegating implementation of {@link DatabaseMetaData}.
*
*
- * Methods that create {@link ResultSet} objects are wrapped to create {@link DelegatingResultSet} objects and the
- * remaining methods simply call the corresponding method on the "delegate" provided in the constructor.
+ * Methods that create {@link ResultSet} objects are wrapped to create {@link DelegatingResultSet} objects and the remaining methods simply call the
+ * corresponding method on the "delegate" provided in the constructor.
*
*
* @since 2.0
@@ -45,190 +46,115 @@ public class DelegatingDatabaseMetaData implements DatabaseMetaData {
/**
* Constructs a new instance for the given delegating connection and database meta data.
*
- * @param connection
- * the delegating connection
- * @param databaseMetaData
- * the database meta data
+ * @param connection the delegating connection
+ * @param databaseMetaData the database meta data
*/
- public DelegatingDatabaseMetaData(final DelegatingConnection> connection,
- final DatabaseMetaData databaseMetaData) {
+ public DelegatingDatabaseMetaData(final DelegatingConnection> connection, final DatabaseMetaData databaseMetaData) {
this.connection = Objects.requireNonNull(connection, "connection");
this.databaseMetaData = Objects.requireNonNull(databaseMetaData, "databaseMetaData");
}
@Override
public boolean allProceduresAreCallable() throws SQLException {
- try {
- return databaseMetaData.allProceduresAreCallable();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::allProceduresAreCallable);
}
@Override
public boolean allTablesAreSelectable() throws SQLException {
- try {
- return databaseMetaData.allTablesAreSelectable();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::allTablesAreSelectable);
}
@Override
public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
- try {
- return databaseMetaData.autoCommitFailureClosesAllResultSets();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::autoCommitFailureClosesAllResultSets);
}
@Override
public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
- try {
- return databaseMetaData.dataDefinitionCausesTransactionCommit();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::dataDefinitionCausesTransactionCommit);
}
@Override
public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
- try {
- return databaseMetaData.dataDefinitionIgnoredInTransactions();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::dataDefinitionIgnoredInTransactions);
}
@Override
public boolean deletesAreDetected(final int type) throws SQLException {
- try {
- return databaseMetaData.deletesAreDetected(type);
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(() -> databaseMetaData.deletesAreDetected(type));
}
@Override
public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
- try {
- return databaseMetaData.doesMaxRowSizeIncludeBlobs();
- } catch (final SQLException e) {
- handleException(e);
- return false;
- }
+ return getB(databaseMetaData::doesMaxRowSizeIncludeBlobs);
}
@Override
public boolean generatedKeyAlwaysReturned() throws SQLException {
connection.checkOpen();
+ return getB(() -> Jdbc41Bridge.generatedKeyAlwaysReturned(databaseMetaData));
+ }
+
+ private T get(final Callable s) throws SQLException {
+ return get(s, null);
+ }
+
+ private T get(final Callable s, final T defaultValue) throws SQLException {
try {
- return Jdbc41Bridge.generatedKeyAlwaysReturned(databaseMetaData);
- } catch (final SQLException e) {
- handleException(e);
- return false;
+ return s.call();
+ } catch (final Exception e) {
+ if (e instanceof SQLException) {
+ handleException((SQLException) e);
+ }
+ return defaultValue;
}
}
@Override
- public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern,
- final String attributeNamePattern) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern)
+ throws SQLException {
+ return getRS(() -> databaseMetaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern));
+ }
+
+ private boolean getB(final Callable s) throws SQLException {
+ return get(s, false);
}
@Override
- public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table,
- final int scope, final boolean nullable) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable)
+ throws SQLException {
+ return getRS(() -> databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable));
}
@Override
public ResultSet getCatalogs() throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCatalogs());
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return getRS(databaseMetaData::getCatalogs);
}
@Override
public String getCatalogSeparator() throws SQLException {
- try {
- return databaseMetaData.getCatalogSeparator();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getCatalogSeparator);
}
@Override
public String getCatalogTerm() throws SQLException {
- try {
- return databaseMetaData.getCatalogTerm();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getCatalogTerm);
}
@Override
public ResultSet getClientInfoProperties() throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getClientInfoProperties());
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return getRS(databaseMetaData::getClientInfoProperties);
}
@Override
- public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table,
- final String columnNamePattern) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException {
+ return getRS(() -> databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern));
}
@Override
- public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern,
- final String columnNamePattern) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern)
+ throws SQLException {
+ return getRS(() -> databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern));
}
@Override
@@ -237,66 +163,34 @@ public Connection getConnection() throws SQLException {
}
@Override
- public ResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable,
- final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getCrossReference(parentCatalog,
- parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, final String foreignCatalog,
+ final String foreignSchema, final String foreignTable) throws SQLException {
+ return getRS(() -> databaseMetaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable));
}
@Override
public int getDatabaseMajorVersion() throws SQLException {
- try {
- return databaseMetaData.getDatabaseMajorVersion();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
+ return getI(databaseMetaData::getDatabaseMajorVersion);
}
@Override
public int getDatabaseMinorVersion() throws SQLException {
- try {
- return databaseMetaData.getDatabaseMinorVersion();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
+ return getI(databaseMetaData::getDatabaseMinorVersion);
}
@Override
public String getDatabaseProductName() throws SQLException {
- try {
- return databaseMetaData.getDatabaseProductName();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getDatabaseProductName);
}
@Override
public String getDatabaseProductVersion() throws SQLException {
- try {
- return databaseMetaData.getDatabaseProductVersion();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getDatabaseProductVersion);
}
@Override
public int getDefaultTransactionIsolation() throws SQLException {
- try {
- return databaseMetaData.getDefaultTransactionIsolation();
- } catch (final SQLException e) {
- handleException(e);
- return 0;
- }
+ return getI(databaseMetaData::getDefaultTransactionIsolation);
}
/**
@@ -320,119 +214,63 @@ public int getDriverMinorVersion() {
@Override
public String getDriverName() throws SQLException {
- try {
- return databaseMetaData.getDriverName();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getDriverName);
}
@Override
public String getDriverVersion() throws SQLException {
- try {
- return databaseMetaData.getDriverVersion();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getDriverVersion);
}
@Override
- public ResultSet getExportedKeys(final String catalog, final String schema, final String table)
- throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getExportedKeys(catalog, schema, table));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getExportedKeys(final String catalog, final String schema, final String table) throws SQLException {
+ return getRS(() -> databaseMetaData.getExportedKeys(catalog, schema, table));
}
@Override
public String getExtraNameCharacters() throws SQLException {
- try {
- return databaseMetaData.getExtraNameCharacters();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getExtraNameCharacters);
}
@Override
- public ResultSet getFunctionColumns(final String catalog, final String schemaPattern,
- final String functionNamePattern, final String columnNamePattern) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection, databaseMetaData.getFunctionColumns(catalog,
- schemaPattern, functionNamePattern, columnNamePattern));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern)
+ throws SQLException {
+ return getRS(() -> databaseMetaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern));
}
@Override
- public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern)
- throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException {
+ return getRS(() -> databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern));
+ }
+
+ private int getI(final Callable s) throws SQLException {
+ return get(s, 0);
}
@Override
public String getIdentifierQuoteString() throws SQLException {
- try {
- return databaseMetaData.getIdentifierQuoteString();
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ return get(databaseMetaData::getIdentifierQuoteString);
}
@Override
- public ResultSet getImportedKeys(final String catalog, final String schema, final String table)
- throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getImportedKeys(catalog, schema, table));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getImportedKeys(final String catalog, final String schema, final String table) throws SQLException {
+ return getRS(() -> databaseMetaData.getImportedKeys(catalog, schema, table));
}
@Override
- public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique,
- final boolean approximate) throws SQLException {
- connection.checkOpen();
- try {
- return DelegatingResultSet.wrapResultSet(connection,
- databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate));
- } catch (final SQLException e) {
- handleException(e);
- throw new AssertionError();
- }
+ public ResultSet getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate)
+ throws SQLException {
+ return getRS(() -> databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate));
}
/**
- * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively
- * invokes this method on my delegate.
+ * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively invokes this method on my delegate.
*
- * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when
- * no non-{@code DelegatingResultSet} delegate can be found by traversing this chain.
+ * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when no non-{@code DelegatingResultSet}
+ * delegate can be found by traversing this chain.
*
*
- * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain
- * a "genuine" {@link ResultSet}.
+ * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain a "genuine" {@link ResultSet}.
*
*
* @param e SQLException to be examined
@@ -267,8 +301,11 @@ boolean isDisconnectionSqlException(final SQLException e) {
boolean fatalException = false;
final String sqlState = e.getSQLState();
if (sqlState != null) {
+ if (disconnectionIgnoreSqlCodes != null && disconnectionIgnoreSqlCodes.contains(sqlState)) {
+ return false;
+ }
fatalException = disconnectionSqlCodes == null
- ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.getDisconnectionSqlCodes().contains(sqlState)
+ ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.isDisconnectionSqlCode(sqlState)
: disconnectionSqlCodes.contains(sqlState);
}
return fatalException;
@@ -319,7 +356,7 @@ protected void passivate() throws SQLException {
}
/**
- * Actually close my underlying {@link Connection}.
+ * Closes the underlying {@link Connection}.
*/
@Override
public void reallyClose() throws SQLException {
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
index 923032f0d2..0b7cdf6868 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionFactory.java
@@ -64,6 +64,8 @@ public class PoolableConnectionFactory implements PooledObjectFactory disconnectionSqlCodes;
+ private Collection disconnectionIgnoreSqlCodes;
+
private boolean fastFailValidation = true;
private volatile ObjectPool pool;
@@ -147,14 +149,14 @@ public void destroyObject(final PooledObject p) throws SQLEx
@Override
public void destroyObject(final PooledObject p, final DestroyMode mode) throws SQLException {
if (mode == DestroyMode.ABANDONED) {
- p.getObject().getInnermostDelegate().abort(Runnable::run);
+ Jdbc41Bridge.abort(p.getObject().getInnermostDelegate(), Runnable::run);
} else {
p.getObject().reallyClose();
}
}
/**
- * Gets the cache state.
+ * Gets the cache state to propagate in {@link #makeObject()}.
*
* @return The cache state.
* @since 2.6.0.
@@ -173,11 +175,18 @@ public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
+ /**
+ * Gets how many connections were created in {@link #makeObject()}.
+ *
+ * @return the connection count.
+ */
protected AtomicLong getConnectionIndex() {
return connectionIndex;
}
/**
+ * Gets the collection of initialization SQL statements.
+ *
* @return The collection of initialization SQL statements.
* @since 2.6.0
*/
@@ -186,7 +195,9 @@ public Collection getConnectionInitSqls() {
}
/**
- * @return The data source JMX ObjectName
+ * Gets data source JMX ObjectName.
+ *
+ * @return The data source JMX ObjectName.
* @since 2.6.0.
*/
public ObjectName getDataSourceJmxName() {
@@ -194,7 +205,9 @@ public ObjectName getDataSourceJmxName() {
}
/**
- * @return The data source JMS ObjectName.
+ * Gets the data source JMX ObjectName.
+ *
+ * @return The data source JMX ObjectName.
* @since 2.6.0
*/
public ObjectName getDataSourceJmxObjectName() {
@@ -202,7 +215,9 @@ public ObjectName getDataSourceJmxObjectName() {
}
/**
- * @return Default auto-commit value.
+ * Gets the Default auto-commit value.
+ *
+ * @return The default auto-commit value.
* @since 2.6.0
*/
public Boolean getDefaultAutoCommit() {
@@ -210,7 +225,9 @@ public Boolean getDefaultAutoCommit() {
}
/**
- * @return Default catalog.
+ * Gets the default catalog.
+ *
+ * @return The default catalog.
* @since 2.6.0
*/
public String getDefaultCatalog() {
@@ -218,7 +235,9 @@ public String getDefaultCatalog() {
}
/**
- * @return Default query timeout in seconds.
+ * Gets the default query timeout in seconds.
+ *
+ * @return The default query timeout in seconds.
* @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
*/
@Deprecated
@@ -229,7 +248,7 @@ public Integer getDefaultQueryTimeout() {
/**
* Gets the default query timeout Duration.
*
- * @return Default query timeout Duration.
+ * @return The default query timeout Duration.
* @since 2.10.0
*/
public Duration getDefaultQueryTimeoutDuration() {
@@ -237,7 +256,9 @@ public Duration getDefaultQueryTimeoutDuration() {
}
/**
- * @return Default query timeout in seconds.
+ * Gets the default query timeout in seconds.
+ *
+ * @return The default query timeout in seconds.
* @since 2.6.0
* @deprecated Use {@link #getDefaultQueryTimeoutDuration()}.
*/
@@ -247,7 +268,9 @@ public Integer getDefaultQueryTimeoutSeconds() {
}
/**
- * @return Default read-only-value.
+ * Gets the default read-only-value.
+ *
+ * @return The default read-only-value.
* @since 2.6.0
*/
public Boolean getDefaultReadOnly() {
@@ -255,7 +278,9 @@ public Boolean getDefaultReadOnly() {
}
/**
- * @return Default schema.
+ * Gets the default schema.
+ *
+ * @return The default schema.
* @since 2.6.0
*/
public String getDefaultSchema() {
@@ -263,7 +288,9 @@ public String getDefaultSchema() {
}
/**
- * @return Default transaction isolation.
+ * Gets the default transaction isolation.
+ *
+ * @return The default transaction isolation.
* @since 2.6.0
*/
public int getDefaultTransactionIsolation() {
@@ -271,11 +298,26 @@ public int getDefaultTransactionIsolation() {
}
/**
- * SQL_STATE codes considered to signal fatal conditions.
+ * Gets the collection of SQL State codes that are not considered fatal disconnection codes.
+ *
+ * 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.
+ *
+ *
+ * @return a {@link Collection} of SQL State codes that should be ignored for disconnection checks.
+ * @since 2.13.0
+ */
+ public Collection getDisconnectionIgnoreSqlCodes() {
+ return disconnectionIgnoreSqlCodes;
+ }
+
+ /**
+ * Gets SQL State codes considered to signal fatal conditions.
*
* 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
- * {@code true}, whenever connections created by this factory generate exceptions with SQL_STATE codes in this list,
+ * {@code true}, whenever connections created by this factory 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).
*
@@ -283,7 +325,7 @@ public int getDefaultTransactionIsolation() {
* If {@link #isFastFailValidation()} is {@code false} setting this property has no effect.
*
*
- * @return SQL_STATE codes overriding defaults
+ * @return SQL State codes overriding defaults
* @since 2.1
*/
public Collection getDisconnectionSqlCodes() {
@@ -310,9 +352,15 @@ public long getMaxConnLifetimeMillis() {
return maxConnDuration.toMillis();
}
+ /**
+ * Gets the maximum number of open prepared statements.
+ *
+ * @return The maximum number of open prepared statements.
+ */
protected int getMaxOpenPreparedStatements() {
return maxOpenPreparedStatements;
}
+
/**
* Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
*
@@ -321,14 +369,20 @@ protected int getMaxOpenPreparedStatements() {
public synchronized ObjectPool getPool() {
return pool;
}
+
/**
+ * Tests whether to pool statements.
+ *
* @return Whether to pool statements.
* @since 2.6.0.
*/
public boolean getPoolStatements() {
return poolStatements;
}
+
/**
+ * Gets the validation query.
+ *
* @return Validation query.
* @since 2.6.0
*/
@@ -358,6 +412,13 @@ public int getValidationQueryTimeoutSeconds() {
return (int) validationQueryTimeoutDuration.getSeconds();
}
+ /**
+ * Initializes the given connection with the collection of SQL statements set in {@link #setConnectionInitSql(Collection)}.
+ *
+ * @param conn the connection to initialize.
+ * @throws SQLException if a database access error occurs or this method is called on a closed connection.
+ * @see #setConnectionInitSql(Collection)
+ */
protected void initializeConnection(final Connection conn) throws SQLException {
final Collection sqls = connectionInitSqls;
if (conn.isClosed()) {
@@ -373,7 +434,9 @@ protected void initializeConnection(final Connection conn) throws SQLException {
}
/**
- * @return Whether to auto-commit on return.
+ * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}.
+ *
+ * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}.
* @since 2.6.0
*/
public boolean isAutoCommitOnReturn() {
@@ -381,7 +444,9 @@ public boolean isAutoCommitOnReturn() {
}
/**
- * @return Whether to auto-commit on return.
+ * Tests whether to set auto-commit on {@link #passivateObject(PooledObject)}.
+ *
+ * @return Whether to set auto-commit on {@link #passivateObject(PooledObject)}.
* @deprecated Use {@link #isAutoCommitOnReturn()}.
*/
@Deprecated
@@ -391,7 +456,7 @@ public boolean isEnableAutoCommitOnReturn() {
/**
* True means that validation will fail immediately for connections that have previously thrown SQLExceptions with
- * SQL_STATE indicating fatal disconnection errors.
+ * SQL State indicating fatal disconnection errors.
*
* @return true if connections created by this factory will fast fail validation.
* @see #setDisconnectionSqlCodes(Collection)
@@ -403,6 +468,8 @@ public boolean isFastFailValidation() {
}
/**
+ * Tests whether to rollback on return.
+ *
* @return Whether to rollback on return.
*/
public boolean isRollbackOnReturn() {
@@ -464,7 +531,8 @@ public PooledObject makeObject() throws SQLException {
}
}
- final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName, disconnectionSqlCodes, fastFailValidation);
+ final PoolableConnection pc = new PoolableConnection(conn, pool, connJmxName,
+ disconnectionSqlCodes, disconnectionIgnoreSqlCodes, fastFailValidation);
pc.setCacheState(cacheState);
return new DefaultPooledObject<>(pc);
@@ -500,10 +568,20 @@ public void passivateObject(final PooledObject p) throws SQL
conn.passivate();
}
+ /**
+ * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}.
+ *
+ * @param autoCommitOnReturn whether to set auto-commit.
+ */
public void setAutoCommitOnReturn(final boolean autoCommitOnReturn) {
this.autoCommitOnReturn = autoCommitOnReturn;
}
+ /**
+ * Sets the cache state to propagate in {@link #makeObject()}.
+ *
+ * @param cacheState the cache state to propagate.
+ */
public void setCacheState(final boolean cacheState) {
this.cacheState = cacheState;
}
@@ -602,18 +680,37 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation
}
/**
+ * 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(final Collection disconnectionIgnoreSqlCodes) {
+ Utils.checkSqlCodes(disconnectionIgnoreSqlCodes, this.disconnectionSqlCodes);
+ this.disconnectionIgnoreSqlCodes = disconnectionIgnoreSqlCodes;
+ }
+
+ /**
+ * Sets the disconnection SQL codes.
+ *
* @param disconnectionSqlCodes
* The disconnection SQL codes.
* @see #getDisconnectionSqlCodes()
* @since 2.1
+ * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}.
*/
public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) {
+ Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes);
this.disconnectionSqlCodes = disconnectionSqlCodes;
}
/**
- * @param autoCommitOnReturn Whether to auto-commit on return.
- * @deprecated Use {@link #setAutoCommitOnReturn(boolean)}.
+ * Sets whether to set auto-commit on {@link #passivateObject(PooledObject)}.
+ *
+ * @param autoCommitOnReturn whether to set auto-commit.
*/
@Deprecated
public void setEnableAutoCommitOnReturn(final boolean autoCommitOnReturn) {
@@ -690,10 +787,20 @@ public synchronized void setPool(final ObjectPool pool) {
this.pool = pool;
}
+ /**
+ * Sets whether to pool statements.
+ *
+ * @param poolStatements whether to pool statements.
+ */
public void setPoolStatements(final boolean poolStatements) {
this.poolStatements = poolStatements;
}
+ /**
+ * Sets whether to rollback on return.
+ *
+ * @param rollbackOnReturn whether to rollback on return.
+ */
public void setRollbackOnReturn(final boolean rollbackOnReturn) {
this.rollbackOnReturn = rollbackOnReturn;
}
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java
index b23365080e..a31b3f3716 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableConnectionMXBean.java
@@ -16,6 +16,7 @@
*/
package org.apache.commons.dbcp2;
+import java.sql.Connection;
import java.sql.SQLException;
/**
@@ -25,43 +26,166 @@
*/
public interface PoolableConnectionMXBean {
+ /**
+ * Clears the cached state. Call when you know that the underlying connection may have been accessed directly.
+ */
void clearCachedState();
+ /**
+ * See {@link Connection#clearWarnings()}.
+ *
+ * @throws SQLException See {@link Connection#clearWarnings()}.
+ */
void clearWarnings() throws SQLException;
+ /**
+ * Returns this instance to my containing pool.
+ *
+ * @throws SQLException Throw if this instance cannot be returned.
+ */
void close() throws SQLException;
+ /**
+ * See {@link Connection#getAutoCommit()}.
+ *
+ * @return See {@link Connection#getAutoCommit()}.
+ * @throws SQLException See {@link Connection#getAutoCommit()}.
+ */
boolean getAutoCommit() throws SQLException;
+ /**
+ * Gets whether to cache properties. The cached properties are:
+ *
+ *
auto-commit
+ *
catalog
+ *
schema
+ *
read-only
+ *
+ *
+ * @return The value for the state caching flag.
+ */
boolean getCacheState();
+ /**
+ * See {@link Connection#getCatalog()}.
+ *
+ * @return See {@link Connection#getCatalog()}.
+ * @throws SQLException See {@link Connection#getCatalog()}.
+ */
String getCatalog() throws SQLException;
+ /**
+ * See {@link Connection#getHoldability()}.
+ *
+ * @return See {@link Connection#getHoldability()}.
+ * @throws SQLException See {@link Connection#getHoldability()}.
+ */
int getHoldability() throws SQLException;
+ /**
+ * See {@link Connection#getSchema()}.
+ *
+ * @return See {@link Connection#getSchema()}.
+ * @throws SQLException See {@link Connection#getSchema()}.
+ */
String getSchema() throws SQLException;
+ /**
+ * Gets the value of the {@link Object#toString()} method via a bean getter, so it can be read as a property via JMX.
+ *
+ * @return the value of the {@link Object#toString()}.
+ */
String getToString();
+ /**
+ * See {@link Connection#getTransactionIsolation()}.
+ *
+ * @return See {@link Connection#getTransactionIsolation()}.
+ * @throws SQLException See {@link Connection#getTransactionIsolation()}.
+ */
int getTransactionIsolation() throws SQLException;
+ /**
+ * See {@link Connection#isClosed()}.
+ *
+ * @return See {@link Connection#isClosed()}.
+ * @throws SQLException See {@link Connection#isClosed()}.
+ */
boolean isClosed() throws SQLException;
+ /**
+ * See {@link Connection#isReadOnly()}.
+ *
+ * @return See {@link Connection#isReadOnly()}.
+ * @throws SQLException See {@link Connection#isReadOnly()}.
+ */
boolean isReadOnly() throws SQLException;
+ /**
+ * Closes the underlying {@link Connection}.
+ *
+ * @throws SQLException Thrown if the connection can be closed.
+ */
void reallyClose() throws SQLException;
+ /**
+ * See {@link Connection#setAutoCommit(boolean)}.
+ *
+ * @param autoCommit See {@link Connection#setAutoCommit(boolean)}.
+ * @throws SQLException See {@link Connection#setAutoCommit(boolean)}.
+ */
void setAutoCommit(boolean autoCommit) throws SQLException;
+ /**
+ * Sets whether to cache properties. The cached properties are:
+ *
+ *
auto-commit
+ *
catalog
+ *
schema
+ *
read-only
+ *
+ *
+ * @param cacheState The new value for the state caching flag
+ */
void setCacheState(boolean cacheState);
+ /**
+ * See {@link Connection#setCatalog(String)}.
+ *
+ * @param catalog See {@link Connection#setCatalog(String)}.
+ * @throws SQLException See {@link Connection#setCatalog(String)}.
+ */
void setCatalog(String catalog) throws SQLException;
+ /**
+ * See {@link Connection#setHoldability(int)}.
+ *
+ * @param holdability {@link Connection#setHoldability(int)}.
+ * @throws SQLException See {@link Connection#setHoldability(int)}.
+ */
void setHoldability(int holdability) throws SQLException;
+ /**
+ * See {@link Connection#setReadOnly(boolean)}.
+ *
+ * @param readOnly See {@link Connection#setReadOnly(boolean)}.
+ * @throws SQLException See {@link Connection#setReadOnly(boolean)}.
+ */
void setReadOnly(boolean readOnly) throws SQLException;
+ /**
+ * See {@link Connection#setSchema(String)}.
+ *
+ * @param schema See {@link Connection#setSchema(String)}.
+ * @throws SQLException See {@link Connection#setSchema(String)}.
+ */
void setSchema(String schema) throws SQLException;
+ /**
+ * See {@link Connection#setTransactionIsolation(int)}.
+ *
+ * @param level See {@link Connection#setTransactionIsolation(int)}.
+ * @throws SQLException See {@link Connection#setTransactionIsolation(int)}.
+ */
void setTransactionIsolation(int level) throws SQLException;
}
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
index b4ce3eb619..a5fe2b34d5 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
@@ -122,7 +122,11 @@ public synchronized void close() throws SQLException {
}
} finally {
try {
- getDelegateInternal().close();
+ @SuppressWarnings("resource")
+ final Connection delegateInternal = getDelegateInternal();
+ if (delegateInternal != null) {
+ delegateInternal.close();
+ }
} finally {
setClosedInternal(true);
}
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java b/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
index 1f7c0aa000..fe019b959d 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolingDataSource.java
@@ -164,7 +164,6 @@ public Connection getConnection(final String userName, final String password) th
throw new UnsupportedOperationException();
}
- // --- DataSource methods -----------------------------------------
/**
* Throws {@link UnsupportedOperationException}.
@@ -193,6 +192,11 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
+ /**
+ * Gets the backing object pool.
+ *
+ * @return the backing object pool.
+ */
protected ObjectPool getPool() {
return pool;
}
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java b/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java
index f553740fb7..d1aacd288c 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolingDriver.java
@@ -87,14 +87,24 @@ public Connection getInnermostDelegate() {
/** The map of registered pools. */
protected static final HashMap> pools = new HashMap<>();
- /** My URL prefix */
+ /**
+ * The Apache Commons connection string prefix {@value}.
+ */
public static final String URL_PREFIX = "jdbc:apache:commons:dbcp:";
+ /**
+ * The String length of {@link #URL_PREFIX}.
+ */
protected static final int URL_PREFIX_LEN = URL_PREFIX.length();
- // version numbers
+ /**
+ * Major version number.
+ */
protected static final int MAJOR_VERSION = 1;
+ /**
+ * Minor version number.
+ */
protected static final int MINOR_VERSION = 0;
/** Controls access to the underlying connection */
@@ -147,7 +157,6 @@ public synchronized void closePool(final String name) throws SQLException {
public Connection connect(final String url, final Properties info) throws SQLException {
if (acceptsURL(url)) {
final ObjectPool extends Connection> pool = getConnectionPool(url.substring(URL_PREFIX_LEN));
-
try {
final Connection conn = pool.borrowObject();
if (conn == null) {
diff --git a/src/main/java/org/apache/commons/dbcp2/Utils.java b/src/main/java/org/apache/commons/dbcp2/Utils.java
index 8652cae12e..3020f89339 100644
--- a/src/main/java/org/apache/commons/dbcp2/Utils.java
+++ b/src/main/java/org/apache/commons/dbcp2/Utils.java
@@ -49,7 +49,9 @@ public final class Utils {
@Deprecated
public static final boolean IS_SECURITY_ENABLED = isSecurityEnabled();
- /** Any SQL_STATE starting with this value is considered a fatal disconnect */
+ /**
+ * Any SQL State starting with this value is considered a fatal disconnect.
+ */
public static final String DISCONNECTION_SQL_CODE_PREFIX = "08";
/**
@@ -80,6 +82,27 @@ public final class Utils {
DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error
}
+ /**
+ * Checks for conflicts between two collections.
+ *
+ * If any overlap is found between the two provided collections, an {@link IllegalArgumentException} is thrown.
+ *
+ *
+ * @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 codes1, final Collection codes2) {
+ if (codes1 != null && codes2 != null) {
+ final Set 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.
*
@@ -179,7 +202,7 @@ public static void closeQuietly(final Statement statement) {
*
JZ0C0 (Sybase disconnect error)
*
JZ0C1 (Sybase disconnect error)
*
- * @return SQL codes of fatal connection errors.
+ * @return A copy SQL codes of fatal connection errors.
* @since 2.10.0
*/
public static Set getDisconnectionSqlCodes() {
@@ -212,6 +235,17 @@ public static String getMessage(final String key, final Object... args) {
return mf.format(args, new StringBuffer(), null).toString();
}
+ /**
+ * Checks if the given SQL state corresponds to a fatal connection error.
+ *
+ * @param sqlState the SQL state to check.
+ * @return true if the SQL state is a fatal connection error, false otherwise.
+ * @since 2.13.0
+ */
+ static boolean isDisconnectionSqlCode(final String sqlState) {
+ return DISCONNECTION_SQL_CODES.contains(sqlState);
+ }
+
static boolean isEmpty(final Collection> collection) {
return collection == null || collection.isEmpty();
}
@@ -240,6 +274,13 @@ public static String toString(final char[] value) {
return value == null ? null : String.valueOf(value);
}
+ /**
+ * Throws a LifetimeExceededException if the given pooled object's lifetime has exceeded a maximum duration.
+ *
+ * @param p The pooled object to test.
+ * @param maxDuration The maximum lifetime.
+ * @throws LifetimeExceededException Thrown if the given pooled object's lifetime has exceeded a maximum duration.
+ */
public static void validateLifetime(final PooledObject> p, final Duration maxDuration) throws LifetimeExceededException {
if (maxDuration.compareTo(Duration.ZERO) > 0) {
final Duration lifetimeDuration = Duration.between(p.getCreateInstant(), Instant.now());
diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
index 481acaf355..6281592127 100644
--- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
+++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/DriverAdapterCPDS.java
@@ -700,7 +700,7 @@ public void setMinEvictableIdleTimeMillis(final int minEvictableIdleTimeMillis)
*
* When a negative value is supplied,
* {@code ceil({@link BasicDataSource#getNumIdle})/abs({@link #getNumTestsPerEvictionRun})} tests will be run.
- * I.e., when the value is -n, roughly one nth of the idle objects will be tested per run.
+ * I.e., when the value is -n, roughly one nth of the idle objects will be tested per run.
*
*
* @param numTestsPerEvictionRun number of statements to examine per run
diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java
index 2fc938ed5b..9bb326f316 100644
--- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java
+++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PStmtKeyCPDS.java
@@ -16,10 +16,12 @@
*/
package org.apache.commons.dbcp2.cpdsadapter;
+import java.sql.PreparedStatement;
+
import org.apache.commons.dbcp2.PStmtKey;
/**
- * A key uniquely identifying a {@link java.sql.PreparedStatement PreparedStatement}.
+ * A key uniquely identifying a {@link PreparedStatement}.
*
* @since 2.0
* @deprecated Use {@link PStmtKey}.
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
index 9ec3451b27..4fd5ff293e 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSource.java
@@ -1109,18 +1109,15 @@ public void setLogWriter(final PrintWriter logWriter) {
/**
*
- * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an
- * infinite lifetime.
+ * Sets the maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime.
*
*
- * 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * 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: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()},
+ * {@link #getLogWriter()}.
*
*
- * @param maxConnLifetimeMillis
- * The maximum permitted lifetime of a connection. A value of zero or less indicates an
- * infinite lifetime.
+ * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection. A value of zero or less indicates an infinite lifetime.
* @since 2.9.0
*/
public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) {
@@ -1129,18 +1126,15 @@ public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) {
/**
*
- * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
- * infinite lifetime.
+ * Sets the maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime.
*
*
- * 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * 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: {@link #getConnection()}, {@link #setLogWriter(PrintWriter)}, {@link #setLoginTimeout(Duration)}, {@link #getLoginTimeoutDuration()},
+ * {@link #getLogWriter()}.
*
*
- * @param maxConnLifetimeMillis
- * The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an
- * infinite lifetime.
+ * @param maxConnLifetimeMillis The maximum permitted lifetime of a connection in milliseconds. A value of zero or less indicates an infinite lifetime.
* @deprecated Use {@link #setMaxConnLifetime(Duration)}.
*/
@Deprecated
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
index afd5c8f241..a9f8c28082 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/InstanceKeyDataSourceFactory.java
@@ -118,6 +118,10 @@ static void removeInstance(final String key) {
}
}
+ private Boolean booleanValueOf(RefAddr refAddr) {
+ return Boolean.valueOf(toString(refAddr));
+ }
+
/**
* Creates an instance of the subclass and sets any properties contained in the Reference.
*
@@ -146,7 +150,7 @@ public Object getObjectInstance(final Object refObj, final Name name, final Cont
final Reference ref = (Reference) refObj;
if (isCorrectClass(ref.getClassName())) {
final RefAddr refAddr = ref.get("instanceKey");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
// object was bound to JNDI via Referenceable API.
obj = INSTANCE_MAP.get(refAddr.getContent());
} else {
@@ -172,6 +176,10 @@ public Object getObjectInstance(final Object refObj, final Name name, final Cont
return obj;
}
+ private boolean hasContent(final RefAddr refAddr) {
+ return refAddr != null && refAddr.getContent() != null;
+ }
+
/**
* Tests if className is the value returned from getClass().getName().toString().
*
@@ -198,143 +206,151 @@ private void setCommonProperties(final Reference ref, final InstanceKeyDataSourc
throws IOException, ClassNotFoundException {
RefAddr refAddr = ref.get("dataSourceName");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDataSourceName(toString(refAddr));
}
refAddr = ref.get("description");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDescription(toString(refAddr));
}
refAddr = ref.get("jndiEnvironment");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
final byte[] serialized = (byte[]) refAddr.getContent();
ikds.setJndiEnvironment((Properties) deserialize(serialized));
}
refAddr = ref.get("loginTimeout");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setLoginTimeout(Duration.ofSeconds(parseInt(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setLoginTimeout(toDurationFromSeconds(refAddr));
}
// Pool properties
refAddr = ref.get("blockWhenExhausted");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultBlockWhenExhausted(parseBoolean(refAddr));
}
refAddr = ref.get("evictionPolicyClassName");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultEvictionPolicyClassName(toString(refAddr));
}
// Pool properties
refAddr = ref.get("lifo");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultLifo(parseBoolean(refAddr));
}
refAddr = ref.get("maxIdlePerKey");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultMaxIdle(parseInt(refAddr));
}
refAddr = ref.get("maxTotalPerKey");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultMaxTotal(parseInt(refAddr));
}
refAddr = ref.get("maxWaitMillis");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultMaxWait(Duration.ofMillis(parseLong(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultMaxWait(toDurationFromMillis(refAddr));
}
refAddr = ref.get("minEvictableIdleTimeMillis");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultMinEvictableIdle(Duration.ofMillis(parseLong(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultMinEvictableIdle(toDurationFromMillis(refAddr));
}
refAddr = ref.get("minIdlePerKey");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultMinIdle(parseInt(refAddr));
}
refAddr = ref.get("numTestsPerEvictionRun");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultNumTestsPerEvictionRun(parseInt(refAddr));
}
refAddr = ref.get("softMinEvictableIdleTimeMillis");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultSoftMinEvictableIdle(Duration.ofMillis(parseLong(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultSoftMinEvictableIdle(toDurationFromMillis(refAddr));
}
refAddr = ref.get("testOnCreate");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultTestOnCreate(parseBoolean(refAddr));
}
refAddr = ref.get("testOnBorrow");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultTestOnBorrow(parseBoolean(refAddr));
}
refAddr = ref.get("testOnReturn");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultTestOnReturn(parseBoolean(refAddr));
}
refAddr = ref.get("testWhileIdle");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultTestWhileIdle(parseBoolean(refAddr));
}
refAddr = ref.get("timeBetweenEvictionRunsMillis");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultDurationBetweenEvictionRuns(Duration.ofMillis(parseLong(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultDurationBetweenEvictionRuns(toDurationFromMillis(refAddr));
}
// Connection factory properties
refAddr = ref.get("validationQuery");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setValidationQuery(toString(refAddr));
}
refAddr = ref.get("validationQueryTimeout");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setValidationQueryTimeout(Duration.ofSeconds(parseInt(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setValidationQueryTimeout(toDurationFromSeconds(refAddr));
}
refAddr = ref.get("rollbackAfterValidation");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setRollbackAfterValidation(parseBoolean(refAddr));
}
refAddr = ref.get("maxConnLifetimeMillis");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setMaxConnLifetime(Duration.ofMillis(parseLong(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setMaxConnLifetime(toDurationFromMillis(refAddr));
}
// Connection properties
refAddr = ref.get("defaultAutoCommit");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultAutoCommit(Boolean.valueOf(toString(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultAutoCommit(booleanValueOf(refAddr));
}
refAddr = ref.get("defaultTransactionIsolation");
- if (refAddr != null && refAddr.getContent() != null) {
+ if (hasContent(refAddr)) {
ikds.setDefaultTransactionIsolation(parseInt(refAddr));
}
refAddr = ref.get("defaultReadOnly");
- if (refAddr != null && refAddr.getContent() != null) {
- ikds.setDefaultReadOnly(Boolean.valueOf(toString(refAddr)));
+ if (hasContent(refAddr)) {
+ ikds.setDefaultReadOnly(booleanValueOf(refAddr));
}
}
+ private Duration toDurationFromMillis(RefAddr refAddr) {
+ return Duration.ofMillis(parseLong(refAddr));
+ }
+
+ private Duration toDurationFromSeconds(RefAddr refAddr) {
+ return Duration.ofSeconds(parseInt(refAddr));
+ }
+
String toString(final RefAddr refAddr) {
return refAddr.getContent().toString();
}
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java
index 3b21c653c7..db7fee5c22 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java
@@ -38,8 +38,7 @@
import org.apache.commons.pool2.impl.DefaultPooledObject;
/**
- * A {@link KeyedPooledObjectFactory} that creates {@link org.apache.commons.dbcp2.PoolableConnection
- * PoolableConnection}s.
+ * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s.
*
* @since 2.0
*/
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
index 85d7491ad0..7d5344ab44 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/PerUserPoolDataSource.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.function.Supplier;
import javax.naming.NamingException;
import javax.naming.Reference;
@@ -35,6 +36,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool2.ObjectPool;
+import org.apache.commons.pool2.impl.EvictionPolicy;
import org.apache.commons.pool2.impl.GenericObjectPool;
/**
@@ -67,23 +69,94 @@ private static HashMap createMap() {
return new HashMap<>();
}
+ /**
+ * Maps user names to a data source property: BlockWhenExhausted.
+ */
private Map perUserBlockWhenExhausted;
+
+ /**
+ * Maps user names to a data source property: EvictionPolicyClassName.
+ */
private Map perUserEvictionPolicyClassName;
+
+ /**
+ * Maps user names to a data source property: Lifo.
+ */
private Map perUserLifo;
+
+ /**
+ * Maps user names to a data source property: MaxIdle.
+ */
private Map perUserMaxIdle;
+
+ /**
+ * Maps user names to a data source property: MaxTotal.
+ */
private Map perUserMaxTotal;
+
+ /**
+ * Maps user names to a data source property: MaxWaitDuration.
+ */
private Map perUserMaxWaitDuration;
+
+ /**
+ * Maps user names to a data source property: MinEvictableIdleDuration.
+ */
private Map perUserMinEvictableIdleDuration;
+
+ /**
+ * Maps user names to a data source property: MinIdle.
+ */
private Map perUserMinIdle;
+
+ /**
+ * Maps user names to a data source property: NumTestsPerEvictionRun.
+ */
private Map perUserNumTestsPerEvictionRun;
+
+ /**
+ * Maps user names to a data source property: SoftMinEvictableIdleDuration.
+ */
private Map perUserSoftMinEvictableIdleDuration;
+
+ /**
+ * Maps user names to a data source property: TestOnCreate.
+ */
private Map perUserTestOnCreate;
+
+ /**
+ * Maps user names to a data source property: TestOnBorrow.
+ */
private Map perUserTestOnBorrow;
+
+ /**
+ * Maps user names to a data source property: TestOnReturn.
+ */
private Map perUserTestOnReturn;
+
+ /**
+ * Maps user names to a data source property: TestWhileIdle.
+ */
private Map perUserTestWhileIdle;
+
+ /**
+ * Maps user names to a data source property: DurationBetweenEvictionRuns.
+ */
private Map perUserDurationBetweenEvictionRuns;
+
+ /**
+ * Maps user names to a data source property: DefaultAutoCommit.
+ */
private Map perUserDefaultAutoCommit;
+
+ /**
+ * Maps user names to a data source property: DefaultTransactionIsolation.
+ */
private Map perUserDefaultTransactionIsolation;
+
+ /**
+ * Maps user names to a data source property: DefaultReadOnly.
+ */
private Map perUserDefaultReadOnly;
/**
@@ -92,7 +165,7 @@ private static HashMap createMap() {
private transient Map managers = createMap();
/**
- * Default no-arg constructor for Serialization.
+ * Constructs a new instance.
*/
public PerUserPoolDataSource() {
}
@@ -103,6 +176,7 @@ public PerUserPoolDataSource() {
* @see org.apache.commons.pool2.ObjectPool#clear()
* @since 2.3.0
*/
+ @SuppressWarnings("resource") // does not allocate a pool
public void clear() {
managers.values().forEach(manager -> {
try {
@@ -140,13 +214,34 @@ private Map convertMap(final Map currentMap,
}
+ /**
+ * Gets the user specific default value in a map for the specified user's pool.
+ *
+ * @param userName The user name key.
+ * @return The user specific value.
+ */
+ private V get(final Map map, final String userName) {
+ return map != null ? map.get(userName) : null;
+ }
+
+ /**
+ * Gets the user specific default value in a map for the specified user's pool.
+ *
+ * @param userName The user name key.
+ * @return The user specific value.
+ */
+ private V get(final Map map, final String userName, final Supplier defaultSupplier) {
+ final V v = get(map, userName);
+ return v != null ? v : defaultSupplier.get();
+ }
+
@Override
protected PooledConnectionManager getConnectionManager(final UserPassKey upKey) {
return managers.get(getPoolKey(upKey.getUserName()));
}
/**
- * Gets the underlying pool but does NOT allocate it.
+ * Gets the underlying pre-allocated pool (does NOT allocate).
*
* @param manager A CPDSConnectionFactory.
* @return the underlying pool.
@@ -208,14 +303,7 @@ public int getNumIdle(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserBlockWhenExhausted(final String userName) {
- Boolean value = null;
- if (perUserBlockWhenExhausted != null) {
- value = perUserBlockWhenExhausted.get(userName);
- }
- if (value == null) {
- return getDefaultBlockWhenExhausted();
- }
- return value;
+ return get(perUserBlockWhenExhausted, userName, this::getDefaultBlockWhenExhausted);
}
/**
@@ -226,11 +314,7 @@ public boolean getPerUserBlockWhenExhausted(final String userName) {
* @return The user specific value.
*/
public Boolean getPerUserDefaultAutoCommit(final String userName) {
- Boolean value = null;
- if (perUserDefaultAutoCommit != null) {
- value = perUserDefaultAutoCommit.get(userName);
- }
- return value;
+ return get(perUserDefaultAutoCommit, userName);
}
/**
@@ -241,11 +325,7 @@ public Boolean getPerUserDefaultAutoCommit(final String userName) {
* @return The user specific value.
*/
public Boolean getPerUserDefaultReadOnly(final String userName) {
- Boolean value = null;
- if (perUserDefaultReadOnly != null) {
- value = perUserDefaultReadOnly.get(userName);
- }
- return value;
+ return get(perUserDefaultReadOnly, userName);
}
/**
@@ -257,11 +337,7 @@ public Boolean getPerUserDefaultReadOnly(final String userName) {
* @return The user specific value.
*/
public Integer getPerUserDefaultTransactionIsolation(final String userName) {
- Integer value = null;
- if (perUserDefaultTransactionIsolation != null) {
- value = perUserDefaultTransactionIsolation.get(userName);
- }
- return value;
+ return get(perUserDefaultTransactionIsolation, userName);
}
/**
@@ -274,33 +350,22 @@ public Integer getPerUserDefaultTransactionIsolation(final String userName) {
* @since 2.10.0
*/
public Duration getPerUserDurationBetweenEvictionRuns(final String userName) {
- Duration value = null;
- if (perUserDurationBetweenEvictionRuns != null) {
- value = perUserDurationBetweenEvictionRuns.get(userName);
- }
- if (value == null) {
- return getDefaultDurationBetweenEvictionRuns();
- }
- return value;
+ return get(perUserDurationBetweenEvictionRuns, userName, this::getDefaultDurationBetweenEvictionRuns);
}
/**
* Gets the user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's
* pool or the default if no user specific value is defined.
+ *
+ * The class must implement {@link EvictionPolicy}.
+ *
*
* @param userName
* The user name key.
* @return The user specific value.
*/
public String getPerUserEvictionPolicyClassName(final String userName) {
- String value = null;
- if (perUserEvictionPolicyClassName != null) {
- value = perUserEvictionPolicyClassName.get(userName);
- }
- if (value == null) {
- return getDefaultEvictionPolicyClassName();
- }
- return value;
+ return get(perUserEvictionPolicyClassName, userName, this::getDefaultEvictionPolicyClassName);
}
/**
@@ -312,14 +377,7 @@ public String getPerUserEvictionPolicyClassName(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserLifo(final String userName) {
- Boolean value = null;
- if (perUserLifo != null) {
- value = perUserLifo.get(userName);
- }
- if (value == null) {
- return getDefaultLifo();
- }
- return value;
+ return get(perUserLifo, userName, this::getDefaultLifo);
}
/**
@@ -331,14 +389,7 @@ public boolean getPerUserLifo(final String userName) {
* @return The user specific value.
*/
public int getPerUserMaxIdle(final String userName) {
- Integer value = null;
- if (perUserMaxIdle != null) {
- value = perUserMaxIdle.get(userName);
- }
- if (value == null) {
- return getDefaultMaxIdle();
- }
- return value;
+ return get(perUserMaxIdle, userName, this::getDefaultMaxIdle);
}
/**
@@ -350,14 +401,7 @@ public int getPerUserMaxIdle(final String userName) {
* @return The user specific value.
*/
public int getPerUserMaxTotal(final String userName) {
- Integer value = null;
- if (perUserMaxTotal != null) {
- value = perUserMaxTotal.get(userName);
- }
- if (value == null) {
- return getDefaultMaxTotal();
- }
- return value;
+ return get(perUserMaxTotal, userName, this::getDefaultMaxTotal);
}
/**
@@ -370,14 +414,7 @@ public int getPerUserMaxTotal(final String userName) {
* @since 2.10.0
*/
public Duration getPerUserMaxWaitDuration(final String userName) {
- Duration value = null;
- if (perUserMaxWaitDuration != null) {
- value = perUserMaxWaitDuration.get(userName);
- }
- if (value == null) {
- return getDefaultMaxWait();
- }
- return value;
+ return get(perUserMaxWaitDuration, userName, this::getDefaultMaxWait);
}
/**
@@ -404,14 +441,7 @@ public long getPerUserMaxWaitMillis(final String userName) {
* @since 2.10.0
*/
public Duration getPerUserMinEvictableIdleDuration(final String userName) {
- Duration value = null;
- if (perUserMinEvictableIdleDuration != null) {
- value = perUserMinEvictableIdleDuration.get(userName);
- }
- if (value == null) {
- return getDefaultMinEvictableIdleDuration();
- }
- return value;
+ return get(perUserMinEvictableIdleDuration, userName, this::getDefaultMinEvictableIdleDuration);
}
/**
@@ -437,14 +467,7 @@ public long getPerUserMinEvictableIdleTimeMillis(final String userName) {
* @return The user specific value.
*/
public int getPerUserMinIdle(final String userName) {
- Integer value = null;
- if (perUserMinIdle != null) {
- value = perUserMinIdle.get(userName);
- }
- if (value == null) {
- return getDefaultMinIdle();
- }
- return value;
+ return get(perUserMinIdle, userName, this::getDefaultMinIdle);
}
/**
@@ -456,14 +479,7 @@ public int getPerUserMinIdle(final String userName) {
* @return The user specific value.
*/
public int getPerUserNumTestsPerEvictionRun(final String userName) {
- Integer value = null;
- if (perUserNumTestsPerEvictionRun != null) {
- value = perUserNumTestsPerEvictionRun.get(userName);
- }
- if (value == null) {
- return getDefaultNumTestsPerEvictionRun();
- }
- return value;
+ return get(perUserNumTestsPerEvictionRun, userName, this::getDefaultNumTestsPerEvictionRun);
}
/**
@@ -476,14 +492,7 @@ public int getPerUserNumTestsPerEvictionRun(final String userName) {
* @since 2.10.0
*/
public Duration getPerUserSoftMinEvictableIdleDuration(final String userName) {
- Duration value = null;
- if (perUserSoftMinEvictableIdleDuration != null) {
- value = perUserSoftMinEvictableIdleDuration.get(userName);
- }
- if (value == null) {
- return getDefaultSoftMinEvictableIdleDuration();
- }
- return value;
+ return get(perUserSoftMinEvictableIdleDuration, userName, this::getDefaultSoftMinEvictableIdleDuration);
}
/**
@@ -509,14 +518,7 @@ public long getPerUserSoftMinEvictableIdleTimeMillis(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserTestOnBorrow(final String userName) {
- Boolean value = null;
- if (perUserTestOnBorrow != null) {
- value = perUserTestOnBorrow.get(userName);
- }
- if (value == null) {
- return getDefaultTestOnBorrow();
- }
- return value;
+ return get(perUserTestOnBorrow, userName, this::getDefaultTestOnBorrow);
}
/**
@@ -528,14 +530,7 @@ public boolean getPerUserTestOnBorrow(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserTestOnCreate(final String userName) {
- Boolean value = null;
- if (perUserTestOnCreate != null) {
- value = perUserTestOnCreate.get(userName);
- }
- if (value == null) {
- return getDefaultTestOnCreate();
- }
- return value;
+ return get(perUserTestOnCreate, userName, this::getDefaultTestOnCreate);
}
/**
@@ -547,14 +542,7 @@ public boolean getPerUserTestOnCreate(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserTestOnReturn(final String userName) {
- Boolean value = null;
- if (perUserTestOnReturn != null) {
- value = perUserTestOnReturn.get(userName);
- }
- if (value == null) {
- return getDefaultTestOnReturn();
- }
- return value;
+ return get(perUserTestOnReturn, userName, this::getDefaultTestOnReturn);
}
/**
@@ -566,14 +554,7 @@ public boolean getPerUserTestOnReturn(final String userName) {
* @return The user specific value.
*/
public boolean getPerUserTestWhileIdle(final String userName) {
- Boolean value = null;
- if (perUserTestWhileIdle != null) {
- value = perUserTestWhileIdle.get(userName);
- }
- if (value == null) {
- return getDefaultTestWhileIdle();
- }
- return value;
+ return get(perUserTestWhileIdle, userName, this::getDefaultTestWhileIdle);
}
/**
@@ -602,10 +583,9 @@ private ObjectPool getPool(final PoolKey poolKey) {
return mgr == null ? null : mgr.getPool();
}
+ @SuppressWarnings("resource") // does not allocate a pool
@Override
- protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password)
- throws SQLException {
-
+ protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userName, final String password) throws SQLException {
final PoolKey key = getPoolKey(userName);
ObjectPool pool;
PooledConnectionManager manager;
@@ -621,7 +601,6 @@ protected PooledConnectionAndInfo getPooledConnectionAndInfo(final String userNa
}
pool = getCPDSConnectionFactoryPool(manager);
}
-
PooledConnectionAndInfo info = null;
try {
info = pool.borrowObject();
@@ -684,14 +663,11 @@ Map put(Map map, final K key, final V value) {
}
/**
- * Supports Serialization interface.
+ * Deserializes an instance from an ObjectInputStream.
*
- * @param in
- * a {@link java.io.ObjectInputStream} value
- * @throws IOException
- * if an error occurs
- * @throws ClassNotFoundException
- * if an error occurs
+ * @param in The source ObjectInputStream.
+ * @throws IOException Any of the usual Input/Output related exceptions.
+ * @throws ClassNotFoundException A class of a serialized object cannot be found.
*/
@SuppressWarnings("resource")
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -707,19 +683,16 @@ private PerUserPoolDataSource readObjectImpl() throws IOException, ClassNotFound
}
}
- private synchronized void registerPool(final String userName, final String password)
- throws NamingException, SQLException {
-
+ private synchronized void registerPool(final String userName, final String password) throws NamingException, SQLException {
final ConnectionPoolDataSource cpds = testCPDS(userName, password);
-
// Set up the factory we will use (passing the pool associates
// the factory with the pool, so we do not have to do so
// explicitly)
final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, getValidationQuery(), getValidationQueryTimeoutDuration(),
- isRollbackAfterValidation(), userName, password);
+ isRollbackAfterValidation(), userName, password);
factory.setMaxConn(getMaxConnDuration());
-
// Create an object pool to contain our PooledConnections
+ @SuppressWarnings("resource")
final GenericObjectPool pool = new GenericObjectPool<>(factory);
factory.setPool(pool);
pool.setBlockWhenExhausted(getPerUserBlockWhenExhausted(userName));
@@ -737,13 +710,13 @@ private synchronized void registerPool(final String userName, final String passw
pool.setTestOnReturn(getPerUserTestOnReturn(userName));
pool.setTestWhileIdle(getPerUserTestWhileIdle(userName));
pool.setDurationBetweenEvictionRuns(getPerUserDurationBetweenEvictionRuns(userName));
-
pool.setSwallowedExceptionListener(new SwallowedExceptionLogger(log));
-
- final PooledConnectionManager old = managers.put(getPoolKey(userName), factory);
- if (old != null) {
+ final PoolKey poolKey = getPoolKey(userName);
+ if (managers.containsKey(poolKey)) {
+ pool.close();
throw new IllegalStateException("Pool already contains an entry for this user/password: " + userName);
}
+ managers.put(poolKey, factory);
}
private Map replaceAll(final Map currentMap, final Map newMap) {
@@ -860,7 +833,9 @@ void setPerUserEvictionPolicyClassName(final Map newMap) {
/**
* Sets a user specific value for {@link GenericObjectPool#getEvictionPolicyClassName()} for the specified user's
* pool.
- *
+ *
+ * The class must implement {@link EvictionPolicy}.
+ *
* @param userName
* The user name key.
* @param value
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java b/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java
index 01d8675a94..31be5411fb 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/PoolKey.java
@@ -20,6 +20,8 @@
import java.util.Objects;
/**
+ * The key type for entries in a {@link PerUserPoolDataSource}.
+ *
* @since 2.0
*/
final class PoolKey implements Serializable {
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java
index 04e066dd54..01deb37744 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java
@@ -30,15 +30,6 @@ final class PooledConnectionAndInfo {
private final UserPassKey userPassKey;
- /**
- * Constructs a new instance.
- *
- * @since 2.4.0
- */
- PooledConnectionAndInfo(final PooledConnection pooledConnection, final char[] userName, final char[] userPassword) {
- this(pooledConnection, new UserPassKey(userName, userPassword));
- }
-
PooledConnectionAndInfo(final PooledConnection pooledConnection, final UserPassKey userPassKey) {
this.pooledConnection = pooledConnection;
this.userPassKey = userPassKey;
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java
index d14ff58362..1de7ccff7c 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSource.java
@@ -27,6 +27,7 @@
import javax.sql.ConnectionPoolDataSource;
import org.apache.commons.pool2.KeyedObjectPool;
+import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
@@ -51,10 +52,19 @@ public class SharedPoolDataSource extends InstanceKeyDataSource {
private static final long serialVersionUID = -1458539734480586454L;
- // Pool properties
+ /**
+ * Max total defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}.
+ */
private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL;
+ /**
+ * Maps user credentials to pooled connection with credentials.
+ */
private transient KeyedObjectPool pool;
+
+ /**
+ * A {@link KeyedPooledObjectFactory} that creates {@link PoolableConnection}s.
+ */
private transient KeyedCPDSConnectionFactory factory;
/**
@@ -89,9 +99,6 @@ public int getMaxTotal() {
return this.maxTotal;
}
- // ----------------------------------------------------------------------
- // Instrumentation Methods
-
/**
* Gets the number of active connections in the pool.
*
@@ -142,14 +149,11 @@ public Reference getReference() throws NamingException {
}
/**
- * Supports Serialization interface.
+ * Deserializes an instance from an ObjectInputStream.
*
- * @param in
- * a {@link java.io.ObjectInputStream} value
- * @throws IOException
- * if an error occurs
- * @throws ClassNotFoundException
- * if an error occurs
+ * @param in The source ObjectInputStream.
+ * @throws IOException Any of the usual Input/Output related exceptions.
+ * @throws ClassNotFoundException A class of a serialized object cannot be found.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
@@ -159,7 +163,7 @@ private void readObject(final ObjectInputStream in) throws IOException, ClassNot
private KeyedObjectPool readObjectImpl() throws IOException, ClassNotFoundException {
try {
return ((SharedPoolDataSource) new SharedPoolDataSourceFactory().getObjectInstance(getReference(), null, null, null)).pool;
- } catch (NamingException e) {
+ } catch (final NamingException e) {
throw new IOException("NamingException: " + e);
}
}
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java
index 937ccd1f1d..b2014365c3 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/SharedPoolDataSourceFactory.java
@@ -25,8 +25,16 @@
* @since 2.0
*/
public class SharedPoolDataSourceFactory extends InstanceKeyDataSourceFactory {
+
private static final String SHARED_POOL_CLASSNAME = SharedPoolDataSource.class.getName();
+ /**
+ * Constructs a new instance.
+ */
+ public SharedPoolDataSourceFactory() {
+ // empty
+ }
+
@Override
protected InstanceKeyDataSource getNewInstance(final Reference ref) {
final SharedPoolDataSource spds = new SharedPoolDataSource();
diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java
index 94643c8070..cde1bf15dd 100644
--- a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java
+++ b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java
@@ -42,10 +42,6 @@ final class UserPassKey implements Serializable {
private final CharArray name;
private final CharArray password;
- UserPassKey(final char[] userName, final char[] password) {
- this(new CharArray(userName), new CharArray(password));
- }
-
UserPassKey(final CharArray userName, final CharArray userPassword) {
this.name = userName;
this.password = userPassword;
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 50373ff370..b11746928a 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/BasicManagedDataSource.java
@@ -127,8 +127,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec
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());
@@ -147,6 +146,7 @@ protected PoolableConnectionFactory createPoolableConnectionFactory(final Connec
connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
connectionFactory.setFastFailValidation(getFastFailValidation());
connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes());
+ connectionFactory.setDisconnectionIgnoreSqlCodes(getDisconnectionIgnoreSqlCodes());
validateConnectionFactory(connectionFactory);
} catch (final RuntimeException e) {
throw e;
@@ -235,17 +235,14 @@ public synchronized void setXADataSource(final String xaDataSource) {
}
/**
- *
* Sets the XADataSource instance used by the XAConnectionFactory.
- *
*
- * 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: getConnection, setLogwriter,
- * setLoginTimeout, getLoginTimeout, getLogWriter.
+ * 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: {@link #getConnection()}, {@link #setLogWriter(java.io.PrintWriter)}, {@link #setLoginTimeout(int)}, {@link #getLoginTimeout()},
+ * {@link #getLogWriter()}.
*
*
- * @param xaDataSourceInstance
- * XADataSource instance
+ * @param xaDataSourceInstance XADataSource instance
*/
public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) {
this.xaDataSourceInstance = xaDataSourceInstance;
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
index 108abb5425..84be596444 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/LocalXAConnectionFactory.java
@@ -212,7 +212,7 @@ public synchronized int prepare(final Xid xid) {
}
/**
- * Always returns a zero length Xid array. The LocalXAConnectionFactory can not support recovery, so no xids
+ * Always returns a zero length Xid array. The LocalXAConnectionFactory cannot support recovery, so no xids
* will ever be found.
*
* @param flag
@@ -369,6 +369,8 @@ public Connection createConnection() throws SQLException {
}
/**
+ * Gets the connection factory.
+ *
* @return The connection factory.
* @since 2.6.0
*/
@@ -376,6 +378,11 @@ public ConnectionFactory getConnectionFactory() {
return connectionFactory;
}
+ /**
+ * Gets the transaction registry.
+ *
+ * @return The transaction registry.
+ */
@Override
public TransactionRegistry getTransactionRegistry() {
return transactionRegistry;
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java b/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java
index 126a39d2bd..a5a72d1a28 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/ManagedConnection.java
@@ -122,7 +122,7 @@ public void close() throws SQLException {
@Override
public void commit() throws SQLException {
if (transactionContext != null) {
- throw new SQLException("Commit can not be set while enrolled in a transaction");
+ throw new SQLException("Commit cannot be set while enrolled in a transaction");
}
super.commit();
}
@@ -148,6 +148,8 @@ public Connection getInnermostDelegate() {
}
/**
+ * Gets the transaction context.
+ *
* @return The transaction context.
* @since 2.6.0
*/
@@ -156,6 +158,8 @@ public TransactionContext getTransactionContext() {
}
/**
+ * Gets the transaction registry.
+ *
* @return The transaction registry.
* @since 2.6.0
*/
@@ -175,7 +179,7 @@ public boolean isAccessToUnderlyingConnectionAllowed() {
@Override
public void rollback() throws SQLException {
if (transactionContext != null) {
- throw new SQLException("Commit can not be set while enrolled in a transaction");
+ throw new SQLException("Commit cannot be set while enrolled in a transaction");
}
super.rollback();
}
@@ -183,7 +187,7 @@ public void rollback() throws SQLException {
@Override
public void setAutoCommit(final boolean autoCommit) throws SQLException {
if (transactionContext != null) {
- throw new SQLException("Auto-commit can not be set while enrolled in a transaction");
+ throw new SQLException("Auto-commit cannot be set while enrolled in a transaction");
}
super.setAutoCommit(autoCommit);
}
@@ -191,7 +195,7 @@ public void setAutoCommit(final boolean autoCommit) throws SQLException {
@Override
public void setReadOnly(final boolean readOnly) throws SQLException {
if (transactionContext != null) {
- throw new SQLException("Read-only can not be set while enrolled in a transaction");
+ throw new SQLException("Read-only cannot be set while enrolled in a transaction");
}
super.setReadOnly(readOnly);
}
@@ -240,7 +244,7 @@ private void updateTransactionStatus() throws SQLException {
if (transactionContext != null && !transactionContext.isTransactionComplete()) {
if (transactionContext.isActive()) {
if (transactionContext != transactionRegistry.getActiveTransactionContext()) {
- throw new SQLException("Connection can not be used while enlisted in another transaction");
+ throw new SQLException("Connection cannot be used while enlisted in another transaction");
}
return;
}
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 858a0c4401..2be2e1a4f1 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 pool) {
+ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool) {
this(transactionRegistry, conn, pool, null, true);
}
/**
- * Create a PoolableManagedConnection.
+ * Creates a PoolableManagedConnection.
*
* @param transactionRegistry
* transaction registry
@@ -57,19 +56,43 @@ public PoolableManagedConnection(final TransactionRegistry transactionRegistry,
* @param pool
* connection pool
* @param disconnectSqlCodes
- * SQL_STATE codes considered fatal disconnection errors
+ * SQL State codes considered fatal disconnection errors
* @param fastFailValidation
* 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 pool, final Collection disconnectSqlCodes,
- final boolean fastFailValidation) {
- super(conn, pool, null, disconnectSqlCodes, fastFailValidation);
+ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool,
+ final Collection disconnectSqlCodes, final boolean fastFailValidation) {
+ this(transactionRegistry, conn, pool, disconnectSqlCodes, null, fastFailValidation);
+ }
+
+ /**
+ * Creates a PoolableManagedConnection.
+ *
+ * @param transactionRegistry
+ * transaction registry
+ * @param conn
+ * underlying connection
+ * @param pool
+ * connection pool
+ * @param disconnectSqlCodes
+ * SQL State codes considered fatal disconnection errors
+ * @param disconnectionIgnoreSqlCodes
+ * SQL State codes considered fatal disconnection errors
+ * @param fastFailValidation
+ * true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to
+ * run query or isValid)
+ * @since 2.13.0
+ */
+ public PoolableManagedConnection(final TransactionRegistry transactionRegistry, final Connection conn, final ObjectPool pool,
+ final Collection disconnectSqlCodes, final Collection 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/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java
index 7eb810154d..9dc80ccb29 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/PoolableManagedConnectionFactory.java
@@ -58,6 +58,8 @@ public PoolableManagedConnectionFactory(final XAConnectionFactory connFactory, f
}
/**
+ * Gets the transaction registry.
+ *
* @return The transaction registry.
* @since 2.6.0
*/
@@ -104,7 +106,7 @@ public synchronized PooledObject makeObject() throws SQLExce
((PoolingConnection) conn).setCacheState(getCacheState());
}
final PoolableManagedConnection pmc = new PoolableManagedConnection(transactionRegistry, conn, getPool(),
- getDisconnectionSqlCodes(), isFastFailValidation());
+ getDisconnectionSqlCodes(), getDisconnectionIgnoreSqlCodes(), isFastFailValidation());
pmc.setCacheState(getCacheState());
return new DefaultPooledObject<>(pmc);
}
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java b/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java
index 4ebb7e7133..cc1b34c1c7 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/TransactionContextListener.java
@@ -22,13 +22,14 @@
* @since 2.0
*/
public interface TransactionContextListener {
+
/**
- * Occurs after the transaction commits or rolls back.
+ * Called after a transaction commits or rolls back.
*
* @param transactionContext
- * the transaction context that completed
+ * the transaction context that completed.
* @param committed
- * true if the transaction committed; false otherwise
+ * true if the transaction committed; false otherwise.
*/
void afterCompletion(TransactionContext transactionContext, boolean committed);
}
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java
index 3421fda810..abef80981a 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/XAConnectionFactory.java
@@ -30,16 +30,16 @@
* @since 2.0
*/
public interface XAConnectionFactory extends ConnectionFactory {
+
/**
- * Create a new {@link java.sql.Connection} in an implementation specific fashion.
+ * Creates a new {@link Connection} in an implementation specific fashion.
*
* An implementation can assume that the caller of this will wrap the connection in a proxy that protects access to
* the setAutoCommit, commit and rollback when enrolled in a XA transaction.
*
*
- * @return a new {@link java.sql.Connection}
- * @throws java.sql.SQLException
- * if a database error occurs creating the connection
+ * @return a new {@link Connection}
+ * @throws SQLException if a database error occurs creating the connection
*/
@Override
Connection createConnection() throws SQLException;
diff --git a/src/main/java/org/apache/commons/dbcp2/managed/package-info.java b/src/main/java/org/apache/commons/dbcp2/managed/package-info.java
index f0bc5210fe..7e613e7b9c 100644
--- a/src/main/java/org/apache/commons/dbcp2/managed/package-info.java
+++ b/src/main/java/org/apache/commons/dbcp2/managed/package-info.java
@@ -19,7 +19,7 @@
*
* This package provides support for pooling of ManagedConnections. A managed
* connection is responsible for managing a database connection in a
- * transactional environment (typically called Container Managed).
+ * transactional environment (typically called Container Managed).
* A managed connection operates like any other connection when no global
* transaction (a.k.a. XA transaction or JTA Transaction) is in progress.
* When a global transaction is active a single physical connection to the
diff --git a/src/main/java/org/apache/commons/dbcp2/package-info.java b/src/main/java/org/apache/commons/dbcp2/package-info.java
index 7fbc736a5d..61d0e38c28 100644
--- a/src/main/java/org/apache/commons/dbcp2/package-info.java
+++ b/src/main/java/org/apache/commons/dbcp2/package-info.java
@@ -19,7 +19,7 @@
*
* Database Connection Pool API.
*
- * Overview in Dialog Form
+ * Overview in Dialog Form
*
* Q: How do I use the DBCP package?
*
diff --git a/src/site/xdoc/configuration.xml b/src/site/xdoc/configuration.xml
index 9579736544..9f6ce90011 100644
--- a/src/site/xdoc/configuration.xml
+++ b/src/site/xdoc/configuration.xml
@@ -498,6 +498,14 @@ the parent connection.
fastFailValidation is set to true.
+
+
disconnectionIgnoreSqlCodes
+
null
+
Comma-delimited list of SQL State codes that should be ignored when determining fatal disconnection errors.
+ These codes will not trigger a fatal disconnection status, even if they match the usual criteria.
+ Setting this property has no effect unless fastFailValidation is set to true.
+
- We recommend you use a mirror to download our release
- builds, but you mustverify the integrity of
- the downloaded files using signatures downloaded from our main
- distribution directories. Recent releases (48 hours) may not yet
- be available from all the mirrors.
-
-
-
- You are currently using [preferred]. If you
- encounter a problem with this mirror, please select another
- mirror. If all mirrors are failing, there are backup
- mirrors (at the end of the mirrors list) that should be
- available.
-
- [if-any logo][end]
-
-
-
-
-
- It is essential that you
- verify the integrity
- of downloaded files, preferably using the PGP signature (*.asc files);
- failing that using the SHA512 hash (*.sha512 checksum files).
-
-
- The KEYS
- file contains the public PGP keys used by Apache Commons developers
- to sign releases.
-
+ We recommend you use a mirror to download our release
+ builds, but you mustverify the integrity of
+ the downloaded files using signatures downloaded from our main
+ distribution directories. Recent releases (48 hours) may not yet
+ be available from all the mirrors.
+
+
+
+ You are currently using [preferred]. If you
+ encounter a problem with this mirror, please select another
+ mirror. If all mirrors are failing, there are backup
+ mirrors (at the end of the mirrors list) that should be
+ available.
+
+ [if-any logo][end]
+
+
+
+
+
+ It is essential that you
+ verify the integrity
+ of downloaded files, preferably using the PGP signature (*.asc files);
+ failing that using the SHA512 hash (*.sha512 checksum files).
+
+
+ The KEYS
+ file contains the public PGP keys used by Apache Commons developers
+ to sign releases.
+
- To use JIRA you may need to create an account
- (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically
- created and you can use the Forgot Password
- page to get a new password).
-
-
-
- If you would like to report a bug, or raise an enhancement request with
- Apache Commons DBCP please do the following:
-
-
Search existing open bugs.
- If you find your issue listed then please add a comment with your details.
+ To use JIRA you may need to create an account
+ (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically
+ created and you can use the Forgot Password
+ page to get a new password).
+
+
+
+ If you would like to report a bug, or raise an enhancement request with
+ Apache Commons DBCP please do the following:
+
+
Search existing open bugs.
+ If you find your issue listed then please add a comment with your details.