Spring provides a nice way to expose plain java objects and its
methods and properties as JMX managed objects. Maybe the best way to do
so is using annotations.
@ManagedResource(
objectName = "domain:name=testBean",
description = "A test Spring-JMX bean")
public class JmxTestBean {
private int age;
private String name;
@ManagedAttribute(description = "age attribute")
public void setAge(int age) {
logger.info("setAge");
this.age = age;
}
@ManagedAttribute(description = "age attribute")
public int getAge() {
logger.info("getAge");
return age;
}
@ManagedAttribute(description = "name attribute")
public void setName(String name) {
logger.info("setNamee");
this.name = name;
}
@ManagedAttribute(description = "name attribute")
public String getName() {
logger.info("getName");
return name;
}
public String dontExposeThisMethod() {
return "dontExposeThisMethod return";
}
@ManagedOperation(description = "method exposed")
public String exposeThisMethod() {
return "exposeThisMethod return";
}
}
In the application context you need
<bean id="jmxAdapter.parent" class="org.springframework.jmx.export.MBeanExporter" abstract="true">
<property name="autodetect">
<value>true</value>
</property>
<property name="assembler">
<ref local="metadataMBeanInfoAssembler"/>
</property>
<property name="namingStrategy">
<ref local="namingStrategy"/>
</property>
</bean>
<!-- Use metadata to filter the exposed operations and attributes -->
<bean id="metadataMBeanInfoAssembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource">
<ref local="annotationJmxAttributeSource"/>
</property>
</bean>
<bean id="annotationJmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource">
<ref local="annotationJmxAttributeSource"/>
</property>
</bean>
<bean id="testBean" class="com.arcmind.springjmx.JmxTestBean">
<property name="name">
<value>TEST</value>
</property>
<property name="age">
<value>100</value>
</property>
</bean>
For testing you’d need to explicitly set the mbean server
<bean id="jmxAdapter" parent="jmxAdapter.parent">
<property name="server">
<ref local="mbeanServer"/>
</property>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
For deploying it gets autodetected
<bean id="jmxAdapter" parent="jmxAdapter.parent"/>
Other options for the assembler property are
<!-- Expose everything through reflection -->
<bean id="simpleReflectiveMBeanInfoAssembler" class="org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler"/>
<!-- Use method names to filter the exposed operations and attributes -->
<bean id="methodNameBasedMBeanInfoAssembler" class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
<property name="managedMethods">
<list>
<value>exposeThisMethod</value>
<value>getAge</value>
<value>setAge</value>
<value>getName</value>
<value>setName</value>
</list>
</property>
</bean>
<!-- Expose only those methods in the interfaces implemented by the bean -->
<bean id="interfaceBasedMBeanInfoAssembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"/>
But then you may need to explicitly say what beans you want to
expose instead of autodetecting them in the jmxAdapter.parent bean.
<property name="beans">
<map>
<entry key="bean:name=testBean1">
<ref local="testBean"/>
</entry>
</map>
</property>