Tag Archives: jmx

Exposing JMX attributes and operations in Java

Something I’m working on currently in my spare time requires me to expose attributes and operations over JMX programmatically without the use of Spring. And I jumped at the opportunity to do a quick post on how to do so.

The general steps are as follows.

  • Write an interface.
  • Write an implementation.
  • Expose over JMX using JMX API.
  • View using JMX Client!

Below I provide a simple but complete example.

Write an interface.

Note the fact that the interface name has ‘MBean’ at the end. This isn’t essential but is a way of telling the JMX api that you are coding by convention. Though this isn’t essential. You can call it whatever you like but you’ll just have to use the JMX api in a slightly different way. Personally I prefer arbitrary naming.

package test;

public interface UserMBean {

    public enum Mood {
        HAPPY, SAD, INDIFFERENT
    }

    int getAge();

    void setAge(int age);

    String getName();

    void setName(String name);

    String getMood();

    void makeSad();

}

Write an implementation.

Note that the class name here is the same as the interface name but without ‘MBean’. Again this is coding by JMX convention but isn’t essential.

package test;


public class User implements UserMBean {
    private int age;
    private String name;
    private Mood mood;

    public User(String name, int age, Mood mood) {
        this.name = name;
        this.age = age;
        this.mood = mood;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getAge() {
        return age;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String getMood() {
        return mood.toString();
    }

    @Override
    public void makeSad() {
        mood = Mood.SAD;
    }

}

Expose over JMX by convention

Here we just pass the user to the jmx api. JMX checks that we are either following the coding convention or that we are passing the interface explicitly.

package test;

import java.lang.management.ManagementFactory;

import javax.management.MBeanServer;
import javax.management.ObjectName;

import test.UserMBean.Mood;

public class JmxExampleByConvention {

    public static void main(String[] args) throws Exception {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ObjectName id = new ObjectName("name.dhruba.test:type=test1");
        User user = new User("dhruba", 32, Mood.HAPPY);
        server.registerMBean(user, id);
        Thread.sleep(Long.MAX_VALUE);
    }

}

If you violate the naming convention you will get an exception like the one below.

Exception in thread "main" javax.management.NotCompliantMBeanException: MBean class test.DefaultUser does not implement DynamicMBean, neither follows the Standard MBean conventions (javax.management.NotCompliantMBeanException: Class test.DefaultUser is not a JMX compliant Standard MBean) nor the MXBean conventions (javax.management.NotCompliantMBeanException: test.DefaultUser: Class test.DefaultUser is not a JMX compliant MXBean)
	at com.sun.jmx.mbeanserver.Introspector.checkCompliance(Introspector.java:160)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:305)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:482)
	at test.JmxExampleByConvention.main(JmxExampleByConvention.java:16)

Expose over JMX by configuration

Here is the use of the JMX api if we do not wish to use conventional naming for our classes and want to call our classes whatever we want. In this case we have to pass the interface explicitly to JMX.

package test;

import java.lang.management.ManagementFactory;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.StandardMBean;

import test.UserMBean.Mood;

public class JmxExampleByConfiguration {

    public static void main(String[] args) throws Exception {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ObjectName id = new ObjectName("name.dhruba.test:type=test1");
        User user = new User("dhruba", 32, Mood.HAPPY);
        StandardMBean mbean = new StandardMBean(user, UserMBean.class);
        server.registerMBean(mbean, id);
        Thread.sleep(Long.MAX_VALUE);
    }

}

View using JMX Client

When you start a JMX client like JVisualVM or JConsole you should initially see some attributes.

Jmx attributes

You can then double click the value cells in JVisualVM to change them or invoke an operation in the Operations tab.

JMX operations

Having done so you’ll end up with new values in the Attributes tab.

JMX attributes

And that’s it. This trick is useful to expose attributes and operations over JMX without the use of Spring and without needing to make your classes Spring beans. Thanks for reading.