10 nov. 2021 15:10:37 Thomas Dumont avatar

Développer des MBeans en utilisant le plugin JMX

Introduction

Le plugin JMX facilite la mise en place de la supervision via ce protocole :

  • Il offre un modèle de développement de MBeans ("standard" et "model" pour des ressources dynamiques)
  • Il réalise l'enregistrement des gestionnaires de MBean via le contexte Spring et détecte en cours d'exécution la création de nouveau MBean correspondant à des nouvelles ressources (ex : création d'un nouveau cache).

Création d'un MBean standard

La création d'un MBean standard nécessite la réalisation de 3 classes :

  • la classe d'interface suffixée par MBean (imposé par la spécification JMX)
  • la classe d'implémentation (même nom que ci-dessus sans le suffix MBean )
  • la classe de gestion servant à l'enregistrement du MBean (fourniture du nom du MBean et de l'instance du bean). Cette classe aura par convention le suffixe MBeanExporter.

Dans notre exemple, nous créerons un MBean fournissant le nombre d'utilisateurs connectés.

Voici l'interface :

/** Class ConnectedUsersMBean.java */

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

L'implémentation :

/** Class ConnectedUsers.java */

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

La classe de gestion :

/** 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(  );
    }
}

Afin que ce MBean soit pris en compte et enregistré par le plugin JMX, il suffit d'ajouter le bean dans le contexte Spring du plugin, myplugin_context.xml, comme suit :

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

Création d'un MBean Model

Ce type de MBean permet de créer dynamiquement des MBean basés sur un modèle commun. Il est généralement utilisé pour instancier des MBeans associés à des ressources dynamiques. A chaque création d'une ressource, un MBean correspondant sera créé.

La création de MBeans par ressource basés sur un modèle demande la création de deux classes :

  • La classe qui décrit la ressource "managée" (suffixée par ManagedResource)
  • La classe de gestion des beans (suffixée par MBeansExporter)

Voici un exemple de 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
    ...
}

Pour la classe de gestion :

/** 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;
    }
}

De la même manière que pour les beans standards, la classe de gestion doit être déclarée dans le fichier de contexte Spring, myplugin_context.xml, pour que l'enregistrement des MBeans se fasse automatiquement :

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

Alternative framework Spring

Pour exporter les MBeans et créer des resources managées l'option proposée par Spring peut être envisagée : http://docs.spring.io/spring/docs/2.0.8/reference/jmx.html