How Can I Find All Instances Of WombatMBean?

Here is a small example that demonstrates how to retrieve all MBeans which are wombats, including domestic wombats and feral wombats, which are very ferocious.

The question here is to find out a way to retrieve all MBeans which extend a base MBean class (in our example Wombat) or whose MBean interface extends a base MBean interface (in our example WombatMBean). The most efficient way to query for MBeans is to use an ObjectName pattern. If you follow the recommended MBean Naming Scheme, then all your MBeans will have a 'type' key indicating their type.

A wombat... You could therefore arrange for a clever naming scheme that would allow you to retrieve all instances of Wombat with a single ObjectName pattern. However, complex class hierarchies are something that cannot be completely modeled by an ObjectName. If your class hierarchy is simple, you might get away by saying that all your wombats will have a type key whose value ends with Wombat. That way, you will be able to say that all MBeans in your domain which have a type key assignement of the form type=Wombat or type=DomesticWombat or type=FeralWombat are all wombats. However this will not lead you much farther.

With JDK 6, an alternative solution is to use a Query.isInstanceOf. This query was added in JDK 6, so with JDK 5 you might need to loop as shown in the code example below. Note that in both these cases, if your MBeans are DynamicMBeans (for instance, if you're using javax.management.StandardMBean) - you will need to take some precautions with regard to class loading.

The extract of code below illustrates the three methods outlined above. It also illustrate how to instantiate a StandardMBean in such a way that isInstanceOf will work. See javax.management.StandardMBean: When And Why for more information on this baroque issue.

The last solution (not demonstrated here) would be to code a metadata service that would know about the class hierarchy and would be able to perform such 'educated' queries. This might be an additional feature for JMX 2.0.
The code example below only shows the simpler alternatives that you can implement and use today.

Cheers,
-- daniel

    
/\*
 \* InstanceOfExample.java
 \*
 \* Created on March 14, 2007, 4:40 PM
 \*
 \* SCCS: %W%
 \* Copyright (c) Sun Microsystems, 2007 - All rights reserved.
 \*/

package instanceofpkg;

import java.lang.management.ManagementFactory;
import java.util.logging.Logger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.StandardMBean;

/\*\*
 \* Class InstanceOfExample
 \* @author Sun Microsystems, 2005 - All rights reserved.
 \*/
public class InstanceOfExample {
    
    /\*\*
     \* A logger for this class.
     \*\*/
    private static final Logger LOG =
            Logger.getLogger(InstanceOfExample.class.getName());
    
    /\*\* Creates a new instance of InstanceOf \*/
    public InstanceOfExample() {
    }
    
    // ---------------------------------------------------------
    // A Wombat MBean...
    //
    public static interface WombatMBean {
        public String getDescription();
    }
    public static class Wombat implements WombatMBean {
        public String getDescription() { return "I am a wombat"; }
        
    }
    
    // ---------------------------------------------------------
    // A subclass of Wombat. It's also a WombatMBean...
    //
    public static class TypedWombat extends Wombat { 
        public TypedWombat(String wombatType) {
            type=wombatType;
        }
        final String type;
        public String getDescription() { 
            return "I am a "+
                ((type==null)?"":(type+" "))+ "wombat";
        }
        public final String getKind() {
            return type;
        }
    }
    
    // ---------------------------------------------------------
    // A DomesticWombat. It has a pet name. Ours is called "Totor"...
    //
    public static interface DomesticWombatMBean extends WombatMBean {
        public String getPetName();
    }
    
    public static class DomesticWombat extends TypedWombat
        implements DomesticWombatMBean {
        public DomesticWombat() {
            super("domestic");
        }
        public String getPetName() { return "Totor"; }
    }
    
    // ---------------------------------------------------------
    // A FeralWombat. Those are very ferocious. Never mess with 
    // them...
    //
    public static interface FeralWombatMBean extends WombatMBean {
        public boolean isFerocious();
    }
    
    public static class FeralWombat  extends TypedWombat
            implements FeralWombatMBean {
        public FeralWombat() {
            super("feral");
        }
        public  boolean isFerocious() { return true; }
    }
    
    // ---------------------------------------------------------
    
    /\*\*
     \* A method that demonstrate various possibilities...
     \*
     \* @param args the command line arguments
     \*/
    public static void main(String[] args) throws Exception {

        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        
        // We can decide that all our wombat type names end with "Wombat".
        // This will enable us to get all instance of Wombat with a simple
        // ObjectName pattern: "australia:\*,type=\*Wombat"
        //
        final ObjectName wombatName = 
                new ObjectName("australia:type=Wombat,name=anonymous");
        final ObjectName typedName = 
                new ObjectName("australia:type=Wombat,name=strange");
        final ObjectName domesticName = 
                new ObjectName("australia:type=DomesticWombat,name=Totor");
        final ObjectName feralName = 
                new ObjectName("australia:type=FeralWombat,name=SuperWombat");
        
        // We can also use isInstanceOf(), but there's a catch. We need to
        // use a subclass of StandardMBean loaded by a ClassLoader that can
        // also load our wombat classes. An easy (though probably not optimal
        // way to do that is to add a trailing {} to new StandardMBean(...)
        //
        // Notice the {} in 'new StandardMBean(...){}'  below...
        //
        // A better way would be to declare a:
        //
        // public static class WombatStandardMBean extends StandardMBean {
        //     public WombatStandardMBean(....) {
        //            super(...);
        //     }
        // }
        //
        // and use that. I was too lazy to do it ;-\\
        //
        server.registerMBean(new StandardMBean(new Wombat(),WombatMBean.class){},wombatName);
        server.registerMBean(new StandardMBean(new TypedWombat("strange"),WombatMBean.class){},typedName);
        server.registerMBean(new StandardMBean(new DomesticWombat(),DomesticWombatMBean.class){},domesticName);
        server.registerMBean(new StandardMBean(new FeralWombat(),FeralWombatMBean.class){},feralName);
        
        // Method 1: use an ObjectName pattern. This is possible in our case
        //     because we have taken care that all our Wombat instances are
        //     named "type=XxxxWombat". 
        // However, using such a simple naming pattern may not always be 
        // feasible. In particular, if we have a deep class hierarchy.
        // For instance, we wouldn't be able to get all instance of 
        // "TypedWombat" in this way.
        //
        System.out.println("query with pattern: "+
                server.queryNames(new ObjectName("australia:\*,type=\*Wombat"), 
                null));
        
        // Method 2: use queryNames with an isInstanceOf query.
        // This works only on JDK 6 because that's when Query.isInstanceOf was added.
        //
        //
        // We pass a query that will call isInstanceOf() for each selected
        // MBean... This works - provided that DynamicMBeans have been properly
        // instantiated.
        //
        // This method would allow us to query for all "TypedWombat" too...
        //
        final String className = WombatMBean.class.getName();
        
        System.out.println("query with isInstanceOF: "+
                server.queryNames(new ObjectName("australia:\*"), 
                Query.isInstanceOf(Query.value(className))));
        
        // Method 3: use queryNames with a wildcard, then check
        //    whether the MBean match our expectation. Here we call
        //    isInstanceof(), but we could also have tried to analyze
        //    its MBeanInfo, for instance...
        //
        // We call server.isInstanceOf() for each selected
        // MBean... This works - provided that DynamicMBeans have been properly
        // instantiated.
        // This method works also on JDK 5
        //
        System.out.println("loop...");
        for (ObjectName n:server.queryNames(new ObjectName("australia:\*"), null)) {
             if (server.isInstanceOf(n,className)) 
                System.out.println(n+" is a "+className);
        }
    }
    
}
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Daniel Fuchs blogs on Scene Builder, JMX, SNMP, Java, etc...

The views expressed on this blog are those of the author and do not necessarily reflect the views of Oracle.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today