Java Dynamic Management Kit 5.1 Tutorial

8.2 MBean Server Delegate Notifications

The MBean server delegate object is an MBean that is automatically created and registered when an MBean server is started. It preserves the management model by serving as the management interface for the MBean server. The delegate exposes read-only information such as the vendor and version number of the MBean server. More importantly for this chapter, it sends the notifications that relate to events in the MBean server: all MBean registrations and unregistrations generate a notification.

8.2.1 NotificationEmitter Interface

A class must implement the NotificationEmitter interface to be recognized as a source of notifications in the JMX architecture. This interface provides the methods for adding or removing a notification listener to or from the emitter. When the emitter sends a notification, it must send it to all listeners that are currently registered through this interface.

This interface also specifies a method that returns information about all notifications that might be sent by the emitter. This method returns an array of MBeanNotificationInfo objects, each of which provides a name, a description string, and the type string of the notification.

As detailed in the Javadoc API, the MBeanServerDelegate class implements the NotificationEmitter interface. We know from the JMX specification that it sends notifications of the following types:


Note –

Although emitter objects are almost always MBeans, they should not expose the methods of the NotificationEmitter interface. That is, the MBean interface of a standard MBean should never extend the NotificationEmitter interface. As we shall see in Chapter 22, Notification Forwarding in Legacy Connectors, the remote connector clients provide the methods needed to register for and receive notifications remotely.


The NotificationEmitter should be used in preference to the old NotificationBroadcaster class.

8.2.2 NotificationListener Interface

Listeners must implement the NotificationListener interface, and they are registered in the notification broadcasters to receive the notifications. The listener interface defines a handler method that receives all notifications of the broadcaster where the listener is registered. We say that a listener is registered when it has been added to the broadcaster's list of notification recipients. This is completely independent of any registration of either object in the MBean server.

Like the broadcaster, the listener is generic, meaning that it can handle any number of different notifications. Its algorithm usually involves determining the type of the notification and taking the appropriate action. A listener can even be registered with several broadcasters and handle all of the notifications that are sent.


Note –

The handler is a callback method that the broadcaster calls with the notification object it wants to send. As such, it runs in the broadcaster's thread and should therefore run rapidly and return promptly. The code of the handler should rely on other threads to execute long computations or blocking operations.


In our example, the listener is a trivial class that has a constructor and the handler method. Our handler simply prints out the nature of the notification and the name of the MBean to which it applied. Other listeners on the agent side might themselves be MBeans that process the event and update the state of their resource or the quality of their service in response. For example, the relation service must know when any MBeans participating in relations are unregistered. It does this by listening to MBean server delegate notifications.


Example 8–1 Listener for MBean Server Delegate Notifications

import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.MBeanServerNotification;

public class AgentListener implements NotificationListener {

         public AgentListener() {
         }    

         public void handleNotification(Notification n,
                                   Object h) {

        // Process the different types of notifications fired by the
        // MBean server delegate.
        String type = n.getType();

         try {
            if (type.equals(
                    MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
                    echo("\t>> \"" +
                        ((MBeanServerNotification) n).getMBeanName() +
                        "\" has been registered in the server");
                 } else if (type.equals(
                    MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
                     echo("\t>> \"" +
                          ((MBeanServerNotification)n).getMBeanName() +
                          "\" has been unregistered from the server\n");
                 } else {
                      echo("\t>> Unknown event type (?)\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

In most cases, the notification object passed to the handler method is an instance of the Notification class. This class provides the notification type as well as a time-stamp, a sequence number, a message string, and user data of any type. All of these are provided by the broadcaster to pass any needed information to its listeners. Because listeners are usually registered through the MBean server, they only know the broadcaster by its object name, given by the getSource method of the notification object.


Note –

The notification model does not assume that notifications will be received in the same order that they are sent. If notification order is critical to your application, your broadcaster should set the sequence numbers appropriately, and your listeners should sort the received notifications.


The MBean server delegate sends MBeanServerNotification objects that are subclasses of the Notification class. This subclass provides two constants to identify the notification types sent by the delegate and a method that gives the object name of the MBean that was registered or unregistered. Our notification handler uses these to print out the type of operation and the object name to which the operation applies.

8.2.3 Adding a Listener Through the MBean Server

Now that we have identified the objects involved, we need to add the listener to the notification broadcaster. Our example does this in the main method of the agent application.


Example 8–2 Registering for MBean Server Delegate Notifications

AgentListener agentListener = null;
[...]

echo("\nRegistering the MBean server delegate listener...");
try {
    agentListener = new AgentListener();
    myAgent.server.addNotificationListener(
        new ObjectName(ServiceName.DELEGATE),
        agentListener, null, null);
} catch(Exception e) {
    e.printStackTrace();
    System.exit(1);
}
echo("done");

In Example 8–2, the agent application adds the AgentListener instance to the delegate MBean, which is known to be a broadcaster. The object name of the MBean server delegate is given by the DELEGATE constant in the ServiceName class. The listener is added through the addNotificationListener method of the MBean server. This method preserves the management architecture by adding listeners to MBeans while referring only to the MBean object names.

If an MBean implements the listener interface and needs to receive certain notifications, it can add itself to a broadcaster. For example, an MBean could use its preregistration method in order to add itself as a notification listener or it could expose a method that takes the object name of the notification broadcaster MBean. In both cases, its notification handler method must be designed to process all expected notification types.

The last two parameters of the addNotificationListener methods of both the MBeanServer and the NotificationBroadcaster interfaces define a filter and a handback object, respectively. Filter objects are defined by the NotificationFilter interface and provide a callback method that the broadcaster calls before calling the notification handler. If the filter is defined by the entity that adds the listener, it prevents the handler from receiving unwanted notifications.

Handback objects are added to a broadcaster along with a listener and are returned to the designated handler with every notification. The handback object is completely untouched by the broadcaster and can be used to transmit context information from the entity that adds the listener to the handler method. The functionality of filters and handback objects is beyond the scope of this tutorial; refer to the JMX specification for their full description.