How to expose a Java EE Singleton as a MBean in JMX in JBoss EAP
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 6.x
- 7.x
Issue
- How to expose a JavaEE 6 Singleton as a MBean in JMX in JBoss EAP 6 - previous versions of JBoss there were JBoss specific annotations such as
@Service/@Managementwhich could be used to make a Singleton which was exposed in JMX. - How to expose a JavaEE 7 Singleton as a MBean in JMX in JBoss EAP 7 - previous versions of JBoss there were JBoss specific annotations such as
@Service/@Managementwhich could be used to make a Singleton which was exposed in JMX.
Resolution
Note: The description below show how the implementation would look like for Java EE6. This is valid as is for Java EE7 as well.
A simple MBean can be created using the EE6 @Singleton and registering it in JMX
Create an interface for your MBean, getters/setters control read/write access to your MBean's attributes, methods listed in the interface expose those such they can be invoked. Note: the interface must end in MXBean, else the JDK will throw a javax.management.NotCompliantMBeanException
public interface EE6ExampleMXBean {
public String getStatus();
public String hello(String name);
}
Next create your @Singleton / MBean implementation which implements your interface. Use @PostConstruct to have your Singleton register itself in the JMX MBean Server and then use @PreDestroy to unregister your MBean from the JMX Server such as:
import java.lang.management.ManagementFactory;
import javax.management.ObjectName;
import javax.management.MBeanServer;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Singleton
@Startup
public class EE6ExampleSingleton implements EE6ExampleMXBean {
private String status = "not started";
private ObjectName objectName;
private MBeanServer platformMBeanServer;
@PostConstruct
public void start() {
status = "starting";
try {
objectName = new ObjectName("com.jboss.examples.ee6.ejb:type=" + this.getClass().getName());
platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
platformMBeanServer.registerMBean(this, objectName);
} catch (Exception e) {
throw new IllegalStateException("Failed to register " + objectName + " into JMX:" + e);
}
status = "started & registered in jmx";
}
@PreDestroy
public void stop() {
status = "stopping";
try {
platformMBeanServer.unregisterMBean(objectName);
} catch (Exception e) {
throw new IllegalStateException("Failed to unregister " + objectName + " from JMX:" + e);
}
status = "stopped & unregistered from jmx";
}
// This is a method which the mbean is exposing
public String hello(String name) {
return "Hello " + name;
}
// This is a read only attribute the mbean is exposing.
// To make it writeable add a public void setStatus(String) to the interface and mbean implementation
public String getStatus() {
return status;
}
See the attached example which is an extension of this code which shows read-only, write-only, read/write, and method calls. The *-source.zip includes the source files and the jar is the compiled version which can be deployed in JBoss EAP 6 and tested via jconsole or another JMX tool.
Note: As this Singleton is registered with a this reference, invocations of business methods with that reference are not compliant to the JavaEE specification. This will have some drawbacks which need to considered, i.e. method Interceptors are not invoked and the reference to it might prevent from removing the bean from the environment or become invalid if used in a different context.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.