Support for @JMX on attributes
alesj Jun 20, 2008 7:30 AMTim raised this question on MC user forum:
- http://www.jboss.com/index.html?module=bb&op=viewtopic&t=137721
So I hacked something in this direction - adding annotation plugin for @JMX.
public abstract class JMXAnnotationPlugin<T extends AnnotatedInfo> extends AbstractAnnotationPlugin<T, JMX>
{
protected JMXAnnotationPlugin()
{
super(JMX.class);
}
protected List<? extends MetaDataVisitorNode> internalApplyAnnotation(T info, MetaData metaData, JMX jmx, KernelControllerContext context) throws Throwable
{
Class<?> exposedInterface = jmx.exposedInterface();
if (exposedInterface == null || void.class.equals(exposedInterface))
exposedInterface = getExposedInterface(info);
if (exposedInterface == null || exposedInterface.isInterface() == false)
throw new IllegalArgumentException("Illegal exposed interface: " + exposedInterface);
BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(createObjectName(context, info, jmx), exposedInterface.getName());
// TODO - uncomment with new MC release; builder.addAnnotation(jmx);
Object proxy = createProxy(context, info, exposedInterface);
KernelController controller = (KernelController)context.getController();
controller.install(builder.getBeanMetaData(), proxy);
// no change directly on context
return null;
}
/**
* Create proxy for attribute.
*
* @param context the context
* @param info the info
* @param exposedInterface the exposed interface
* @return attribute's proxy
* @throws Throwable for any error
*/
protected Object createProxy(KernelControllerContext context, T info, Class<?> exposedInterface) throws Throwable
{
return Proxy.newProxyInstance(
context.getClassLoader(),
new Class<?>[]{exposedInterface},
new AttributeInvocationHandler(context, getName(info))
);
}
protected void internalCleanAnnotation(T info, MetaData metaData, JMX jmx, KernelControllerContext context) throws Throwable
{
Controller controller = context.getController();
controller.uninstall(createObjectName(context, info, jmx));
}
/**
* Get exposed interface from info.
*
* @param info the info
* @return exposed interface
*/
protected abstract Class<?> getExposedInterface(T info);
/**
* Get name from info.
*
* @param info the info
* @return info's name
*/
protected abstract String getName(T info);
/**
* Create object name.
*
* @param context the context
* @param info the info
* @param jmx the annotation
* @return obejct name
* @throws Exception for any error
*/
protected String createObjectName(ControllerContext context, T info, JMX jmx) throws Exception
{
if (jmx != null)
{
String jmxName = jmx.name();
if (jmxName != null && jmxName.length() > 0)
return jmxName;
}
// try to build one from the bean name and info param
String name = context.getName().toString();
String objectName = name;
if (name.contains(":") == false)
{
objectName = "jboss.pojo:name='" + name + "'";
}
return objectName + ",property=" + getName(info);
}
/**
* Attribute invocation handler.
*/
protected class AttributeInvocationHandler implements InvocationHandler
{
private KernelControllerContext context;
private String property;
protected AttributeInvocationHandler(KernelControllerContext context, String property)
{
this.context = context;
this.property = property;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
Object target = context.get(property);
return method.invoke(target, args);
}
}
}
I'm creating a proxy target around @JMX exposed attribute, installing it to MC, hence leaving all the rest of jmx work to MC.
Does this look legit?