Port MBean from JBoss 4.x to JBoss 7

前端 未结 2 904
暗喜
暗喜 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:03

    Singleton EJB with @Startup? http://www.adam-bien.com/roller/abien/entry/singleton_the_simplest_possible_jmx

    0 讨论(0)
  • 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 <T> void processInjectionTarget(@Observes ProcessInjectionTarget<T> pit) {
    
            // check if the MBean annotation is present
            AnnotatedType<T> 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<T> delegate = pit.getInjectionTarget();
                    InjectionTarget<T> wrapper = new JmxInjectionTarget<T>(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 <T> ObjectName getObjectName(AnnotatedType<T> 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<T> implements InjectionTarget<T> {
    
            private final InjectionTarget<T> d;
            private final ObjectName objectName;
    
            public JmxInjectionTarget(InjectionTarget<T> delegate, ObjectName objectName) {
                this.d = delegate;
                this.objectName = objectName;
            }
            @Override
            public void dispose(T instance) {
                d.dispose(instance);
            }
    
            @Override
            public Set<InjectionPoint> getInjectionPoints() {
                return d.getInjectionPoints();
            }
    
            @Override
            public T produce(CreationalContext<T> ctx) {
                return d.produce(ctx);
            }
    
            @Override
            public void inject(T instance, CreationalContext<T> 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 )

    0 讨论(0)
提交回复
热议问题