Port MBean from JBoss 4.x to JBoss 7

前端 未结 2 934
暗喜
暗喜 2021-02-19 13:47

we\'re currently in the process of porting some of our projects from JBoss 4.x to JBoss 7. So far everything seems to work fine, except for our MBeans, which we\'re commonly usi

2条回答
  •  暗喜
    暗喜 (楼主)
    2021-02-19 14:10

    I think more concise way to do it is to use CDI extension. Please take a look at the solution we use:

    @Documented
    @Retention(value=RUNTIME)
    @Target(value=TYPE)
    @Inherited
    public @interface MBean {
        String value() default "";
    }
    

    ...

    This is working code of CDI extension:

    public class ManagementExtension implements Extension {
    
        private static Logger log = LoggerFactory
                .getLogger(ManagementExtension.class);
    
        public  void processInjectionTarget(@Observes ProcessInjectionTarget pit) {
    
            // check if the MBean annotation is present
            AnnotatedType at = pit.getAnnotatedType();
            if (at.isAnnotationPresent(MBean.class)) {
                // it makes sense to register JMX interfaces only for singletons
                if (!at.isAnnotationPresent(Singleton.class)) {
                    log.warn("Ignoring attemt to register JMX interface for a non-singleton EJB: "
                            + at.getJavaClass().getName());
                    return;
                }
    
                try {
                    // decorate the InjectionTarget
                    InjectionTarget delegate = pit.getInjectionTarget();
                    InjectionTarget wrapper = new JmxInjectionTarget(delegate, getObjectName(at));
    
                    // change the InjectionTarget with the decorated one
                    pit.setInjectionTarget(wrapper);
                } catch (Exception e) {
                    log.warn("Cannot get JMX object name for: " + at.getJavaClass().getName(), e);
                }
    
            }
        }
    
        private  ObjectName getObjectName(AnnotatedType at) throws MalformedObjectNameException {
    
            String name = at.getAnnotation(MBean.class).value();
    
            if (name.isEmpty()) {
                name = at.getJavaClass().getPackage().getName() + ":type="
                        + at.getJavaClass().getSimpleName();
            }
    
            return new ObjectName(name);
        }
    
        private class JmxInjectionTarget implements InjectionTarget {
    
            private final InjectionTarget d;
            private final ObjectName objectName;
    
            public JmxInjectionTarget(InjectionTarget delegate, ObjectName objectName) {
                this.d = delegate;
                this.objectName = objectName;
            }
            @Override
            public void dispose(T instance) {
                d.dispose(instance);
            }
    
            @Override
            public Set getInjectionPoints() {
                return d.getInjectionPoints();
            }
    
            @Override
            public T produce(CreationalContext ctx) {
                return d.produce(ctx);
            }
    
            @Override
            public void inject(T instance, CreationalContext ctx) {
                d.inject(instance, ctx);
                //the next piece of code better be done in postConstruct but...
                //got no idea why but postConstruct never gets called
                //for Singleton EJB bean
                MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
                try {
                    if(mBeanServer.isRegistered(objectName))
                    mBeanServer.unregisterMBean(objectName);
                    mBeanServer.registerMBean(instance, objectName);
                } catch (Exception e) {
                    log.warn("Cannot register "+objectName, e);
                    return;
                }
                log.info("added JMX registration for: " + objectName);
            }
    
            @Override
            public void postConstruct(T instance) {
                d.postConstruct(instance);
            }
    
            @Override
            public void preDestroy(T instance) {
                d.preDestroy(instance);
            }
    
        }
    }
    

    Then just mark your class by @Mbean annotation and will be automatically registered in Mbean server :

    @Startup 
    @Singleton 
    @MBean("com.company=JmxBindName")
    public class SomeService
    

    Works like a charm )

提交回复
热议问题