|
|
||
Eamonn McManus's BlogRemoving getters from Model MBean operationsPosted by emcmanus on February 13, 2007 at 06:43 AM | Comments (1)One curiosity about Model MBeans is that attributes also appear as operations. Is there any way to avoid that? We encounter this question occasionally, most recently in the JMX forum on SDN. As the contributor there notes, this is tracked as RFE 6339571, but won't be implemented until Java SE 7. What can you do in the mean time? In order to define an attribute, say The The answer is yes, via a hack. We can tweak the serialization
of this MBeanInfo so that operations like We'll define a subclass of ModelMBeanInfoSupport
called NoGetterMBeanInfo, and add a writeReplace
method to this class. The writeReplace method can return a
different object to be serialized in the place of the original
one. Instead of serializing a NoGetterMBeanInfo, which would
require a client such as JConsole to know that class, we can
serialize a ModelMBeanInfoSupport. Since that's a standard class,
every client must know it. And we can arrange for this new
ModelMBeanInfoSupport not to contain any getter methods like
We identify getter methods by their Descriptor:
if the Descriptor contains a Here then is the code for NoGetterMBeanInfo:
import java.util.ArrayList;
import java.util.List;
import javax.management.Descriptor;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
public class NoGetterMBeanInfo extends ModelMBeanInfoSupport {
public NoGetterMBeanInfo(ModelMBeanInfo mmbi) {
super(mmbi);
}
@Override
public NoGetterMBeanInfo clone() {
return new NoGetterMBeanInfo(this);
}
private Object writeReplace() {
List
To use it, change code where you do something like this... ModelMBean mbean = new RequiredModelMBean(myModelMBeanInfo); ...into this... ModelMBean mbean = new RequiredModelMBean(new NoGetterMBeanInfo(myModelMBeanInfo)); Of course this hack will only work if you are using a connector
that is based on Java object serialization, such as the RMI
connector that is part of the Java platform. If you are using a
SOAP-based connector, say, then you will need to look at how to
achieve the same result in that context. (One possibility is to
insert an MBeanServerForwarder
that intercepts a remote The forum question asked about how to do this in the context of Spring; since Spring uses Model MBeans the question arises frequently. I was able to plug in the NoGetterMBeanInfo by using a custom MBeanExporter like this:
import javax.management.JMException;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBean;
import javax.management.modelmbean.ModelMBeanInfo;
import org.springframework.jmx.export.MBeanExporter;
public class NoGetterExporter extends MBeanExporter {
public NoGetterExporter() {
}
@Override
protected void doRegister(Object mbean, ObjectName objectName) throws JMException {
if (mbean instanceof ModelMBean) {
ModelMBean mmb = (ModelMBean) mbean;
ModelMBeanInfo mmbi = (ModelMBeanInfo) mmb.getMBeanInfo();
mmb.setModelMBeanInfo(new NoGetterMBeanInfo(mmbi));
}
super.doRegister(mbean, objectName);
}
}
You probably already have an MBeanExporter in your Spring configuration file, with lines looking something like this:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
...
</bean>
You should just be able to change the MBeanExporter class name to the fully-qualified name of NoGetterExporter. NoGetterMBeanInfo is a hack, but I hope it's a useful one! Bookmark blog post: CommentsComments are listed in date ascending order (oldest first) | Post Comment
| ||
|
|