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?