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

rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 28330454939d646e3b10aa9608a5c15fdded05dc
Author: opencode <[email protected]>
AuthorDate: Thu Nov 5 16:24:14 2026 +0100

    Create the cache counter for a late StatementCache definition
    
    cacheSizeMap was populated only by poolStarted. A StatementCache definition 
added to a running pool therefore built chains with a null cacheSize, refused 
every park and closed every statement, while still registering its JMX MBean.
    
    Create the pool's counter on the first reset that finds none, under the 
map's monitor. Add a test that adds the interceptor after pool creation, opens 
a new physical connection, parks a statement and checks both counters.
---
 .../jdbc/pool/interceptor/StatementCache.java      |  7 +++++
 .../TestStatementCacheJmxCacheSize.java            | 31 ++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
index cce3f2404e..1407521711 100644
--- 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
+++ 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
@@ -269,6 +269,13 @@ public class StatementCache extends 
StatementDecoratorInterceptor implements Sta
             draining = false;
             synchronized (cacheSizeMap) {
                 cacheSize = cacheSizeMap.get(parent);
+                if (cacheSize == null) {
+                    // A definition added to a running pool did not exist when
+                    // its start registered the counter; create it on the first
+                    // borrow that builds a chain for the definition.
+                    cacheSize = new AtomicInteger(0);
+                    cacheSizeMap.put(parent, cacheSize);
+                }
             }
             this.pcon = con;
             if (!pcon.getAttributes().containsKey(STATEMENT_CACHE_ATTR)) {
diff --git 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestStatementCacheJmxCacheSize.java
 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestStatementCacheJmxCacheSize.java
index 35a7b4454f..b4a7203ca0 100644
--- 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestStatementCacheJmxCacheSize.java
+++ 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestStatementCacheJmxCacheSize.java
@@ -84,6 +84,37 @@ class TestStatementCacheJmxCacheSize extends 
JdbcPoolBaseTest {
         return added;
     }
 
+    @Test
+    void aDefinitionAddedToARunningPoolGetsItsCounter() throws Exception {
+        DataSource ds = newDataSource();
+        ds.getPoolProperties().setInitialSize(0);
+        ds.getPoolProperties().setMaxActive(2);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(0);
+        ds.createPool();
+
+        // Hold a connection built before the definition is added, so the
+        // second borrow must create a physical connection and its chain.
+        Connection first = ds.getConnection();
+        try {
+            ds.getPoolProperties().setJdbcInterceptors(
+                    StatementCache.class.getName() + "(prepared=true,max=5)");
+            try (Connection second = ds.getConnection()) {
+                StatementCache cache = interceptorOf(second, 
StatementCache.class);
+                Assertions.assertNotNull(cache,
+                        "the new connection's chain must hold the added 
definition");
+                PreparedStatement statement = second.prepareStatement("SELECT 
1");
+                statement.close();
+
+                Assertions.assertEquals(1, cache.getCacheSizePerConnection(),
+                        "a statement closed on the new chain must be parked");
+                Assertions.assertEquals(1, cache.getCacheSize(),
+                        "the late definition must have obtained a cache-size 
counter");
+            }
+        } finally {
+            first.close();
+        }
+    }
+
     @Test
     void theCacheSizeAttributeIsADescribedNumber() throws Exception {
         MBeanServer server = ManagementFactory.getPlatformMBeanServer();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to