This is an automated email from the ASF dual-hosted git repository.

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new c96c958a57 NIFI-15372: Ensure Driver is Deregistered when DBCP Service 
is removed.
c96c958a57 is described below

commit c96c958a57c8b04587179f01fb8d2ae461117a15
Author: Bob Paulin <[email protected]>
AuthorDate: Thu Dec 18 18:15:08 2025 -0600

    NIFI-15372: Ensure Driver is Deregistered when DBCP Service is removed.
    
    Signed-off-by: Pierre Villard <[email protected]>
    
    This closes #10670.
---
 .../org/apache/nifi/dbcp/DBCPConnectionPool.java   | 22 ++++++++++++++++++++--
 .../java/org/apache/nifi/dbcp/DBCPServiceTest.java | 12 ++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
 
b/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
index ec967bd230..9241834986 100644
--- 
a/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
+++ 
b/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/main/java/org/apache/nifi/dbcp/DBCPConnectionPool.java
@@ -34,6 +34,7 @@ import org.apache.nifi.annotation.behavior.Restriction;
 import org.apache.nifi.annotation.behavior.SupportsSensitiveDynamicProperties;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
 import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnRemoved;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.PropertyValue;
 import org.apache.nifi.components.RequiredPermission;
@@ -103,6 +104,9 @@ public class DBCPConnectionPool extends 
AbstractDBCPConnectionPool implements DB
      */
     protected static final String SENSITIVE_PROPERTY_PREFIX = "SENSITIVE.";
 
+    // Hold an instance of the registered driver so we can properly 
de-register it.
+    private volatile Driver registeredDriver;
+
     private static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = 
List.of(
         DATABASE_URL,
         DB_DRIVERNAME,
@@ -261,9 +265,13 @@ public class DBCPConnectionPool extends 
AbstractDBCPConnectionPool implements DB
             return DriverManager.getDriver(url);
         } catch (final SQLException e) {
             // In case the driver is not registered by the implementation, we 
explicitly try to register it.
+            // deregister existing driver
             try {
-                final Driver driver = (Driver) 
clazz.getDeclaredConstructor().newInstance();
-                DriverManager.registerDriver(driver);
+                if (registeredDriver != null) {
+                    DriverManager.deregisterDriver(registeredDriver);
+                }
+                registeredDriver = (Driver) 
clazz.getDeclaredConstructor().newInstance();
+                DriverManager.registerDriver(registeredDriver);
                 return DriverManager.getDriver(url);
             } catch (final SQLException e2) {
                 throw new ProcessException("No suitable driver for the given 
Database Connection URL", e2);
@@ -272,4 +280,14 @@ public class DBCPConnectionPool extends 
AbstractDBCPConnectionPool implements DB
             }
         }
     }
+
+    @OnRemoved
+    public void onRemove() {
+        try {
+            // We need to deregister the driver to allow the 
InstanceClassLoader to be garbage collected.
+            DriverManager.deregisterDriver(registeredDriver);
+        } catch (SQLException e) {
+            getLogger().warn("Driver could not be deregistered. This may cause 
a memory leak.", e);
+        }
+    }
 }
diff --git 
a/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
 
b/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
index 3c6e976ea3..2250adbdb7 100644
--- 
a/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
+++ 
b/nifi-extension-bundles/nifi-standard-services/nifi-dbcp-service-bundle/nifi-dbcp-service/src/test/java/org/apache/nifi/dbcp/DBCPServiceTest.java
@@ -27,6 +27,7 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.UUID;
 import org.apache.nifi.components.ConfigVerificationResult;
@@ -177,6 +178,17 @@ public class DBCPServiceTest {
         }
     }
 
+    @Test
+    public void testDeregisterDriver() throws SQLException {
+        runner.enableControllerService(service);
+        runner.assertValid(service);
+        final int serviceRunningNumberOfDrivers = 
Collections.list(DriverManager.getDrivers()).size();
+        runner.disableControllerService(service);
+        runner.removeControllerService(service);
+        final int expectedDriversAfterRemove = serviceRunningNumberOfDrivers - 
1;
+        assertEquals(expectedDriversAfterRemove, 
Collections.list(DriverManager.getDrivers()).size(), "Driver should be 
deregistered on remove");
+    }
+
     @Test
     public void testGetConnectionMaxTotalConnectionsExceeded() {
         runner.setProperty(service, DBCPProperties.MAX_TOTAL_CONNECTIONS, "1");

Reply via email to