JMX Module

Overview

This module exposes some system monitoring data using Java Management Extensions (JMX) and provides an easy framework for other modules to publish objects using JMX.

Features

  • Maintains management beans for Core, all loaded Modules and Scheduled Tasks
  • Compatible with any JMX client or system monitoring software that supports JMX (e.g. Nagios, Zabbix)
  • Provides a service which other modules can use to create management beans

Usage

JMX with Tomcat

Tomcat can be launched with it's own JMX bean server. To do this add the following to the start of catalina.sh:

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.ssl=false \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.port=8999 \
  -Djava.rmi.server.hostname=localhost"

This will create a JMX bean server with no authentication. This SHOULD ONLY be done for development servers.

Enabling authentication

For a production server you can specify a password file and/or SSL requirements.

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.ssl=true \
  -Dcom.sun.management.jmxremote.authenticate=true \
  -Dcom.sun.management.jmxremote.password.file=../conf/jmxremote.password \
  -Dcom.sun.management.jmxremote.access.file=../conf/jmxremote.access \
  -Dcom.sun.management.jmxremote.port=8999 \
  -Djava.rmi.server.hostname=localhost"

Once you have configured Tomcat to use JMX, restart it, login to OpenMRS and install the JMX module.

Monitoring

The JRE comes bundled with a simple JMX viewer called jconsole. You can use this to connect to the Tomcat JMX server and view the OpenMRS beans as well as the other Tomcat diagnostic beans.

Module API

Other modules can use this module to easily publish JMX management beans (called MBeans). The bean will be published as part of the same domain and host as the other beans. For example, the Usage Statistics Module publishes a bean which appears like this:

Creating an MBean

There are several ways to define an MBean. The easiest is to define an interface that uses the @MXBean annotation, e.g.

@MXBean
public interface HelloWorldMBean {
  public String getMessage();
}

...and a class which implements that interface, e.g.

public class HelloWorldMBeanImpl implements HelloWorldMBean {
  @Override
  public String getMessage() {
    return "Hello world!";
  }
}

In your module activator you can then register an instance of the bean with the JMX module when your module is started, e.g.

JMXService jmxSvc = Context.getService(JMXService.class);
jmxSvc.registerMBean("HelloWorld", null, new HelloWorldMBeanImpl());

...and unregister it when it shuts down, e.g.

jmxSvc.unregisterMBean("HelloWorld", null);

Usually you will want to access OpenMRS services to get the values of your bean properties. This requires a valid OpenMRS session with the correct privileges for those service methods. To make this easier, the JMX module defines an annotation which will wrap the method call in a temporary OpenMRS session with the requested privileges, e.g.

@MXBean
public interface HelloWorldMBean {
  @WithSession({PrivilegeConstants.VIEW_ADMIN_FUNCTIONS})
  public String getMessage();
}

Source code

Project code is hosted on github at https://github.com/rowanseymour/openmrs-module-jmx