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 52ac1675a2319925caf3a907754c4b979c5e61b0
Author: opencode <[email protected]>
AuthorDate: Thu Oct 15 10:30:56 2026 +0200

    Use unique increasing sequence numbers for MBean notifications
    
    BaseModelMBean emitted every JMX notification with the hard-coded
    sequence number 1, which prevents listeners that use the sequence
    number for ordering or to detect missed or duplicated notifications
    from doing so, contrary to the JMX requirements for notification
    sources.
    
    Add a per-MBean sequence number counter (AtomicLong since
    notifications may be emitted from several admin threads) and use it
    at both notification construction sites so attribute change
    notifications and generic notifications share one increasing
    sequence. Notifications built by callers and passed to the
    sendNotification/sendAttributeChangeNotification overloads keep the
    sequence number assigned by their constructing sender as per the JMX
    contract.
    
    Add a unit test asserting the exact sequence numbers of two attribute
    change notifications and a following generic notification.
---
 .../apache/tomcat/util/modeler/BaseModelMBean.java   | 15 ++++++++++++---
 .../modeler/TestBaseModelMBeanNotifications.java     | 20 ++++++++++++++++++++
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/java/org/apache/tomcat/util/modeler/BaseModelMBean.java 
b/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
index a3fa451082..6c862c9b76 100644
--- a/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
+++ b/java/org/apache/tomcat/util/modeler/BaseModelMBean.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.modeler;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicLong;
 
 import javax.management.Attribute;
 import javax.management.AttributeChangeNotification;
@@ -139,6 +140,11 @@ public class BaseModelMBean implements DynamicMBean, 
MBeanRegistration, ModelMBe
      */
     protected String resourceType = null;
 
+    /**
+     * The sequence number for the next notification sent by this MBean.
+     */
+    private final AtomicLong sequenceNumber = new AtomicLong();
+
     // key: operation val: invoke method
     // private Hashtable invokeAttMap=new Hashtable();
 
@@ -568,8 +574,10 @@ public class BaseModelMBean implements DynamicMBean, 
MBeanRegistration, ModelMBe
             return; // Old and new are both null == no change
         }
 
-        AttributeChangeNotification notification = new 
AttributeChangeNotification(this, 1, System.currentTimeMillis(),
-                "Attribute value has changed", oldValue.getName(), type, 
oldValue.getValue(), newValue.getValue());
+        AttributeChangeNotification notification =
+                new AttributeChangeNotification(this, 
sequenceNumber.incrementAndGet(), System.currentTimeMillis(),
+                        "Attribute value has changed", oldValue.getName(), 
type, oldValue.getValue(),
+                        newValue.getValue());
         sendAttributeChangeNotification(notification);
 
     }
@@ -599,7 +607,8 @@ public class BaseModelMBean implements DynamicMBean, 
MBeanRegistration, ModelMBe
                     new 
IllegalArgumentException(sm.getString("baseModelMBean.nullMessage")),
                     sm.getString("baseModelMBean.nullMessage"));
         }
-        Notification notification = new Notification("jmx.modelmbean.generic", 
this, 1, message);
+        Notification notification =
+                new Notification("jmx.modelmbean.generic", this, 
sequenceNumber.incrementAndGet(), message);
         sendNotification(notification);
 
     }
diff --git 
a/test/org/apache/tomcat/util/modeler/TestBaseModelMBeanNotifications.java 
b/test/org/apache/tomcat/util/modeler/TestBaseModelMBeanNotifications.java
index 0d378aa7ab..b206dc66ea 100644
--- a/test/org/apache/tomcat/util/modeler/TestBaseModelMBeanNotifications.java
+++ b/test/org/apache/tomcat/util/modeler/TestBaseModelMBeanNotifications.java
@@ -34,9 +34,11 @@ public class TestBaseModelMBeanNotifications {
 
         private final List<String> received = new ArrayList<>();
         private final List<AttributeChangeNotification> changes = new 
ArrayList<>();
+        private final List<Long> sequences = new ArrayList<>();
 
         @Override
         public void handleNotification(Notification notification, Object 
handback) {
+            sequences.add(notification.getSequenceNumber());
             String name;
             if (notification instanceof AttributeChangeNotification acn) {
                 changes.add(acn);
@@ -170,6 +172,24 @@ public class TestBaseModelMBeanNotifications {
         Assert.assertEquals("updated", change.getNewValue());
     }
 
+    @Test
+    public void testSequenceNumbersIncrease() throws Exception {
+        BaseModelMBean mbean = new BaseModelMBean();
+        TesterNotificationListener listener = new TesterNotificationListener();
+        mbean.addAttributeChangeNotificationListener(listener, "A", "hb");
+        send(mbean, "A");
+        send(mbean, "A");
+        Assert.assertEquals(2, listener.changes.size());
+        Assert.assertEquals(1L, listener.changes.get(0).getSequenceNumber());
+        Assert.assertEquals(2L, listener.changes.get(1).getSequenceNumber());
+
+        // General notifications share the same sequence counter
+        mbean.addNotificationListener(listener, null, null);
+        mbean.sendNotification("message");
+        Assert.assertEquals(3, listener.sequences.size());
+        Assert.assertEquals(3L, listener.sequences.get(2).longValue());
+    }
+
     @Test
     public void testNonAttributeFilterIsNotRemovedByName() throws Exception {
         BaseModelMBean mbean = new BaseModelMBean();


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

Reply via email to