Sun Microsystems
Products & Services
 
Support & Training
 
 

Previous Previous     Contents     Index     Next Next

5.6 Creating an MBean Using the instantiate Method

The last way of creating an MBean relies on the instantiate method of the MBean server. In addition, we can use a nondefault constructor to instantiate the class with a different behavior. This method is not demonstrated in the BaseAgent example, but as in Example 5-2, we instantiate and register the MBean in separate steps.

First, you instantiate the class using the instantiate method of the MBean server. This method lets you specify the constructor you want use when instantiating. Note that we could also have specified a constructor to the createMBean method in the previous example.

To specify a constructor, you must give an array of objects for the parameters and an array of strings that defines the signature. If these arrays are empty or null, the MBean server will try to use the default no-parameter constructor. If the class does not have a public no-parameter constructor, you must specify the parameters and signature of a valid public constructor.

One advantage of this creation method is that the instantiate method of the MBean server also supports class loaders. If any are registered in the MBean server, they will automatically be used if the class is not available locally. See Chapter 12, M-Let Class Loader for more information on class loading.

The main advantage of this method is that, like the first method of MBean creation, we retain a direct reference to the new object. The direct reference again enables us to use the MBean's shortcut methods explicitly.

5.7 Managing MBeans

In 5.5 Creating an MBean Using the createMBean Method, you rely totally on the MBean server to create and access an MBean. You get attributes and invoke operations through the MBean server. Here we will concentrate on the usage of MBean metadata classes when accessing MBeans that represent resources.

We will rely on the StandardAgent and DynamicAgent classes presented in Part I, Instrumentation Using MBeans. As mentioned in 2.3.1 Comparison With the SimpleStandard Example, the two are nearly identical. The same code works for any registered MBean, whether standard or dynamic. We examine the method for displaying MBean metadata that is common to both.

Example 5-3 Processing MBean Information

private MBeanServer server = null; // assigned by MBeanServerFactory

private void printMBeanInfo(ObjectName mbeanObjectName, String mbeanName) {

    echo("    using the getMBeanInfo method of the MBeanServer");
    sleep(1000);
    MBeanInfo info = null;
    try {
         info = server.getMBeanInfo(mbeanObjectName);
    } catch (Exception e) {
          echo("\t!!! Could not get MBeanInfo object for " +
               mbeanName + " !!!");
          e.printStackTrace();
          return;
    }
    echo("\nCLASSNAME: \t"+ info.getClassName());
    echo("\nDESCRIPTION: \t"+ info.getDescription());
    echo("\nATTRIBUTES");
    MBeanAttributeInfo[] attrInfo = info.getAttributes();
    if (attrInfo.length>0) {
        for(int i=0; i<attrInfo.length; i++) {
            echo(" ** NAME: \t"+ attrInfo[i].getName());
            echo("    DESCR: \t"+ attrInfo[i].getDescription());
            echo("    TYPE: \t"+ attrInfo[i].getType() +
                 "\tREAD: "+ attrInfo[i].isReadable() +
                 "\tWRITE: "+ attrInfo[i].isWritable());
        }
    } else echo(" ** No attributes **");

    echo("\nCONSTRUCTORS");
    MBeanConstructorInfo[] constrInfo = info.getConstructors();
    for(int i=0; i<constrInfo.length; i++) {
        echo(" ** NAME: \t"+ constrInfo[i].getName());
        echo("    DESCR: \t"+ constrInfo[i].getDescription());
        echo("    PARAM: \t"+ constrInfo[i].getSignature().length +
                 " parameter(s)");
    }

    echo("\nOPERATIONS");
    MBeanOperationInfo[] opInfo = info.getOperations();
    if (opInfo.length>0) {
        for(int i=0; i<constrInfo.length; i++) {
            echo(" ** NAME: \t"+ opInfo[i].getName());
            echo("    DESCR: \t"+ opInfo[i].getDescription());
            echo("    PARAM: \t"+ opInfo[i].getSignature().length +
                     " parameter(s)");
        }
    } else echo(" ** No operations ** ");

    echo("\nNOTIFICATIONS");
    MBeanNotificationInfo[] notifInfo = info.getNotifications();
    if (notifInfo.length>0) {
        for(int i=0; i<constrInfo.length; i++) {
            echo(" ** NAME: \t"+ notifInfo[i].getName());
            echo("    DESCR: \t"+ notifInfo[i].getDescription());
            String notifTypes[] = notifInfo[i].getNotifTypes();
            for (int j = 0; j < notifTypes.length; j++) {
                echo("    TYPE: \t" + notifTypes[j]);
            }
        }
    } else echo(" ** No notifications **");
}

The getMBeanInfo method of the MBean server gets the metadata of an MBean's management interface and hides the MBean's implementation. This method returns an MBeanInfo object that contains the MBean's description. We can then get the lists of attributes, operations, constructors, and notifications to display their descriptions. Recall that the dynamic MBean provides its own meaningful descriptions and that the standard MBean descriptions are default strings provided by the introspection mechanism of the MBean server.

5.8 Filtering MBeans With the Base Agent

The base agent does very little filtering because it does very little management. Usually, filters are applied programmatically to get a list of MBeans to which some operations apply. There are no management operations in the MBean server that apply to a list of MBeans. You must loop through your list and apply the desired operation to each MBean.

Before exiting the agent application, we do a query of all MBeans so that we can unregister them properly. MBeans should be unregistered before being destroyed because they might need to perform some actions before or after being unregistered. See the Javadoc API of the MBeanRegistration interface for more information.

Example 5-4 Unregistering MBeans

public void removeMBeans() {
        
        try {
            echo("Unregistering all the registered MBeans except " +
                 "the MBean server delegate\n");
            echo("    Current MBean count = " + mbs.getMBeanCount() 
                 + "\n");
            Set allMBeans = mbs.queryNames(null, null);
            for (Iterator i = allMBeans.iterator(); i.hasNext(); ) {
                ObjectName name = (ObjectName) i.next();
                if (!name.toString().equals(ServiceName.DELEGATE)) {
                    echo("\tUnregistering " + name.toString());
                    mbs.unregisterMBean(name);
                }
            }
            echo("\n    Current MBean count = " + mbs.getMBeanCount() 
                +"\n");
            echo("done\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

We use the queryNames method because we only need the object names to operate on MBeans. The null object name as a filter gives us all MBeans in the MBean server. We then iterate through the resulting set and unregister each one, except for the MBean server delegate. As we shall see in 6.1.2 MBean Server Delegate, the delegate is also an MBean and so it will be returned by the query. However, if we unregister it, the MBean server can no longer function and cannot remove the rest of our MBeans.

We recognized the delegate by its standard name which is given by the static field ServiceName.DELEGATE. The ServiceName class provides standard names and other default properties for communications and service MBeans. It also provides the version strings that are exposed by the delegate MBean. Note that, because the delegate is the only MBean created directly by the MBean server, it is the only one whose name cannot be overridden during its registration. The delegate object name is always the same, so we are always sure to detect it.

Previous Previous     Contents     Index     Next Next