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 209f3964ccd245c3bdb7d66a931222f5f3f24fec
Author: opencode <[email protected]>
AuthorDate: Thu Nov 5 22:11:23 2026 +0100

    Attempt the slow query JMX publication once per pool
    
    JMX is a best-effort management channel, and pool names are unique under 
Catalina. SlowQueryReportJmx nevertheless retried a refused MBean publication 
on every borrow, forming the ObjectName and building a Registration each time, 
with throttle state to keep the repeated failures quiet.
    
    Attempt the publication once per pool instead. A refusal is logged once in 
registerJmx(), later borrows leave the MBean server alone, and PoolJmx drops 
the retry and throttle state (publishing, failureLoggedUnder, 
malformedNameReported, refused, failureMarker). Update the tests and log 
messages to the no-retry contract.
---
 .../jdbc/pool/interceptor/SlowQueryReportJmx.java  | 177 +++++++--------------
 .../tomcat/jdbc/pool/util/LocalStrings.properties  |   6 +-
 .../interceptor/TestSlowQueryJmxNotifications.java |  86 ++++------
 .../TestSlowQueryReportAbandonedPool.java          |   3 -
 4 files changed, 89 insertions(+), 183 deletions(-)

diff --git 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
index 05f2994574..82d4040e1e 100644
--- 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
+++ 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
@@ -63,7 +63,8 @@ import org.apache.tomcat.jdbc.pool.util.MessageFactory;
  * first interceptor instance of a pool to borrow a connection publishes them, 
and every other instance of that pool -
  * its other connections, the second definition of the recommended 
two-thresholds configuration - reports through them.
  * The pool start callback only records the pool and its registration name; an 
idle pool is not published, so
- * monitoring begins with the first borrow.
+ * monitoring begins with the first borrow. The publication is attempted once: 
JMX is a best-effort management channel,
+ * so a refusal is logged for the operator and later borrows leave the server 
alone.
  * They are published under the name the pool started with - see {@link 
ConnectionPool#getRegistrationName()} - which
  * identifies the pool and must be unique among the live pools of a class 
loader: Tomcat gives every pool it manages a
  * name of its own, and a programmatically built pool has a unique default 
name. A duplicate live name is reported as
@@ -136,8 +137,7 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
 
     /**
      * Everything this class publishes for one pool: the notification 
broadcaster its clients attach their listeners to
-     * and, in the {@code notifyPool=false} mode, the ObjectName the pool's 
MBean occupies together with the marker of a
-     * publication the MBeanServer refused.
+     * and, in the {@code notifyPool=false} mode, the ObjectName the pool's 
MBean occupies.
      * <p>
      * The state hangs from the pool's statistics store (see {@link 
PoolStatistics#getJmxState()}), which is 1:1 with
      * the pool, and nothing a pool published can be given up by another 
pool's close. It is built by the first
@@ -145,9 +145,10 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
      * pool is.
      * </p>
      * <p>
-     * Publication and release are serialised against each other by this 
object's monitor, and the MBeanServer is
-     * called outside it: a borrow either publishes, or finds the publication 
already made, already refused and left for
-     * a later borrow to retry, or already superseded by the pool's close - in 
which case the borrow gives back the
+     * The publication is attempted once per pool: JMX is a best-effort 
management channel, so a refusal is logged and
+     * not retried by later borrows. Publication and release are serialised 
against each other by this object's monitor,
+     * and the MBeanServer is called outside it: a borrow either publishes, 
finds that the attempt has already been
+     * made, or finds the state already superseded by the pool's close - in 
which case the borrow gives back the
      * publication it just made. A published MBean can therefore never outlive 
the state that published it, and the
      * ObjectName a release gives up is the one this state recorded when it 
published, whatever class or
      * {@code objectName} property the interceptor instance running the close 
happens to carry.
@@ -170,20 +171,10 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
          */
         private ObjectName publishedUnder;
         /**
-         * the ObjectName whose refusal this state has already reported with 
its exception, so that a persistent
-         * refusal is not reported once per borrow; guarded by this
+         * whether a publication has been attempted for this pool, so that a 
refusal is logged once and later borrows
+         * leave the management server alone; guarded by this
          */
-        private ObjectName failureLoggedUnder;
-        /**
-         * whether a failure that could not form an ObjectName has been 
reported, so that a permanent malformed name
-         * is not logged with a stack trace on every borrow; guarded by this
-         */
-        private boolean malformedNameReported;
-        /**
-         * whether a publication attempt is in flight, so that the concurrent 
borrows of one pool make one attempt
-         * rather than one per thread; guarded by this
-         */
-        private boolean publishing;
+        private boolean attempted;
         /**
          * whether the close of the pool has given this state up; guarded by 
this
          */
@@ -216,15 +207,6 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
             return publishedUnder;
         }
 
