One disadvantage of the in-source metadata approach is that the beans which can be simple Java classes when using the interface-based approach must now have Spring-specific annotations applied to their source code. The benefit that comes for this price is the ability to instruct Spring to set much more of the generated Model MBean's metadata.
The following class, ManageMe, shows an otherwise normal Java class that has the Spring-specific annotations (JDK annotations in this case, though Commons Attributes could have been used instead).
* This class's main purpose is to test and showcase Spring 2.5's support for
* annotations-based MBean exposure.
description="Example and test of Spring's support for annotations-based detail")
public class ManageMe
private String manageableString;
private boolean manageableBoolean;
private boolean anotherBoolean;
@ManagedAttribute(description="The manageableString Attribute")
public String getManageableString()
@ManagedAttribute(description="Set the manageableString Attribute")
public void setManageableString(String string)
this.manageableString = string;
@ManagedAttribute(description="Get the manageableBoolean Attribute")
public boolean isManageableBoolean()
@ManagedAttribute(description="Set the manageableBoolean Attrbiute")
public void setManageableBoolean(boolean bool)
this.manageableBoolean = bool;
@ManagedAttribute(description="Get value of another boolean")
public boolean isAnotherBoolean()
@ManagedOperation(description="Setter for another boolean")
@ManagedOperationParameter(name="bool",description="Setter for another boolean") })
public void setAnotherBoolean(boolean bool)
this.anotherBoolean = bool;
@ManagedOperation(description="Textbook Hello World example.")
public String helloWorld()
return "Hello World!";
@ManagedOperation(description="Slightly more interesting variant of Hello World")
@ManagedOperationParameter(name="subject",description="Subject of Hello") })
public String helloWorld(String subject)
return "Hello " + subject;
I set the bean class ManageMe up intentionally to expose multiple attributes and operations for comparison purposes. I intentionally annotated one of the attribute accessor methods (
setAnotherBoolean) with the
@ManagedOperationannotation rather than the normally used
@ManagedAttributeannotation. For the other attributes, I used the proper
@ManagedAttribute. I also used
@ManagedOperationon real operations that are not getter or setter methods for an attribute.
The Spring XML configuration file I used for this is shown next.
<?xml version="1.0" encoding="UTF-8"?>
<description>A JMX Service</description>
<property name="manageableString" value="springXmlDefault" />
<property name="manageableBoolean" value="false" />
<property name="assembler" ref="annotationsAssembler"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
<property name="attributeSource" ref="jmxAttributeSource"/>
<property name="attributeSource" ref="jmxAttributeSource"/>
The most interesting aspect of this XML file for our use is MBeanExporter's use of MetadataMBeanInfoAssembler and its use of AnnotationJmxAttributeSource.
Now, it is time to look at this managed bean using JConsole and see the extra provided data. Click on any screen snapshot to see a larger version of that screen snapshot.
The first screen snapshot (below) shows that the managedString attribute is both writable and readable. This is because the
@ManagedAttributeannotation was applied to both the setter and getter method for that attribute in the
ManageMeclass shown above.
Note in the screen snapshot of JConsole shown above that the description is also shown. While the Readable and Writable fields are true in this String attribute case, the Is field is false.
The next screen snapshot (below) demonstrates the JConsole output for AnotherBoolean. In this case, the field Readable is still true, but Writable is false. This is because I "mistakenly" applied an
@ManagedOperationattribute to the setter for AnotherBoolean rather than the appropriate
@ManagedAttributeannotation. Note also that the Is field is marked true because this is a boolean and the getter is correctly annotated.
The final screen snapshot (below) displays what JConsole looks like for a boolean that has both its getter (or is method) and setter set correctly with
@ManagedAttribute. As you can see in the snapshot, all three fields (Readable, Writable, and Is) are true in this case.
In all three of the above screen snapshots, you will note that there is no setAnotherBoolean listed because of the problem of misapplying
@ManagedOperationto a setter method. The other getters and setters are there because the
@ManagedAttributeannotation was properly applied to them. For completeness, you can note that
@ManagedOperationdoes work for true operations that are not actually getters or setters for attributes. The two helloWorld methods prove this.
In summary, Spring's support for metadata-configurated MBean exporting is easy to apply to garner extra exposed MBean detail. One of the most important take-aways from this blog entry is that
@ManagedAttributemust be used on getter and setter methods and that
@ManagedOperationshould be used on methods that are not getters or setters for any attributes.
One thing I did not show here is that if neither annotation is applied to a getter or setter method, it is not shown as an operation in JConsole. In other words, the only way to get a getter or setter method to show up is to use
@ManagedAttributefor each piece (once for the getter and once for the setter). If you want a read-only attribute from a JMX client perspective, apply
@ManagedAttributeto only the getter. If you want a write-only, apply that annotation only to the setter method.
Chapter 20 of the Spring 2.5 reference focuses on Spring's JMX support. Of particular interest related to this blog entry are sections 20.3.3 ("Using JDK 5.0 Annotations") and 20.3.4 ("Source-Level Metadata Types"). The latter section includes Table 20.2 ("Source-Level Metadata Types") which confirms that
@ManagedAttributeshould be applied to methods that are getters and setters for attributes while
@ManagedOperationshould be applied to all methods other than getters and setters.