The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Inter-MXBean references

Posted by emcmanus on June 21, 2006 at 8:50 AM PDT

MXBeans include a way to handle inter-MBean references conveniently. You can use this to build an MBean hierarchy that is simple to navigate.

In a previous blog entry, I described MXBeans. User-defined MXBeans are a new feature in the Mustang (Java SE 6) platform. They define a type mapping, so you can use arbitrary types in the Java interface that defines your management interface, but have them mapped to a fixed set of predefined types. More details in that earlier entry.

One thing I didn't mention there is that MXBeans contain a facility for managing references between MXBeans very simply. (This facility was based on an idea by Charles Paclat of BEA.) This is probably easiest to explain by example. Suppose I have some products, and each product is composed of one or more modules. I have one MBean per product and one MBean per module. Given the MBean for a product, I would like to be able to see the MBeans for its modules, and vice versa. It looks something like this:

Product MBean referencing two Module MBeans

The corresponding MXBean interfaces might look like this:

public interface ProductMXBean {
    public Set<ModuleMXBean> getModules();
    public void addModule(ModuleMXBean module);
    public void removeModule(ModuleMXBean module);
    public String getName();
    // ...
}

public interface ModuleMXBean {
    public ProductMXBean getProduct();
    public String getName();
    // ...
}

The ModuleMXBean has an attribute called Product, defined by the getProduct() method. The declared type of that attribute is ProductMXBean, but this type will be mapped by the MXBean framework. So the actual type that a client such as jconsole will see will in fact be ObjectName. You might see something like this if you connected jconsole to this app:

JConsole showing a Module MXBean with an ObjectName in its Product attribute

The Product attribute is an ObjectName, specifically the name of the ProductMXBean.

Creating references

What might the code that created the ProductMXBean and ModuleMXBeans look like? Here's one possibility:

        // Create and register the Product
        ObjectName productName = new ObjectName("com.example.myapp:type=Product");
        ProductMXBean product = new ProductImpl("wonderprod");
        mbeanServer.registerMBean(product, productName);
        
        // Create and register the Modules and add each one to the Product
        String[] moduleIds = {"fred", "jim", "sheila"};
        for (String moduleId : moduleIds) {
            ModuleMXBean module = new ModuleImpl(moduleId, product);
            ObjectName moduleName =
                new ObjectName("com.example.myapp:type=Module,name=" + moduleId);
            mbeanServer.registerMBean(module, moduleName);
            product.addModule(module);
        }

Here we are creating the Product and its Modules all at the same time, so we are able to give the Product a direct reference to each of the Module objects and vice versa. The code in bold shows this happening. This approach assumes an intimate relationship between all the objects in question, and is most suitable if the code for creating all the MXBeans is small and centralized.

Another possibility is illustrated by rewriting the code as follows. Only the code in bold below has changed.

        // Create and register the Product
        ObjectName productName = new ObjectName("com.example.myapp:type=Product");
        ProductMXBean product = new ProductImpl("wonderprod");
        mbeanServer.registerMBean(product, productName);
        ProductMXBean productProxy =
            JMX.newMXBeanProxy(mbeanServer, productName, ProductMXBean.class);
        
        // Create and register the Modules and add each one to the Product
        String[] moduleIds = {"fred", "jim", "sheila"};
        for (String moduleId : moduleIds) {
            ModuleMXBean module = new ModuleImpl(moduleId, productProxy);
            ObjectName moduleName =
                new ObjectName("com.example.myapp:type=Module,name=" + moduleId);
            mbeanServer.registerMBean(module, moduleName);
            ModuleMXBean moduleProxy =
                JMX.newMXBeanProxy(mbeanServer, moduleName, ModuleMXBean.class);
            product.addModule(moduleProxy);
        }

The coupling between the Product and its Modules is much looser because each only knows the ObjectName of the other, and not the object itself as before. The Modules could have been created in one place in the code and the Product somewhere else entirely, and they would only have had to agree on the ObjectNames.

Navigating the MXBean hierarchy

The real power of this approach comes when you are coding a client that interacts with this model.

You can construct a proxy for an MXBean using the new method JMX.newMXBeanProxy. If you have a proxy for a ModuleMXBean, say, then it is an object of type ModuleMXBean. If you call its getName() method, that will result in a call to MBeanServerConnection.getAttribute(moduleObjectName, "Name"). Very handy.

But the ModuleMXBean interface also has this method:
ProductMXBean getProduct();
What does it return when you call it on a ModuleMXBean proxy?

You might have guessed the answer. It returns another proxy, this time for the ProductMXBean.

Suppose we known the ObjectName of a ModuleMXBean, and we want to find the names of all the modules in the same product. We can do this by starting with a proxy for the ModuleMXBean and using it to obtain a proxy for its ProductMXBean:

Navigating from the ModuleMXBean to its ProductMXBean

Then we can navigate from this proxy to proxies for all of the product's modules:

Navigating from the ProductMXBean to its ModuleMXBeans

In code, finding the names of all the modules given just the ObjectName of one module looks like this:

        ModuleMXBean startModuleProxy =
            JMX.newMXBeanProxy(mbeanServerConnection, startModuleName,
                               ModuleMXBean.class);
        ProductMXBean containingProduct = startModuleProxy.getProduct();
        Set<ModuleMXBean> modules = containingProduct.getModules();
        for (ModuleMXBean module : modules)
            System.out.println(module.getName());

The ability to navigate through the MBean model using proxies is a very powerful one, and a strong incentive to use this approach to managing references between MBeans.

Related Topics >> Open JDK      
Comments
Comments are listed in date ascending order (oldest first)