Skip to main content

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 href="http://weblogs.java.net/blog/emcmanus/archive/2006/02/what_is_an_mxbe.html">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 src="http://weblogs.java.net/blog/emcmanus/archive/mxbeanref.png"
width="550" height="401" />

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 src="http://weblogs.java.net/blog/emcmanus/archive/jconsole-mxbeanref.png"
width="548" height="325" />

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 href="http://download.java.net/jdk6/doc/api/javax/management/JMX.html#newMXBeanProxy(javax.management.MBeanServerConnection,%20javax.management.ObjectName,%20java.lang.Class)">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 src="http://weblogs.java.net/blog/emcmanus/archive/module-getproduct.png"
width="621" height="348" />

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

Navigating from the ProductMXBean to its ModuleMXBeans src="http://weblogs.java.net/blog/emcmanus/archive/product-getmodules.png"
width="621" height="381" />

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 >>

Comments

<p>The old HTML&nbsp;Adaptor (which looks like it hasn't ...

The old HTML Adaptor (which looks like it hasn't been updated in a decade) displays inter MBean references as links which can be used to navigate as you describe programmatically above. But JConsole doesn't seem to do this, nor the newer superset replacement, Visual VM. Are we missing something or is this a real lack of functionality from these tools?