Nov 10, 2021 3:10:37 PM Thomas Dumont avatar

Create JMX MBeans using JMX plugin

Introduction

The JMX plugin facilitates the implementation of supervision via this protocol :

  • It offers a development model of MBeans ("standard" and "model" for dynamic resources)
  • It realizes the registration of the MBean managers via the Spring context and detects during the creation of new MBean corresponding to new resources (ex: creation of a new cache).

Creation of a standard MBean

The creation of a standard MBean requires the realization of 3 classes :

  • the interface class suffixed by MBean (imposed by the JMX specification)
  • the implementation class (same name as above without the MBean suffix)
  • the management class used to register the MBean (providing the name of the MBean and the instance of the bean). This class will have the MBeanExporter suffix by convention.

In our example, we will create an MBean providing the number of connected users.

Here is the interface :

/** Class ConnectedUsersMBean.java */

public interface ConnectedUsersMBean
{
    /**
     * Users sessions count
     * @return The sessions count
     * @throws IOException If an error occurs
     */
    int getConnectedUsersCount(  ) throws IOException;
}

The implementation :

/** Class ConnectedUsers.java */

public class ConnectUsers implements ConnectedUsersMBean
{
    /**
     * {@inheritDoc}
     */
    @Override
    int getConnectedUsersCount(  ) throws IOException
    {
        ...
        return nCount;
    }
}

The management class :

/** Class ConnectedUsersMBeanManager.java */

import fr.paris.lutece.plugins.jmx.mbeans.MBeanExporter;

/**
 * Portal MBean Exporter
 */
public class ConnectedUsersMBeanExporter implements MBeanExporter
{
    private static final String MBEAN_NAME = "type=ConnectedUsers";

    /**
     * {@inheritDoc}
     */
    @Override
    public String getMBeanName(  )
    {
        return MBEAN_ROOT_NAME + MBEAN_NAME;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getMBean(  )
    {
        return new ConnectedUsers(  );
    }
}

In order for this MBean to be taken into account and saved by the JMX plugin, just add the bean to export it in the Spring context of the plugin, myplugin_context.xml, as follows :

<bean id="myplugin.connectedUsersMBeanExporter" class="fr.paris.lutece.plugins.myplugin.mbeans.ConnectedUsersMBeanExporter" />

Creating a MBean Model

This type of MBean dynamically creates MBean based on a common model. This type of MBean is generally used to instantiate MBeans associated with dynamic resources. Each time a resource is created, a corresponding MBean will be created.

Creating MBeans by model-based resource requires the creation of two classes:

  • The class that describes the "managed" resource (suffixed by ManagedResource)
  • The bean management class (suffixed by MBeansExporter)

Here is a sample code :

/** Class MyManagedResource.java */

public class MyManagedResource implements ManagedResource
{
    private static final String MBEAN_NAME_PLUGINS = "Lutece:type=MyResource,name=";

    /**
     * {@inheritDoc}
     */
    @Override
    public String getName(  )
    {
        return MBEAN_NAME_PLUGINS + myresource.getName(  );
    }

    // TODO : Add below all methods exposed through JMX for this resource
    ...
}

For the management class :

/** Class MyResourceMBeansManager.java */

public class MyResourceMBeansExporter implements ResourceExporter
{
    /**
     * {@inheritDoc}
     */
    @Override
    public ModelMBeanInfo getMBeanInfo(  )
    {
        // for each attribute
        Descriptor descriptorAttr1 = new DescriptorSupport( new String[]
                {
                    "name=Attr1", "descriptorType=attribute", "default=0", "displayName=Attribute 1",
                    "getMethod=getAttr1", "setMethod=setAttr1"
                } );

        ModelMBeanAttributeInfo[] mmbai = new ModelMBeanAttributeInfo[nAttributeCount];
        mmbai[0] = new ModelMBeanAttributeInfo( "Attr1", "java.lang.String", "Attribute 1", true, false,
                false, descriptorVersion );
        ...


        ModelMBeanOperationInfo[] mmboi = new ModelMBeanOperationInfo[nAttributeCount];
        mmboi[0] = new ModelMBeanOperationInfo( "getAttr1", "getter for Attr1", null, "String",
                ModelMBeanOperationInfo.INFO );

        return new ModelMBeanInfoSupport( PluginManagedResource.class.getName(), "PluginModelBean", mmbai, null, mmboi, null );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Iterable<ManagedResource> getMBeans(  )
    {
        // Returns the list of MyManagedResource
        ...
        return list;
    }
}

In the same way as for standard beans, the management class must be declared in the Spring context file, myplugin_context.xml, so that the MBeans can be saved automatically :

<bean id="myplugin.myresourceMBeansExporter" class="fr.paris.lutece.plugins.myplugin.mbeans.MyResourceMBeansExporter" />

Alternative framework Spring

To export MBeans and create managed resources the option proposed by Spring can be considered : http://docs.spring.io/spring/docs/2.0.8/reference/jmx.html