Accéder au contenu principal

Intégrez JMX dans vos applications

JMX (Java Management eXtension)! Le seul nom peut faire peur et pourtant, cette technologie peut très facilement être intégrée dans vos applications Java de la plus simple à la plus complexe sans surcout particulier. Elle est en effet incluse dans Java SE depuis la version 1.5. Tout d'abord, à quoi cela peut t'il servir? Le premier usage de base est que JMX permet de surveiller les ressources utilisées par une application (mémoire, CPU, nombre de threads, système d'exploitation, etc). Ces informations sont fournies de base par la machine virtuelle. Vous pouvez cependant rajouter des informations spécifiques à votre application. L'API JMX vous permet de :
  • Exposer des propriétés de configuration qui pourront être consultées ou modifiées. 
  • Exposer des méthodes qui permettront de contrôler l'application pour l'arrêter, démarrer des modules, etc.
  • Afficher des notifications d'alarmes
Dans des systèmes en production, JMX peut être intégré à des systèmes de monitoring d'applications tels que Zabbix, Nagios pour n'en citer que quelques uns. Il peut également être utilisé avec JConsole qui est une application gratuite livrée avec le JDK depuis la version 1.5.

Exposer des attributs avec JMX

L'une des utilisations les plus simples de JMX consiste à exposer des propriétés de configuration. Il faut pour cela déclarer une interface et son implémentation. Il n'y a qu'une seule contrainte de nommage de l'interface. Si le nom de la classe est Test, l'interface correspondante doit s'appeler TestMBean. Le MBean ajouté en fin de classe permet ainsi d'indiquer les attributs et méthodes qui seront exposés, la classe d'implémentation peut contenir d'autres classes publiques qui ne seront pas exposées.
Voici un premier exemple avec une classe de configuration de base de données. Je vais donc appeler l'interface DatabaseManagementMBean.

 package com.jmxtest.mbeans;  
   
 public interface DatabaseManagementMBean {  
      String getDbUser();  
      void setDbUser(String user);  
      String getDbPassword();  
      void setDbPassword(String password);  
      String getDbDriver();  
      void setDbDriver(String dbDriver);  
      String getDbURL();  
      void setDbURL(String dbURL);  
      Long getDbCounter();  
 }  
Notez que la dernière méthode getDbCounter n'a pas de méthode set correspondante ce qui signifie que l'attribut "dbCounter" est en lecture seule. Cela n'empêche pas d'implémenter une méthode setDbCounter dans l'implémentation. Cette dernière ne sera simplement pas visible.

L'implémentation de l'interface doit donc s'appeler DatabaseManagement (sans le MBean).

 package com.jmxtest.mbeans;  
   
 public class DatabaseManagement implements DatabaseManagementMBean {  
      String dbDriver = "org.apache.derby.jdbc.ClientDriver";  
      String dbURL = "jdbc:derby://localhost:1527/testjmx";  
      String dbUser = "linus";  
      String dbPassword = "ChangeMe";  
      Integer dbCounter = 0;  
        
      public DatabaseManagement() {  
      }  
   
      public String getDbDriver() {  
           return dbDriver;  
      }  
   
      public String getDbPassword() {  
           return dbPassword;  
      }  
   
      public String getDbURL() {  
           return dbURL;  
      }  
   
      public String getDbUser() {  
           return dbUser;  
      }  
   
      public void setDbDriver(String dbDriver) {  
           this.dbDriver = dbDriver;  
      }  
   
      public void setDbPassword(String dbPassword) {  
           this.dbPassword = dbPassword;  
      }  
   
      public void setDbURL(String dbURL) {  
           this.dbURL = dbURL;  
      }  
   
      public void setDbUser(String dbUser) {  
           this.dbUser = dbUser;  
      }  
   
      public Integer getDbCounter() {  
           return dbCounter;  
      }  
   
      public void setDbCounter(Integer dbCounter) {  
           this.dbCounter = dbCounter;  
      }  
 }  
   


L'exposition de la classe pour JMX se fait de la manière suivante.
 import java.lang.management.ManagementFactory;  
   
 import javax.management.MBeanServer;  
 import javax.management.ObjectName;  
   
 import com.jmxtest.mbeans.DatabaseManagement;  
   
 public class TestJMXProperties {  
      // MBeans  
      DatabaseManagement databaseConfig;  
        
      public TestJMXProperties() {  
           createMBeans();            
      }  
   
      //Register MBeans  
      private void createMBeans() {  
           try {  
                System.out.println("Creating MBeans");  
                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();   
   
                databaseConfig = new DatabaseManagement();  
                ObjectName databaseName = new ObjectName("TestJMX:name=Database Management");  
                mbs.registerMBean(databaseConfig, databaseName);  
           } catch (Exception e) {  
                System.out.println(e.getMessage());  
                e.printStackTrace();  
           }  
      }  
   
      // Initialize the mbeans  
        
      public static void main(String[] args) throws InterruptedException {  
           TestJMXProperties test = new TestJMXProperties();  
           Integer counter = 0;  
           while (true) {                 
                Thread.sleep(10000);                 
                System.out.println("Waiting 10 seconds " + counter);  
                test.databaseConfig.setDbCounter(counter++);  
           }  
      }  
 }  
   

Exécutez l'application avec les options suivantes :
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=1333

Les nouvelles propriétés peuvent être visualisées avec l'application JConsole. Sélectionnez l'application à superviser.


Avec Java 1.7, la sécurité a été renforcée. JConsole essaye d'abord de se connecter en mode SSL sécurisé. En ayant démarré avec les options indiquées précédemment, vous pouvez vous connecter en mode "Insecure connection".


Après la connexion, allez sur l'onglet MBean puis l'objet TestJMX. Vous verrez la liste des attributs définis dans l'application.


L'attribut dbCounter est en lecture seule. En double-cliquant sur la valeur, elle apparaitra sous forme de graphe qui peut ainsi être sauvegardé.


Vous pouvez également utiliser l'application JVisualVM après avoir rajouté le plugin VisualVM-MBeans.


L'affichage est similaire à JConsole et vous pouvez également profiler votre application.

Exposez des méthodes

Le principe d'exposition des opérations est le même que celui des propriétés. La méthode Java ne doit simplement pas commencer par "set" ou "get" pour être considérée comme une opération.
Je vais maintenant définir une classe MainManagement avec son interface MainManagementMBean. Encore une fois, seul le nommage MBean permet d'indiquer qu'il s'agit de l'interface qui expose les méthodes.

L'interface MainManagementMBean contient les méthodes suivantes.

 package com.jmxtest.mbeans;  
   
 public interface MainManagementMBean {  
      public void stop();  
      public void reload();  
      public void debug(boolean on);  
      public void save();  
 }  
   


Je défini ici une implémentation de cette interface juste à titre d'exemple.

 package com.jmxtest.mbeans;
   
 // Main Management class  
   
 public class MainManagement implements MainManagementMBean {  
        
      public static volatile MainManagement _instance = null;  
   
      boolean debug = false;  
        
      // MBeans  
      DatabaseManagement databaseConfig;     // Database MBean  
      MainManagement main;     // Ini file content and operations  
        
        
      // Constructor that loads the ini file  
      public MainManagement(){  
           loadIniFile();  
      }  
   
      // Retrieves a unique instance of the class  
        
      public static MainManagement getInstance() {  
           if (_instance == null)  
                _instance = new MainManagement();  
           return _instance;  
      }       
   
      // Private method to load the configuration file  
        
      private void loadIniFile() {  
           System.out.println("Load configuration file");  
           databaseConfig = new DatabaseManagement();  
           debug = false;  
      }  
        
      // Private method to save the configuration file  
        
      private void saveIniFile() {  
           System.out.println("Saving ini file");            
      }  
        
      // Turns the application in debug mode.  
      // This has to be completed according to the debug framework used  
   
      public void debug(boolean on) {  
           System.out.println("Debug=" + on);  
           debug = on;  
      }  
   
      // Reloads the ini file  
        
      public void reload() {  
           loadIniFile();  
      }  
   
      // Exposed method to save the configuration file  
        
      public void save() {  
           saveIniFile();  
      }  
   
      // Exposed method to stop the application.  
      // Security must be put in place when this kind of methods are publicly exposed,   
        
      public void stop() {  
           System.out.println("Stop");  
           System.exit(0);  
      }  
        
      public DatabaseManagement getDatabaseConfig() {  
           return databaseConfig;  
      }
 }

L'enregistrement du MBean se fait de la même manière que précédemment.

 import java.lang.management.ManagementFactory;  
 import java.text.SimpleDateFormat;  
 import java.util.Calendar;  
   
 import javax.management.MBeanServer;  
 import javax.management.ObjectName;  
   
 import com.jmxtest.mbeans.MainManagement;  
 import com.jmxtest.mbeans.DatabaseManagement;  
   
 public class TestJMX {  
   
      // MBeans  
      DatabaseManagement databaseConfig;  
      MainManagement main;  
        
      public TestJMX() {  
           createMBeans();            
      }  
   
      //Register MBeans  
      private void createMBeans() {  
           try {  
                System.out.println("Creating MBeans");  
                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();   
   
                main = MainManagement.getInstance();  
                ObjectName mainName = new ObjectName("TestJMX:name=TestJMX Management");  
                mbs.registerMBean(main, mainName);  
                  
                databaseConfig = main.getDatabaseConfig();  
                ObjectName databaseName = new ObjectName("TestJMX:name=Database Management");  
                mbs.registerMBean(databaseConfig, databaseName);  
           } catch (Exception e) {  
                System.out.println(e.getMessage());  
                e.printStackTrace();  
           }  
      }  
   
      // Initialize the mbeans  
        
      public static void main(String[] args) throws InterruptedException {  
           TestJMX testJMX = new TestJMX();  
           Integer counter = 0;  
           while (true) {  
                Thread.sleep(10000);  
                System.out.println("Waiting 10 seconds");  
                testJMX.databaseConfig.setDbCounter(counter++);  
           }  
      }  
 }  
   

Les méthodes ainsi exposées sont maintenant visibles dans JConsole et peuvent être appelées.


Voici donc comment avec quelques classes Java tout à fait standard et sans librairie additionnelle il est possible d'offrir une interface permettant de contrôler votre application à distance.

Commentaires

Posts les plus consultés de ce blog

Supprimer les partitions Raspberry sur une carte SD sous Windows 7 avec Diskpart

Si vous souhaitez récupérer une ancienne carte SD utilisée pour démarrer un Raspberry pour un autre usage (appareil photo, etc), il vous faudra supprimer les deux partitions créées au moment de l'écriture de l'image sur la carte SD. Vous pouvez voir les partition en sélectionnant Menu Windows/Ordinateur/bouton droit "Gérer". Voici un exemple du résultat final. Vous pouvez supprimer la partition Unix de 7 Gb (ou 4Gb en fonction de la taille de votre carte) en sélectionnant la partition puis en faisant "bouton droit Supprimer". Laissez juste une partition pour pouvoir faire les autres manipulations avec DISKPART. Démarrez l'outil DISKPART en ligne de commande. Une nouvelle fenêtre s'ouvrira. Microsoft DiskPart version 6.1.7601 Copyright (C) 1999-2008 Microsoft Corporation. Sur l'ordinateur : FRVILN0H305806 DISKPART> list disk   N° disque  Statut         Taille   Libre    Dyn  GPT   ---------  -------------  -------  -------  ---  ---   D

Comment lire son écran de téléphone Android sur PC (2)

Voici une nouvelle manière d'accéder à votre téléphone depuis votre PC. Cette méthode utilise le câble USB et Google Chrome. Elle fonctionne donc sur Windows, Mac et Linux. Les pré-requis sont les mêmes que ceux du billet précédent : Téléphone configuré en mode Développement Drivers USB installés sur le PC Google Chrome installé L'application Vysor s'installe comme une extension de Google Chrome. Cherchez dans le Webstore et lancez l'installation. Une fois installée, l'application apparaît dans les extensions. Vous pouvez la lancer de différentes manières. La manière la plus simple est d'ouvrir la fenêtre des applications : chrome://apps/ Une autre manière est de créer un raccourci en cliquant sur « Détails ». Ensuite créez un raccourci sur le bureau, le menu démarrer et/ou la barre de tâche. Vous pouvez également cliquer sur afficher dans la boutique et lancer l'application depuis la boutique. Une fois

Serveur d'impression CUPS sur Raspberry Pi

Je possède une très vieille imprimante laser HP Laserjet 6L noir et blanc de 12 ans d'age qui a survécu à plusieurs imprimantes jet d'encre couleurs tombées en désuétude pour obsolescence programmée. J'envisage tout de même sérieusement de les démanteler pour les recycler en CNC, graveur ou autre.   Je continue donc a utiliser cette bonne petite imprimante parallèle qui me rend bien des services (en 12 ans, j'ai changé le toner 3 fois pour un coût de 20 € la cartouche). J'ai donc dû m'équiper d'une adaptateur USB/Parallèle pour pouvoir la connecter sur un PC récent. Le problème principal est que le driver de cette imprimate n'est reconnu que par un seul de mes PC sous Windows 7. Les autres PC sous Windows 8 ou Windows 10 reconnaissent bien l'imprimante, mais sortent des feuilles avec le code Postscript. L'impression depuis une tablette ou un téléphone Androïd est également tout simplement impossible. Pour remédier à ce problème, j'ai don