Adding descriptions to JMX beans using an annotation wrapper
November 13, 2012 14 Comments
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:
Now wouldn’t it be nice if it would look more like that:
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.
Excellent approach. Thanks! Do you know how I can set default values to the MBean operations’ parameters?
Thank you very much. Setting the default values for an operation is not possible with my current implementation. But in general, it is possible to set it through the descriptor of the MBeanParameterInfo. In my code, I create the parameter info through:
MBeanParameterInfo pInfo = new MBeanParameterInfo(paramName, paramType, paramDescription)
.There is another constructor that allows to pass a
javax.management.Descriptor
to the constructor.This could be an instance of
javax.management.DescriptorSupport
orjavax.management.ImmutableDescriptor
.Here you can set the default values for operation parameters:
Descriptor descriptor = new DescriptorSupport();
descriptor.setField("default","123");
MBeanParameterInfo pInfo = new MBeanParameterInfo(paramName, paramType, paramDescription, descriptor);
I haven’t tested it, but it should work from what the specification and JavaDoc says.
Hi there. Great solution to a really annoying problem !! Now I can use the Jmx console because I can put a name in front of each method parameter ;)
Thanks a lot.
Thank you, that is exactly why I created it.
Hi,
Thank you very much for very useful post. I am looking for a some way to automate MXBeans with annotations, I dont want use MXBeans interfaces and class implementing MXBean interface instead I want to directly define MXBean attributes directly from java class.
I am looking for something like this.
@MXBean
public class Foo
{
// In JMX Console
@MXBeanattribute
private boolean isBar;
// Not in JMX Console
private boolean isFoo;
// In JMX Console
@MXBeanattribue
public String getClassName()
{
return Foo.class.getName();
}
}
can you please give me some suggestions/ideas on this,is there anyway to do this without using dynamicMbean and using JMX/MXBeans.
Thank you.
Thanks Razz,
if you want to achieve this, you can use my solution. It does exactly what you want: https://github.com/uklimaschewski/JMXWrapper
It creates automatically a dynamic MBean for you out of a normal Java class.
Apart of the J2EE based Spring JMX annotation tool, I know of no other solution.
(The standard Java annotation implementation that was promised in JDK7 was postponed, and there is not much happening there, AFAIK.)
MBeans and MXBeans will always require the declaration of an interface and an implementation class.
Thank you very much for your reply. I have few questions, can you please clarify.
As MXBean restircts the data types, so that they are “more compatible” with potential clients, I thought of introducing JMX using MXBean into project I am working with. But I am finding difficulties on automation using MXBean.
From your last I understood that automation can be only achived with dynamic MBean and not with MXBean/MBean.
can you point me some pros/cons between dynamicMbean vs MXBean.
From my reading I found that MXBean is useful in restricting exposure of data types/clasees with clients.
is dynamicMBean has any cons in the context of restirction of the data types/classes exposure with clients.
Thanks again.
Thank you very much for your reply. I have few questions, can you please clarify.
As MXBean restircts the data types, so that they are “more compatible” with potential clients, I thought of introducing JMX using MXBean into project I am working with. But I am finding difficulties on automation using MXBean.
From your last I understood that automation can be only achived with dynamic MBean and not with MXBean/MBean.
can you point me some pros/cons between dynamicMbean vs MXBean.
From my reading I found that MXBean is useful in restricting exposure of data types/clasees with clients.
is dynamicMBean has any cons in the context of restirction of the data types/classes exposure with clients.
Thanks again.
Hi Udo,
Very useful post indeed. Question! Were you able to control the order of presentation of the Operations of an MBean in JConsole or Java VisualVM ?
Thanks!
Thank you very much. Yes, the latest version on GitHub now has a feature to sort attributes and operations, either by name or in a custom order.
See https://github.com/uklimaschewski/JMXWrapper for a description on how to do this.
Awesome Udo! This is great. Thanks you very much!
Thank you Udo. Just tested the wrapper and was amazed by it’s greateness! No more parameter p0, p1 in jconsole.
Thanks you! :-)
Thanks a lot for this JMX wrapper ! this makes things clearer in the console AND in the code