[DBCP-554]
org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should
close ALL of its resources even when an exception occurs.
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 99132a4..66eb615 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -133,6 +133,9 @@
       <action dev="ggregory" type="update" issue="DBCP-553" due-to="Gary Gregory">
         org.apache.commons.dbcp2.PoolablePreparedStatement.passivate() should close ALL of its resources even when an exception occurs.
       </action>
+      <action dev="ggregory" type="update" issue="DBCP-554" due-to="Gary Gregory">
+        org.apache.commons.dbcp2.PoolableCallableStatement.passivate() should close ALL of its resources even when an exception occurs.
+      </action>
     </release>
     <release version="2.6.0" date="2019-02-14" description="This is a minor release, including bug fixes and enhancements.">
       <action dev="chtompki" type="add" issue="DBCP-534" due-to="Peter Wicks">
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java b/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
index 717e7b2..8efcefd 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolableCallableStatement.java
@@ -21,6 +21,7 @@
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.pool2.KeyedObjectPool;
@@ -119,13 +120,23 @@
         // ResultSet's when it is closed.
         // FIXME The PreparedStatement we're wrapping should handle this for us.
         // See DBCP-10 for what could happen when ResultSets are closed twice.
-        final List<AbandonedTrace> resultSets = getTrace();
-        if (resultSets != null) {
-            final ResultSet[] set = resultSets.toArray(new ResultSet[resultSets.size()]);
-            for (final ResultSet element : set) {
-                element.close();
+        final List<AbandonedTrace> resultSetList = getTrace();
+        if (resultSetList != null) {
+            final List<Exception> thrown = new ArrayList<>();
+            final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]);
+            for (final ResultSet resultSet : resultSets) {
+                if (resultSet != null) {
+                    try {
+                        resultSet.close();
+                    } catch (Exception e) {
+                        thrown.add(e);
+                    }
+                }
             }
             clearTrace();
+            if (!thrown.isEmpty()) {
+                throw new SQLExceptionList(thrown);
+            }
         }
 
         super.passivate();