-        /**
-         * Returns the ObjectName whose refusal this state has already 
reported loudly.
-         *
-         * @return the reported ObjectName, or {@code null} while no 
publication for this pool has been refused
-         */
-        protected synchronized ObjectName failureMarker() {
-            return failureLoggedUnder;
-        }
-
         /**
          * Returns whether the close of this pool has given this state up.
          *
@@ -255,23 +237,21 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
         }
 
         /**
-         * Decides whether the calling borrow is to publish this pool's MBean.
+         * Decides whether the calling borrow is to make this pool's one 
publication attempt.
          *
-         * @return {@code true} if the caller is to publish it now - nothing 
is published for the pool, no other borrow
-         *             is publishing, and the pool has not closed - and {@code 
false} when there is nothing to publish
-         *             or someone else is at it
+         * @return {@code true} if the caller is to attempt the publication - 
none has been made or attempted yet, and
+         *             the pool has not closed - and {@code false} when there 
is nothing left to do
          */
         protected synchronized boolean beginPublication() {
-            if (released || publishedUnder != null || publishing) {
+            if (released || attempted) {
                 return false;
             }
-            publishing = true;
+            attempted = true;
             return true;
         }
 
         /**
-         * Records a publication the MBeanServer accepted, and clears the 
refusal marker: a registration under the name
-         * works again, so a later failure cycle reports loudly once more.
+         * Records a publication the MBeanServer accepted.
          *
          * @param oname the ObjectName the MBean was published under
          *
@@ -280,66 +260,13 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
          *             that publication, so the borrow that made it has to 
give it back
          */
         protected synchronized boolean published(ObjectName oname) {
-            publishing = false;
             if (released) {
                 return false;
             }
             publishedUnder = oname;
-            failureLoggedUnder = null;
             return true;
         }
 
-        /**
-         * Ends a publication attempt that did not publish, and reports it. 
The attempt being over, a later borrow
-         * retries.
-         * <p>
-         * The retry is not made cheaper than the attempt it repeats, and that 
is deliberate: the first borrow that
-         * finds nothing published publishes it, so a clash with a stale or 
foreign MBean costs monitoring only for as
-         * long as that MBean is there, while a backoff would make every pool 
that ever clashed wait out a delay before
-         * its monitoring came back. What a persistent refusal therefore costs 
is one publish attempt per borrow - the
-         * ObjectName formed, a {@link Registration} built, and the 
MBeanServer's refusal - on a pool whose monitoring is
-         * misconfigured, which is the cost paid for that recovery. Only the 
first refusal of an ObjectName is reported
-         * with its exception, so a persistent refusal is not reported once 
per borrow.
-         * </p>
-         *
-         * @param oname the ObjectName whose publication was refused, or 
{@code null} when no ObjectName could be formed
-         *                  - there is then no name to mark, so this state 
remembers that the malformed name was
-         *                  reported and later retries stay at debug level
-         * @param x     what the MBeanServer answered
-         */
-        protected synchronized void refused(ObjectName oname, Exception x) {
-            publishing = false;
-            if (oname == null) {
-                if (!malformedNameReported) {
-                    malformedNameReported = true;
-                    
log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailedNoData"), 
x);
-                } else if (log.isDebugEnabled()) {
-                    log.debug("Jmx registration failed again: " + x);
-                }
-                return;
-            }
-            if (oname.equals(failureLoggedUnder)) {
-                // The loud report went out with the first refusal of this
-                // name; repeats ride along at debug, without a stack trace, so
-                // a persistent refusal stays quiet under borrow load
-                if (log.isDebugEnabled()) {
-                    log.debug("Jmx registration of [" + oname + "] failed 
again: " + x);
-                }
-                return;
-            }
-            // First refusal for this ObjectName, or a refusal under another
-            // ObjectName than the one already reported: report it loudly and
-            // remember to throttle the repeats
-            failureLoggedUnder = oname;
-            if (x instanceof InstanceAlreadyExistsException) {
-                // Retryable: the name may be held by a stale or foreign MBean
-                // that a later borrow finds gone
-                
log.warn(MessageFactory.get("slowQueryReportJmx.jmxRegistrationInUse", oname), 
x);
-            } else {
-                
log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailed", 
oname), x);
-            }
-        }
-
         /**
          * Gives up everything this state holds: the ObjectName the pool's 
MBean occupied, which the MBeanServer is
          * asked to release, and with it the broadcaster the pool's clients' 
listeners are attached to. The close of the
@@ -866,11 +793,11 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
     /**
      * Registers this pool's MBean with JMX.
      * <p>
-     * The attempt is made by the first borrow that finds nothing published 
for the pool, and only by that borrow:
-     * {@link PoolJmx#beginPublication()} hands the publication to one thread 
at a time, and a borrow that finds the
-     * publication made - or refused and waiting for a retry, which is the 
next borrow's business - is turned away
-     * before the ObjectName is formed. Forming it and building a {@link 
Registration} for a race that can only be lost
-     * is work a healthy pool would pay per borrow for no possible use.
+     * The publication is attempted once per pool, by the first borrow that 
needs it:
+     * {@link PoolJmx#beginPublication()} hands the attempt to one thread, and 
every later borrow is turned away before
+     * the ObjectName is formed. JMX is a best-effort management channel, so a 
refusal is logged for the operator and
+     * not retried; forming the name and building a {@link Registration} again 
on every borrow would cost the pool work
+     * for a publication that is not part of its operation.
      * </p>
      * <p>
      * A pool this instance cannot resolve a statistics store for is skipped 
before any of it: a pool that carries no
@@ -899,38 +826,44 @@ public class SlowQueryReportJmx extends SlowQueryReport 
implements NotificationE
         if (state == null || !state.beginPublication()) {
             return;
         }
-        ObjectName oname = null;
+        ObjectName oname;
         try {
             oname = getObjectName(getClass(), state.getPoolName());
-            // The MBeanServer keeps the registration resource, never this
-            // instance: an instance reaches the pool (its own and the 
inherited
-            // pool fields), so publishing one made the JVM-lifetime 
registration
-            // pin a pool that was abandoned without closing - the only path 
that
-            // ever takes a registration down again is a close, which 
abandonment
-            // never runs
-            Registration registration = new Registration(state.getPoolName(), 
statistics, state);
-            try {
-                
ManagementFactory.getPlatformMBeanServer().registerMBean(registration, oname);
-            } catch (Exception x) {
-                // What the server refused - a name a foreign or stale MBean
-                // occupies, a non-compliant resource, a security restriction. 
A
-                // later borrow retries.
-                state.refused(oname, x);
-                return;
-            }
-            if (!state.published(oname)) {
-                // The pool's close landed while the server was taking this in,
-                // and has already given up everything the state held; this
-                // publication belongs to nobody now but the thread that made 
it
-                JmxUtil.unregisterJmx(oname);
-            }
         } catch (MalformedObjectNameException | RuntimeOperationsException x) {
             // A name that cannot be formed - a malformed objectName property, 
or
-            // a pool name carrying characters the ObjectName grammar reserves 
-
-            // has no ObjectName to record the refusal against; the state
-            // remembers that it was reported and later retries stay at debug
-            // level (see refused).
-            state.refused(null, x);
+            // a pool name carrying characters the ObjectName grammar reserves.
+            // There is no publication to make, and JMX is best effort, so this
+            // is reported once and not attempted again.
+            
log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailedNoData"), 
x);
+            return;
+        }
+        // The MBeanServer keeps the registration resource, never this
+        // instance: an instance reaches the pool (its own and the inherited
+        // pool fields), so publishing one made the JVM-lifetime registration
+        // pin a pool that was abandoned without closing - the only path that
+        // ever takes a registration down again is a close, which abandonment
+        // never runs
+        Registration registration = new Registration(state.getPoolName(), 
statistics, state);
+        try {
+            
ManagementFactory.getPlatformMBeanServer().registerMBean(registration, oname);
+        } catch (InstanceAlreadyExistsException x) {
+            // The name is held by a foreign or stale MBean. JMX is best effort
+            // and names are unique under Catalina, so this is reported rather
+            // than retried: by the time a retry ran, the name could describe a
+            // different component.
+            
log.warn(MessageFactory.get("slowQueryReportJmx.jmxRegistrationInUse", oname), 
x);
+            return;
+        } catch (Exception x) {
+            // A non-compliant resource, a security restriction, or another
+            // server-side refusal. Reported once, not retried.
+            
log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailed", 
oname), x);
+            return;
+        }
+        if (!state.published(oname)) {
+            // The pool's close landed while the server was taking this in,
+            // and has already given up everything the state held; this
+            // publication belongs to nobody now but the thread that made it
+            JmxUtil.unregisterJmx(oname);
         }
     }
 
diff --git 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties
 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties
index 44f3d82f17..54d36c999d 100644
--- 
a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties
+++ 
b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties
@@ -216,9 +216,9 @@ slowQueryReport.slowQueryReport=Slow Query Report SQL={0}; 
time={1} ms;
 slowQueryReport.unknownProperty=The interceptor property [{0}] is not 
recognized and is not applied: property names are matched exactly, and a name 
this interceptor does not know leaves the setting it was meant to configure at 
the value it carries. Check the jdbcInterceptors configuration for the name 
that was meant to be configured.
 
 slowQueryReportJmx.invalidNotifyPool=The configured notifyPool [{0}] is 
neither true nor false and is not applied: query notifications keep going to 
the channel the current setting [{1}] selects. Correct the value in the 
jdbcInterceptors configuration to choose the notification channel that was 
meant to be configured.
-slowQueryReportJmx.jmxRegistrationFailed=Jmx registration of [{0}] failed, no 
JMX data will be exposed for the query stats until a registration succeeds. The 
registration is retried by later borrows; repeated failures are logged at debug 
level.
-slowQueryReportJmx.jmxRegistrationFailedNoData=Jmx registration failed, no JMX 
data will be exposed for the query stats.
-slowQueryReportJmx.jmxRegistrationInUse=Jmx registration of [{0}] failed: the 
name is already in use by another MBean. The registration is retried by later 
borrows; repeated failures are logged at debug level.
+slowQueryReportJmx.jmxRegistrationFailed=Jmx registration of [{0}] failed, so 
no JMX data will be exposed for the query stats. JMX is a best-effort 
management channel, so the registration is not retried; correct the reported 
cause and restart the pool to restore the management surface.
+slowQueryReportJmx.jmxRegistrationFailedNoData=Jmx registration failed, so no 
JMX data will be exposed for the query stats. JMX is a best-effort management 
channel, so the registration is not retried.
+slowQueryReportJmx.jmxRegistrationInUse=Jmx registration of [{0}] failed 
because the name is already in use by another MBean. JMX is a best-effort 
management channel, so the registration is not retried; give the pool a unique 
name or remove the other MBean and restart the pool to restore the management 
surface.
 slowQueryReportJmx.noJmxSupport={0}- No JMX support, composite type was not 
found.
 slowQueryReportJmx.unableToInitCompositeType=Unable to initialize composite 
data type for JMX stats and notifications.
 
diff --git 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryJmxNotifications.java
 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryJmxNotifications.java
index 5698f700dd..0379991ab7 100644
--- 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryJmxNotifications.java
+++ 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryJmxNotifications.java
@@ -793,9 +793,7 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
                                 + " the name is formed and a Registration 
built to lose the"
                                 + " slot race: parsing a full ObjectName and 
allocating a"
                                 + " publication that cannot happen on every 
borrow of a"
-                                + " perfectly registered pool is cost with no 
possible use -"
-                                + " and a refused registration still leaves 
the slot free, so"
-                                + " the retry semantics of a failed publish 
are untouched");
+                                + " perfectly registered pool is cost with no 
possible use");
             }
         } finally {
             ds.close();
@@ -803,8 +801,7 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
     }
 
     @Test
-    void 
aRefusedPublicationKeepsRetryingAndAPublishTheServerTookStandsUntilTheClose()
-            throws Exception {
+    void aRefusedPublicationIsNotRetriedByALaterBorrow() throws Exception {
         String poolName = "JmxRegFail-" + System.nanoTime();
         DataSource ds = newDataSource();
         ds.setName(poolName);
@@ -829,31 +826,24 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
                 SlowQueryReportJmx.PoolJmx state = 
SlowQueryReportJmx.jmxStateFor(pool);
                 Assertions.assertNull(state.publishedUnder(),
                         "a publish the MBeanServer refused must not leave the 
pool claiming an"
-                                + " MBean that was never published - every 
later borrow would find"
-                                + " the pool published and never retry");
+                                + " MBean that was never published");
+            }
 
-                // With the obstacle gone, a later borrow must still get the
-                // MBean published: the refused attempt must not have latched
-                // anything for the life of the pool.
-                server.unregisterMBean(oname);
-                try (@SuppressWarnings("unused") Connection next = 
ds.getConnection()) {
-                    Assertions.assertTrue(server.isRegistered(oname),
-                            "the borrow after the obstacle was removed must 
publish the MBean");
-                    // the attribute of the interceptor's MBean interface,
-                    // answered by the registered resource: not the obstacle,
-                    // which exposes no such attribute
-                    Assertions.assertDoesNotThrow(() -> 
server.getAttribute(oname, "SlowQueriesCD"),
-                            "the published MBean must be the interceptor's, 
answering its statistics query");
-                    Assertions.assertEquals(oname,
-                            
SlowQueryReportJmx.jmxStateFor(pool).publishedUnder(),
-                            "the retrying borrow must have recorded what it 
published");
-                }
+            // JMX is best effort. With the obstacle gone, a later borrow does
+            // not repeat the attempt: the refusal was reported once for the
+            // operator, and retrying by name could collide with yet another
+            // component that took it.
+            server.unregisterMBean(oname);
+            try (@SuppressWarnings("unused") Connection next = 
ds.getConnection()) {
+                Assertions.assertFalse(server.isRegistered(oname),
+                        "a later borrow must not retry a refused publication");
+                
Assertions.assertNull(SlowQueryReportJmx.jmxStateFor(pool).publishedUnder(),
+                        "the pool must still not claim a publication it never 
made");
             }
+
             ds.close();
-            Assertions.assertFalse(server.isRegistered(oname),
-                    "closing the pool must release the registration the retry 
published");
             Assertions.assertNull(SlowQueryReportJmx.jmxStateFor(pool),
-                    "and give up the JMX state it hung from");
+                    "closing the pool must give up the JMX state it hung 
from");
         } finally {
             // remove the obstacle if the test never got as far as removing
             // it itself; on the green path nothing is registered any more
@@ -866,7 +856,7 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
     }
 
     @Test
-    void persistentPublicationRefusalKeepsRetryingAndCleansUpOnClose() throws 
Exception {
+    void aRefusedPublicationIsReportedOnceAndCleanedUpOnClose() throws 
Exception {
         String poolName = "JmxRegRefuse-" + System.nanoTime();
         DataSource refusingPool = reportingPoolNamed(poolName);
 
@@ -879,36 +869,27 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
         List<Notification> received = new CopyOnWriteArrayList<>();
         NotificationListener listener = (notification, handback) -> 
received.add(notification);
         try {
-            // The first refused borrow: nothing is published for the pool, and
-            // the failure is marked as reported - the loud report of this pool
-            // (warn/error) has gone out, its repeats ride at debug without
-            // a stack trace (not asserted: the module's test infrastructure
-            // captures no log, so the throttle is pinned through its
-            // bookkeeping only)
+            // The first borrow attempts the publication and is refused:
+            // nothing is published for the pool, and the refusal is reported
+            // once by registerJmx().
             Connection first = refusingPool.getConnection();
             ConnectionPool pool = refusingPool.getPool();
             SlowQueryReportJmx.PoolJmx state = 
SlowQueryReportJmx.jmxStateFor(pool);
             Assertions.assertNull(state.publishedUnder(),
                     "a refused publication must not leave the pool claiming an 
MBean");
-            Assertions.assertEquals(oname, state.failureMarker(),
-                    "the first refusal of this ObjectName must be marked as 
reported for the"
-                            + " throttle");
             interceptorOf(first, SlowQueryReportJmx.class)
                     .addNotificationListener(listener, null, null);
 
-            // Later borrows keep retrying: still refused (the obstacle holds
-            // the name), still nothing published, and the identical marker
-            // keeps their logging throttled
+            // Later borrows do not retry the publication; the obstacle keeps
+            // the name and nothing is published for this pool, but its own
+            // broadcaster still serves its listeners.
             try (@SuppressWarnings("unused") Connection second = 
refusingPool.getConnection();
                     @SuppressWarnings("unused") Connection third = 
refusingPool.getConnection()) {
                 Assertions.assertNull(state.publishedUnder(),
-                        "retried refusals must leave the pool unpublished, so 
that the next borrow"
-                                + " can try again");
-                Assertions.assertEquals(oname, state.failureMarker(),
-                        "repeated refusals of the same ObjectName must not 
re-mark it loudly");
+                        "later borrows must not retry a refused publication");
                 Assertions.assertEquals("registration-obstacle",
                         server.getAttribute(oname, "HeldBy"),
-                        "the retried publishes must still be colliding with 
the obstacle");
+                        "the name must still belong to the obstacle");
                 // A slow query of the refused pool still reaches the pool's 
own
                 // broadcaster - state the close has to give up even though no
                 // publication of this pool ever succeeded
@@ -923,9 +904,7 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
             first.close();
 
             // Close a pool that never got published: its close gives up the
-            // state it reported through - broadcaster and throttle marker and
-            // all - so neither outlives the pool, and a later pool under the
-            // same name starts its own failure cycle marked loudly again
+            // state it reported through, so it does not outlive the pool.
             refusingPool.close();
             Assertions.assertNull(SlowQueryReportJmx.jmxStateFor(pool),
                     "the close of the pool gives up the JMX state it published 
nothing from");
@@ -933,18 +912,17 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
                     server.getAttribute(oname, "HeldBy"),
                     "and the name still belongs to the obstacle: the refused 
pool never took it");
 
-            // the name stayed retryable through every refusal: once the
-            // obstacle is gone, a fresh pool under the name publishes at once
-            // and publishes cleanly - success marks nothing in the throttle
+            // A fresh pool under a freed name makes its own attempt and
+            // publishes cleanly.
             server.unregisterMBean(oname);
             DataSource revivedPool = reportingPoolNamed(poolName);
             try (@SuppressWarnings("unused") Connection borrowed = 
revivedPool.getConnection()) {
                 Assertions.assertTrue(server.isRegistered(oname),
                         "the first borrow of a pool started after the obstacle 
is gone"
                                 + " must publish the MBean");
-                
Assertions.assertNull(SlowQueryReportJmx.jmxStateFor(revivedPool.getPool())
-                                .failureMarker(),
-                        "a succeeding publication must not leave a throttle 
marker behind");
+                Assertions.assertEquals(oname,
+                        
SlowQueryReportJmx.jmxStateFor(revivedPool.getPool()).publishedUnder(),
+                        "the published MBean must be the revived pool's");
             }
             revivedPool.close();
             Assertions.assertFalse(server.isRegistered(oname),
@@ -1270,8 +1248,6 @@ class TestSlowQueryJmxNotifications extends 
JdbcPoolBaseTest {
                 SlowQueryReportJmx.PoolJmx state = 
SlowQueryReportJmx.jmxStateFor(ds.getPool());
                 Assertions.assertNull(state.publishedUnder(),
                         "a name that cannot be formed must never leave the 
pool claiming a publication");
-                Assertions.assertNull(state.failureMarker(),
-                        "a failure that cannot form its ObjectName has no name 
to mark as reported");
             }
         } finally {
             logger.removeHandler(handler);
diff --git 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportAbandonedPool.java
 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportAbandonedPool.java
index ede0c4cb4b..91e585ccc5 100644
--- 
a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportAbandonedPool.java
+++ 
b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportAbandonedPool.java
@@ -220,9 +220,6 @@ class TestSlowQueryReportAbandonedPool extends 
JdbcPoolBaseTest {
             Assertions.assertNull(state.publishedUnder(),
                     "and the successor must not report through the abandoned 
pool's MBean:"
                             + " its own publication is the one the MBeanServer 
refused");
-            Assertions.assertNotNull(state.failureMarker(),
-                    "the refusal is recorded against the ObjectName, reported 
once and retried"
-                            + " on the next borrow");
 
             survivor.close();
 


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

Reply via email to