Monitoring and Managing your Java EE application with JMX

I have recently become a big fan of the Java Management eXtensions (JMX) framework for monitoring and managing our server-side applications that are installed on Glassfish 3. Setting an application up to be monitored via JMX with either VisualVM or JConsole (both available as part of the JDK) is a relatively easy and straightforward process, so much so, that I don’t know why we have not started using JMX earlier.

We have a application that runs within Glassfish and acts as a proxy from our handheld wireless devices in our warehouses to our ActiveMQ messaging server. We wanted a way to monitor the health of this application in real-time and looked at using JMX for the task.

The process is fairly painless. Start with creating an interface with “get” methods for the data that should be available through JMX. The interface name should be appended with “MXBean” if any of the interface’s methods will need to return values other than primitives. In the example below getClients() returns a Set of MessagingProxyClientMXBean objects. These MXBeans dive further into device specific info and will also show as a tree structure in VisualVM. (More about these beans later). Below is the interface for exposing data related to our messaging proxy server.

The final piece to get the MXBean to appear in JConsole is to connect to the JMX instance and register the MXBean. In the code snippet below, and unique nameString is defined which will determine the bean’s location in JConsole’s tree hierarchy.

Launching VisualVM and connecting to Glassfish’s JMX port, the “com.lynden.messaging” node appears and shows the results of the MessagingProxyClients info that was defined in the class and interface above.

Nesting MXBeans

As previously mentioned, MXBeans can be nested, which in this case can be used to display information about the individual clients that are connected to the proxy server.

Just like in the previous example an MXBean interface can be created to represent the various pieces of data about the client that we want available in JMX, along with an implementation of the interface (Not shown).

Registering the MXBean for the client is similar to the above process for registering the MXBean for the server itself, except for the “clientNameString” variable shown below, which shows a type=MessagingProxyClients,name=<some-client-id>. Once that is in place, any new clients that connect to the proxy will automatically appear in JConsole without needing any sort of refresh.

Below is a screenshot from VisualVM of an expanded proxy server node, displaying all the connected client instances. The right side of the window shows the various properties that are available from the client’s MXBean.

JMX Operations

One final piece of JMX functionality that can be useful is the ability to execute methods on the MXBeans (called Operations) in VisualVM/JConsole. In order to create a method available via JMX it only needs to be in the MXBean interface and implementation, and not conform to the standard JavaBean “getter” format. In our client’s MXBean, in addition to the getter methods, the bean also contained a removeClient() method which would force the client’s connection to the proxy to close. Below is a snippet from the client’s MXBean’s implementation.

Below is a screenshot from VisualVM showing that the method can be invoked from the bean’s “Operations” tab by clicking the “removeClient” button.

With this information available from our production servers via JMX we now have a very useful tool for debugging issues when they arise in production that will give us greater insight than the application’s log files alone.