CDI (Contexts and Dependency Injection) is a new standard that makes application development easier by providing type safety dependency injection, scope binding (request, session, application, etc.) and contextual lifecycle management of Java components. It also exposes a powerful SPI (Service Provider Interface) to extend its functionality through portable extensions.
JMX (Java Management Extensions) provides a consistent, well defined interface to monitor and manage your applications by exposing objects (MBeans) through an MBeanServer. Currently, there are two ways to expose an object as an MBean: you can either provide an interface of your class, in which case, you won’t be able to add textual descriptions for your exposed fields and methods; or you can implement javax.management.DynamicMBean, which is cumbersome and difficult to maintain.
JSR-255, the JMX specification 2.0, is an initiative that will make the writing of MBeans easier through annotations. However, by the time of this writing, the JSR is inactive as stated here. |
I’ve decided to write my first own portable extension that will allow you to expose any object automatically or manually through JMX by just adding some simple annotations. You can download the complete code from here.
Let’s take a look at the following example:
When the bean is instantiated by CDI, a dynamic MBean is created and registered on an MBeanServer to expose the attributes and methods annotated with @ManagedAttribute and @ManagedOperation respectively. You can then use any JMX Agent Viewer to monitor and manage your code.
Figure 1. JBoss AS JMX Console. A view of an MBean.
You don’t have to worry anymore about obtaining an MBeanServer, registering the MBean and unregistering it. This is all done automatically for you. It’s a simple way of instrumenting your code without writing complex and uneven administration interfaces!
Creation and registration of the MBean is done when the bean is instantiated by CDI, not on startup. If you want the MBean to be registered on startup, you will have to annotate your class with the @Singleton and @Startup annotations. |
If you don’t want the object to be automatically registered on instantiation but still want to register it yourself later in the code, you can set the autoRegister property of the @MBean to false. To register your object programmatically, you use the MBeanFactory service to create a DynamicMBean instance, and then register it to an MBeanServer. For example:
You can even expose objects that are not annotated with @MBean. In this case, all fields and methods from the class are exposed. Any @ManagedAttribute or @ManagedOperation annotations will be ignored.
CDI Integration
Writing the portable extension was pretty straightforward. First, I created a class org.gescobar.management.cdi.ManagementExtension that extends javax.enterprise.inject.spi.Extension with a method to observe the ProcessInjectionTarget event:
Basically, what we are doing here is replacing the InjectionTarget with a wrapper class that will register and unregister the MBean if the @MBean annotation is present and autoRegister is true
To register the portable extension, I created a file called javax.enterprise.inject.spi.Extension with only one line:
Testing
I used TestNG and Arquillian to write and execute the tests inside a remote JBoss AS 6.0.0.M1 container. One of the tests looks like this:
Arquillian is a JBoss project for running tests on different containers. By the time of this writing, it hasn’t been release but you can download the code from SVN and build it using Maven 2.
What’s next?
It would be nice to support the following:
- Automatic and manual registration of MBeans for JBoss Seam.
- Manual registration of MBeans in any J2SE environment.
- @ManagedAttribute annotation on methods that return information.
- Name for operation parameters.
- Notifications using annotations.
- Message keys from resource bundles for descriptions.
You can check the project on Google Code here. Please, feel free to download it and give it a try!