Close

Spring - Annotation Based Spring JMX Integration

[Last Updated: Jul 25, 2018]

Following example shows how to integrate JMX into a Spring application

We are going to use Spring MBean related annotations which automatically export Spring bean properties and method as JMX MBean attributes and operations.

Example

Defining MBean attributes and operations.

package com.logicbig.example;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Component
@ManagedResource
public class ExampleModelBean {

  private int lineLength;
  private int delay;
  private List<Consumer<Boolean>> stopListeners=new ArrayList<>();

  @ManagedAttribute
  public int getLineLength() {
      return lineLength;
  }

  @ManagedAttribute
  public void setLineLength(int lineLength) {
      this.lineLength = lineLength;
  }

  @ManagedAttribute
  public int getDelay() {
      return delay;
  }

  @ManagedAttribute
  public void setDelay(int delay) {
      this.delay = delay;
  }

  @ManagedOperation
  public void stop() {
      stopListeners.forEach(c->c.accept(true));
  }

  @ManagedOperation
  public void start() {
      stopListeners.forEach(c->c.accept(false));
  }

  public void addStopListener(Consumer<Boolean> stopListener) {
      stopListeners.add(stopListener);
  }
}
To mark a bean for export to JMX, we need to annotate it with the @ManagedResource. Each method we wish to expose as an operation must be annotated with the @ManagedOperation. Each property which has to be exposed must be annotated with the ManagedAttribute. When marking properties we can omit either the annotation on the getter or the setter to create a write-only or read-only attribute respectively.

Using MBean in example application

In this demo example we are using Java Swing:

//This panel uses swing 2d to display a rotating line.
@Component
public class ExamplePanel extends JPanel {
  @Autowired
  private ExampleModelBean exampleModelBean;
  private int angle = 0;
  private Timer timer;

  @PostConstruct
  public void postConstruct() {
      //set defaults
      exampleModelBean.setLineLength(100);
      exampleModelBean.setDelay(200);
      exampleModelBean.addStopListener(stop -> {
          if (stop) {
              timer.stop();
          } else {
              timer.restart();
          }
      });
      initTimer();
  }

  private void initTimer() {
      timer = new Timer(exampleModelBean.getDelay(), e -> {
          angle += 5;
          if (angle >= 360) {
              angle = 0;
          }
          repaint();
          //update delay in case model bean has changed
          if (timer.getDelay() != exampleModelBean.getDelay()) {
              if (exampleModelBean.getDelay() < 0) {
                  exampleModelBean.setDelay(0);
              }
              timer.setDelay(exampleModelBean.getDelay());
          }
      });
      timer.setRepeats(true);
      timer.start();
  }

  @Override
  protected void paintComponent(Graphics g) {
      g.clearRect(0, 0, getWidth(), getHeight());
      int lineLength = exampleModelBean.getLineLength();
      //center of panel
      int x1 = getWidth() / 2;
      int y1 = getHeight() / 2;
      //degree to radians
      double angle = this.angle * Math.PI / 180;
      //to polar coordinates
      int x2 = (int) (x1 + lineLength * Math.sin(angle));
      int y2 = (int) (y1 + lineLength * Math.cos(angle));
      //draw line
      g.drawLine(x1, y1, x2, y2);
  }
}

JavaConfig

package com.logicbig.example;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;

@ComponentScan
@Configuration
@EnableMBeanExport
public class AppConfig {
}

Main class

public class SpringJmxExampleMain {

  public static void main(String[] args) {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(AppConfig.class);
      ExamplePanel panel = context.getBean(ExamplePanel.class);
      JFrame frame = createFrame();
      frame.add(panel);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
  }

  private static JFrame createFrame() {
      JFrame frame = new JFrame("Spring JMX Integration Example ");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(new Dimension(500, 400));
      return frame;
  }
}

Output

Run the main class and use JConsole to access our MBean:

Example Project

Dependencies and Technologies Used:

  • spring-context 5.0.7.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.5.4

Spring JMX Integration Example. Select All Download
  • spring-jmx-integration-annotation-based
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • ExampleModelBean.java

    See Also