Monitor your Web applications using JMX and Spring

Learn how to use JMX and Spring to monitor new Web application projects.

When debugging issues in production, there have been times where it would be nice to view various pieces of information about an application while it is actually running, such as the number of clients currently connected, the number of messages sent in the last minute or a list of the properties that the application currently has loaded. It would also be great to have the ability to invoke methods at runtime, such as forcing a reload of a properties file, or the reset of a connection with a messaging client, without the need to restart the Web app or Web app server.

Java Management Extensions (JMX) is a framework which allows you to monitor and administer Java applications remotely, and can be used with JVMs running locally or remotely. JMX can be used to inspect Java objects, as well as invoke methods on those objects, allowing the ability to interact with an application at runtime and view real-time information about the application that could be more useful than combing through log files.

Using JMX and Spring, it is possible to achieve this easily and provide useful real-time information to developers and system administrators. The process of exposing this information and functionality via JMX MBean is straightforward by following the JMX naming conventions and using Spring to eliminate a lot of boilerplate code. MBean is a class which exposes attributes or methods for a specified application that can be viewed and invoked via JMX.

Tools such as VisualVM and JConsole can be used to connect via JMX to an enabled Java Runtime, and applications can even connect programatically via the JMX API to attach and monitor another JVM and view and interact with application MBeans.

In this four part tutorial, I will show how to create a generic application MBean which can be used across all Web applications to provide a view of generic data such as version number and build date, but at the same time, eliminate the need to write boilerplate code in each application in order to accomplish this.

Create a new SampleJmxUtils library project

This project will be a simple Java library/jar which will contain the base JMX MBean. Applications can then include this library as a dependency in order to gain the JMX functionality with no additional Java code and minimal configuration.

The first step is to define an interface whose name ends with MBean. This is one of the JMX naming conventions. The implementation of that interface will contain the same name, minus the MBean suffix. For this example our interface will be named ApplicationMBean, and our implementation will be a class named Application.

The interface will contain get methods for information we want to expose via JMX as well as methods we want to be able to invoke via JMX. 
For this tutorial, we'll start with an interface that provides the following information about the application.

  • Last restart date
  • Build date
  • Version number
  • List of properties the application has loaded

In addition to this, we would like the ability to force the application to reload the properties from the local filesystem via JMX as well.

The ApplicationMBean interface

Create an interface defining the generic functionality that all Web applications should have. In this case we will be providing information on the application version number, build date, the time the application was started and the properties that the application has loaded. We will also be providing a way to refresh the application properties dynamically via the MBean.

 
package com.lynden.jmx;

import java.io.IOException;
import java.util.Date;
import java.util.Properties;

public interface ApplicationMBean {
    public String getVersion();
    public String getBuildDate();
    public Date getAppStartTime();
    public Properties getProperties();
    public void refreshProperties() throws IOException;

Implement the inteface 

Create an implementation of the interface and add the @Component annotation so that Spring will instantiate this class as a Spring bean. The @PostConstruct annotation on the init() method instructs Spring to invoke the method once the class has been instantiated. This method will load the properties from the property file on the local file system.

package com.lynden.jmx;

import java.io.FileReader;
import java.io.IOException;
import java.util.Date; 
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class Application implements ApplicationMBean {

    protected String version = "N/A";
    protected String buildDate;
    protected Date startDate;
    protected Properties properties;

    public Application() {
        startDate = new Date();
    }

    @PostConstruct
    public void init() {

        try {
            refreshProperties();
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }

    }

    @Override
    public Properties getProperties() {
        return properties;
    }

    @Override
    public void refreshProperties() throws IOException {
        properties = new Properties();
        properties.load( new FileReader( "/home/robbob/somefile.txt" ) );
    }

    @Override
    public String getVersion() {
        return properties.getProperty("version");
    }

    @Override
    public String getBuildDate() {
        return properties.getProperty("build.date");
    }

    @Override
    public Date getAppStartTime() {
        return startDate;
    }
}

Dig Deeper on Front-end, back-end and middle-tier frameworks