Adding descriptions to JMX beans using an annotation wrapper

When working with standard JMX beans, a constant source of disappointment is the lack of descriptive information about the beans, attributes and operations.

Have a look again at how JConsole displays a bean, from my previous JMX introductory example:

JConsole view of a standard MBean

Now wouldn’t it be nice if it would look more like that:

JConsole view of a fully described MBean

Notice that attribute and operation names are now more meaningful than just some more or less cryptically Java identifiers. Also, the operation parameter to Shutdown now is correctly named, not the absolute meaningless p1 that makes any administrator scratch his head, if he doesn’t have your source code at hand.

And last but not least, there are real descriptions to all the elements in the info table!

What a pity that, though this is part of the JMX standard, it is not possible to achieve it using standard MBeans.

The only possibility is to create a so called Dynamic MBean. But this means implementing a rather complex and abstract interface and a lot of code to write for every bean.

Wouldn’t it be nice to define our example bean in a way like this?

 @JMXBean(description = "My first JMX bean test")
 public class MyBean {
    int level = 0;
    @JMXBeanAttribute(name = "Floor Level", description = "The current floor level")
    public int getLevel() {
        return level;
    }
    @JMXBeanAttribute
    public void setLevel(int newLevel) {
        level = newLevel;
    }
    @JMXBeanOperation(name = "Echo Test", description = "Echoes the parameter back to you")
    public String myMethod(
            @JMXBeanParameter(name = "Input", description = "String of what to echo") String param) {
        return "You said " + param;
    }
 }

Luckily, this is possible with a small wrapper utility that I created, named JMXWrapper.

With it, you can directly define a JMX bean through Java annotations, give descriptive names and add textual descriptions to all elements of a bean.

Notice that there is no interface definition needed anymore, any POJO (Plain Old Java Object) will do, as long as it follows the MXBean constraints, it can be turned into a dynamic JMX bean by simply adding some annotations.

You can map normal methods to attributes or operations. Read-only, write-only and read-write and boolean attributes are supported. Internal setter and getter method names do not have to follow the Java bean standard but can be any method (with one parameter for a setter and no parameter, but a return type for a getter).

And that’s not all; you can even externalize the names and descriptions and use the standard Java ResourceBundle features to localize the names and descriptions.

So it is possible to present the administration interface in the same language your application or server is running with.

Simply specify a standard Java ResourceBundle name in the JMXBean annotation and then specify name and description keys on the elements:

@JMXBean(resourceBundleName="com.example.my.package.BundleName",
    descriptionKey="myBeanDescription")
        public class MyBean {
           int level = 0;
           @JMXBeanAttribute(nameKey="level", descriptionKey="levelDescription")
           public int getLevel() {
               return level;
           }

The wrapper will automatically load locale specific translations from the resource bundle during bean creation time. If no translation can be found, the standard names and descriptions will be used.
And how do you use the wrapper? Simply drop an instance of your annotated normal Java class to the constructor of JMXBeanWrapper and register it with the JMX server:

MyBean bean = new MyBean();
JMXBeanWrapper wrappedBean = new JMXBeanWrapper(bean);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
mbs.registerMBean(wrappedBean, new Objectname("com.example.my.package:type=TestBean,name=My Bean"));

That’s all!

I have placed the code of the wrapper on GitHub. Feel free to use it, all feedbacks are welcome. I published it under the MIT Open Source License.