JDK-6598156 : Notification: receive duplicated notifications
  • Type: Bug
  • Component: core-svc
  • Sub-Component: javax.management
  • Affected Version: 6u10
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_9
  • CPU: sparc
  • Submitted: 2007-08-28
  • Updated: 2010-07-29
  • Resolved: 2008-06-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Duplicate :  
Description
A singleton mbean is repeatedly registered/unregistered, a listener needs to receive notifications from the mbean so it is added to the mbean every time the mbean is registered, suppose that the mbean is to be registered 10th time, then each notification the mbean sends out will be received 10 times by the listener. 

Here is the test code:

import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

public class Test {
    public static void main(String[] args) throws Exception {
        MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
        ObjectName emitter = new ObjectName("Default:name=NotificationEmitter");
        
        JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
        JMXConnectorServer server =
                JMXConnectorServerFactory.newJMXConnectorServer(url,
                null, mbeanServer);
        server.start();
        
        url = server.getAddress();
        
//        Map env = new HashMap(1);
//        env.put("jmx.remote.x.enable.event.service", "true");
//        JMXConnector conn = JMXConnectorFactory.connect(url, env);
        JMXConnector conn = JMXConnectorFactory.connect(url);
        
        NotificationEmitter emitterImpl = new NotificationEmitter();
        
        mbeanServer.registerMBean(emitterImpl, emitter);
        
        MyListener directL = new MyListener();
        conn.getMBeanServerConnection().addNotificationListener(emitter,
                directL, null, null);
        
        emitterImpl.sendNotif(1, null);
        
        for (int i=0; i<10; i++) {
            mbeanServer.unregisterMBean(emitter);
            mbeanServer.registerMBean(emitterImpl, emitter);
            Thread.sleep(10);
        }

        conn.getMBeanServerConnection().addNotificationListener(emitter,
                directL, null, null);
        
        emitterImpl.sendNotif(1, null);
        
        Thread.sleep(100);
        if (directL.received != 2) {
            throw new RuntimeException("Expected to receive 2, but got "+
                    directL.received);
        }
        
        mbeanServer.unregisterMBean(emitter);
    }
    
//--------------------------
// private classes
//--------------------------
    
    private static class MyListener implements NotificationListener {
        public void handleNotification(Notification notif, Object handback) {
            System.out.println("---MyListener-handleNotification "+notif.getSequenceNumber());
            received++;
        }
        
        private int received = 0;
    }
    
    public static class NotificationEmitter extends NotificationBroadcasterSupport
            implements NotificationEmitterMBean {
        
        /**
         * Send Notification objects.
         *
         * @param nb The number of notifications to send
         */
        public void sendNotif(int nb, String userData) {
            for (int i = 0; i<nb; i++) {
                Notification notif = new Notification(myType, this, counter++);
                notif.setUserData(userData);
                sendNotification(notif);
            }
        }
        
        public int counter = 0;
        private final String myType = "notification.my_notification";
    }
    
    public interface NotificationEmitterMBean {
        public void sendNotif(int nb, String userData);
    }
}

The test result is:

---MyListener-handleNotification 0
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 0
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
---MyListener-handleNotification 1
Exception in thread "main" java.lang.RuntimeException: Expected to receive 2, but got 12
        at Test.main(Test.java:65)

Comments
EVALUATION The description has pointed out the cause. Until now no user gets this problem, it means that to repeat registering/unregistering an MBean is not often at all. So we can fix the bug in JDK7 which we will have the event service, the event service will have a different way to collect mbean notifications.
21-05-2008

EVALUATION Today's internal notification mechanic adds always its one listener to an NotificationBroadcaster MBean when the mbean is registered, but it has no way to remove its listener when the mbean is unregistered, so the listener will be kept by the mbean implementation till the mbean GCed. When the mbean is re-registered (not createMBean), the notification mechanic will add again the same listener to the mbean, so one notification will be received 2 times. We can try to remove the listener before add the listener to the mbean every time we receive a REGISTRATION_NOTIFICATION of this the mbean. This will be fixed in JDK1.7 with the event service
29-08-2007