Advanced JMX (1) - Notifications

October 2nd, 2007 Radim Marek Posted in Java |

Since the release as part of Java 5 (formerly called J2SDK 5.0) the Java Management Extensions proved to be effective tool for management of the application systems and intercommunication between the various software components. JBoss AS’ kernel itself relies on JMX as the integration bus into which various components plug.

Although there are many developers successfully using JMX, general knowledge often doesn’t cover more advanced aspects of this technology. This is a first part of my series to shed light on not so common parts of the specification and hopefully help you to take advantage of it and understand some aspects of systems build on top of JMX. First part of this series is dedicated to ability of MBean to broadcast management events to its listeners, called notifications.

JMX notification model

The basic unit of information covered by this model is a notification. It’s an instance of the class javax.management.Notification or one of the subclasses. A notification identifies itself by its type (characterises of a generic notification object), reference to the source MBean and the sequence number of a particular occurrence. Optional information includes time stamp and a text message. Custom information demanded by notification can be attached using setUserData method.

Following example demonstrates creation of a notification:


    return new Notification("Vendor.JMXDemo.eventType1",
                    this,
                    sequence++,
                    System.currentTimeMillis(),
                    "Notification from JMX Demo application");

Notification type is a String interpreted as any number of dot-separated components for controlled naming structure of notifications. All notification types prefixed by JMX. are reserved events emitted by JMX infrastructure.

Broadcasting notifications

In order to allow broadcasting of the notifications, your MBean has to extend either interface NotificationBroadcaster or NotificationEmitter. Both interfaces give you ability to emit notifications and provide interface for registration/removal of the listeners. NotificationEmitter adds additional functionality for removing listeners.

Helper class NotificationBroadcasterSupport provides implementation of NotificationEmitter and introduces mode for dispatching notifications. Most of the application would require only the level of control/functionality provided by this helper class and following text will assume so.

Although it’s not mandatory by specification, every managed bean to emit notifications should implement method getNotificationInfo which returns an array indicating class name and description (represented by instance of MBeanNotificationInfo) for each notification MBean may send. By default NotificationBroadcasterSupport class returns an empty array.

Code demonstrating simple emitter would look like


    public class JMXDemo extends NotificationBroadcasterSupport implements DemoMBean {
        private long sequenceNumber = 0;        

        public JMXDemo() {}
        public void doSomething() {
            // ... component code ...
            if (someCondition) {
                sendNotification(createEvent1Notification(someData));
            }
        }        

        private Notification createEvent1Notification(...) {
            return new Notification(....);
        }        

        public MBeanNotificationInfo[] getNotificationInfoaa() {
            String[] notifications = new String[] {
                "Vendor.JMXDemo.eventType1"
            };        

            MBeanNotificationInfo[] info = {
                new MBeanNotificationInfo(notifications,
                    "javax.management.Notification",
                "First notification example")
            };        

            return info;
        }
    }

Private field sequenceNumber is used to keep maintain unique sequence numbers, as stated in previous section.

Respective emission of the notification is performed by the method sendNotification and in this example it’s subject to the custom condition (in real-life application it could be for example checking of usage level of monitored resource), but it’s of course fully in developer’s decision when the notification should be emitted, to meet functional specification.

Receiving notifications

A class that requests to receive notifications sent by MBean – notification listener – has to implement interface NotificationListener which defines call-back method handleNotification invoked by broadcaster MBean when it emits a notification.

Method signature is following:


    void handleNotification(Notification notification, Object handback)

Where handback is a reference to the object provided during registration of listener, returned back to the listener to provide mechanism to establish appropriate context when a notification arrives. This functionality allows subscription to multiple managed bean emitting same types of the notifications.


    public void handleNotification(Notification notification, Object handback) {
        if (handback.equals(DEMO_CONTEXT)) {
            log.debug("Test Notification " + notification);
        } else if (handback.equals(SERVICE_CONTEXT)) {
            storeNotificationToDB(notification);
        }
    }

In this example the notification received within DEMO_CONTEXT (String) are logged, whereas the ‘real-life’ SERVICE_CONTEXT notifications are saved to persistent storage.

Registering listener

Once the client application is connected to the agent application and has obtained MBeanServerConnection reference, it can register a listener using methods addNotificationListener.

This method accepts following arguments:

  • ObjectName sourceMBean – the name of MBean listener wants to be registered
  • Target object – reference to the class that implements NotificationListener interface, or ObjectName reference to MBean which will handle emitted notifications. Based no reference passed appropriate method call will be selected.
  • Optional argument NotificationFilter in order to perform filtering (see below) of incoming notifications. Otherwise null to be supplied.
  • Object handback – context to be sent back to the listener when a notification is emitted.

If both source and target objects meet registration conditions (valid object names/listener implements NotificationListener interface) and communication to server is successful, the listener is registered and will start to receive emitted notifications.

Filtering notifications

Objects can act as filters of the emitted notification if they do implement NotificationFilter
interface. The listener which has got filter specified when registering will be called to handle notification only in case the filter’s isNotificationEnabled method returns positive response (true).


    boolean isNotificationEnabled(Notification notification)

Attribute change notifications

Class AttributeChangeNotification is one of the predefined notification subclasses, used to notify listener when the value of a managed bean attribute changes.

Unfortunately there is no logic provided by JMX and it is responsibility of MBean developer to send notifications when an attribute change occurs. Most common usage is to send notification within setter method.


    public void setStatus(int status) {
        sendNotification(new AttributeChangeNotification(this,
                    sequenceNumber++,
                    System.currentTimeMillis(),
                    "status changed",
                    "status",
                    "int",
                    this.status,
                    status));
            this.status = status;
        }

Constructor is similar to Notification with additional information about attribute name, type and old and new value.

Special class AttributeChangeNotificationFilter is available for filtering attribute change notifications by implicitly disabling/enabling of selected or all attributes. Example below demonstrates filter for listener interested only in the change notifications regarding attribute ’status’.


    filter = new AttributeChangeNotificationFilter();
    filter.disableAllAttributes();
    filter.enableAttribute("status");

Leave a Reply