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
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 )