Inter-MXBean references
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:
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:
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:
Then we can navigate from this proxy to proxies for all of the product's modules:
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.
- Login or register to post comments
- Printer-friendly version
- emcmanus's blog
- 1570 reads






Comments
<p>The old HTML Adaptor (which looks like it hasn't ...
by jherbers - 2011-06-20 14:01
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?