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

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

commit 93634e4d40cdf947d637d0b32a7ce954d8237274
Author: opencode <[email protected]>
AuthorDate: Thu Nov 5 15:02:05 2026 +0100

    Use the base class key for anonymous timer MBeans
    
    ResetAbandonedTimer built its JMX key from getClass().getSimpleName(). An 
anonymous subclass has an empty simple name, so the key became 
,JdbcInterceptor= and the registration failed on every borrow while the base 
class worked.
    
    Fall back to ResetAbandonedTimer.class.getSimpleName() when the subclass 
name is empty. Add a test that binds an anonymous timer to a pooled connection 
and asserts its MBean is published under the base-class key.
---
 .../jdbc/pool/interceptor/ResetAbandonedTimer.java |  9 +++++-
 .../TestResetAbandonedTimerMBeanIdle.java          | 34 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
index 8beaf71f38..ee5da06fb1 100644
--- 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
+++ 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
@@ -161,7 +161,14 @@ public class ResetAbandonedTimer extends 
AbstractQueryReport implements ResetAba
                     // level, with the exception behind it. A refused name is
                     // not claimed here, so it stays the property of whoever
                     // holds it and the next borrow tries again.
-                    String keyprop = ",JdbcInterceptor=" + 
getClass().getSimpleName();
+                    String simpleName = getClass().getSimpleName();
+                    if (simpleName.isEmpty()) {
+                        // An anonymous subclass has no simple name; fall back
+                        // to the base class's name so the JMX key is never
+                        // empty.
+                        simpleName = ResetAbandonedTimer.class.getSimpleName();
+                    }
+                    String keyprop = ",JdbcInterceptor=" + simpleName;
                     oname = JmxUtil.registerJmx(pcon.getObjectName(), keyprop, 
this);
                 }
             }
diff --git 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestResetAbandonedTimerMBeanIdle.java
 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestResetAbandonedTimerMBeanIdle.java
index ceda27f1c3..6c017d1a21 100644
--- 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestResetAbandonedTimerMBeanIdle.java
+++ 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestResetAbandonedTimerMBeanIdle.java
@@ -280,4 +280,38 @@ class TestResetAbandonedTimerMBeanIdle extends 
JdbcPoolBaseTest {
                 "the release must be the idle check's own, which is the 
bookkeeping the pokes defeated");
         awaitSessions(0);
     }
+
+    @Test
+    void anAnonymousSubclassPublishesUnderTheBaseClassKey() throws Exception {
+        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+        String uid = Long.toString(System.nanoTime());
+        DataSource ds = newDataSource();
+        ds.getPoolProperties().setJmxEnabled(true);
+        ds.getPoolProperties().setInitialSize(0);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(0);
+        ds.createPool();
+        ds.preRegister(server, new ObjectName(
+                "tomcat:type=ResetAbandonedTimerMBeanTest,role=anonymous,uid=" 
+ uid));
+        pool = ds;
+
+        try (Connection connection = ds.getConnection()) {
+            PooledConnection pc = connection.unwrap(PooledConnection.class);
+            ResetAbandonedTimer anonymous = new ResetAbandonedTimer() {
+            };
+            anonymous.reset(ds.getPool(), pc);
+            try {
+                ObjectName timerName = null;
+                for (ObjectName name : server.queryNames(new 
ObjectName("tomcat.jdbc:*"), null)) {
+                    if 
(ResetAbandonedTimer.class.getSimpleName().equals(name.getKeyProperty("JdbcInterceptor"))
+                            && uid.equals(name.getKeyProperty("uid"))) {
+                        timerName = name;
+                    }
+                }
+                Assertions.assertNotNull(timerName,
+                        "an anonymous timer has no simple name and must 
publish under the base class key");
+            } finally {
+                anonymous.reset(null, null);
+            }
+        }
+    }
 }


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

Reply via email to