Les MBeans WebLogic faciles avec Groovy

GroovyMBean

Groovy, langage dynamique à succès s’exécutant sur la JVM, comporte un petit composant très simple mais très puissant pour accéder aux MBeans : GroovyMBean
http://groovy.codehaus.org/Groovy+and+JMX

En résumé, une fois une référence au serveur JMX (directe ou via une remote connection) obtenue, il suffit de créer un GroovyMBean à l’aide de l’ObjectName du MBean à manipuler …

def groovyMBean = new GroovyMBean(server, mBeanObjectName)

… pour pouvoir accéder aux attributs JMX comme de banals attributs d’objet :

groovyMBean.myAttribute

… ou mieux, appeler une opération JMX aussi simplement qu’une méthode :

groovyMBean.myOperation(param1,param2)

C’est ici les capacités dynamiques du langage Groovy qui permettent à GroovyMBean de se comporter comme une sorte de proxy universel et cacher la lourdeur des apis JMX, apis qui ressemblent fortement à de la réflection.

Les MBeans de WebLogic

Oui mais voilà, mon expérience personnelle étant assez centrée sur WebLogic, je trouvais que GroovyMBean n’était pas encore assez simple d’utilisation 😉

En effet, les MBeans de WebLogic sont organisés de manière hiérarchique : pour naviguer dans cette hiérarchie, les MBeans de WebLogic disposent d’attributs de type ObjectName ou ObjectName[] référençant des MBeans enfants.

Ainsi, à partir de l’ObjectName d’un MBean racine, il est possible d’accéder à tous les MBeans de la hiérarchie sans avoir à construire un ObjectName compliqué ou le rechercher avec les apis JMX.

C’est grâce à cela que WLST (WebLogic Scripting Tools), l’outils de scripting basé sur JPython de WebLogic, peut exposer la configuration ou l’état des ressources d’un domaine WebLogic sous la forme d’une arborescence de fichier :

wlst wls:/offline> connect('weblogic','weblogic','t3://localhost:7001') Connecting to t3://localhost:7001 with userid weblogic (...) wls:/base_domain/serverConfig> cd('JDBCSystemResources') wls:/base_domain/serverConfig/JDBCSystemResources> ls() dr-- cgDataSource dr-- cgDataSource-nonXA dr-- samplesDataSource wls:/base_domain/serverConfig/JDBCSystemResources> cd('cgDataSource/JDBCResource/cgDataSource/JDBCDriverParams/cgDataSource') wls:/base_domain/serverConfig/JDBCSystemResources/cgDataSource/JDBCResource/cgDataSource/JDBCDriverParams/cgDataSource> ls() dr-- Properties -r-- DriverName com.pointbase.jdbc.jdbcUniversalDriver -r-- Password ****** -r-- PasswordEncrypted ****** -r-- Url jdbc:pointbase:server://localhost:9093/weblogic_eval;new -r-- UseXaDataSourceInterface true -r-x isSet Boolean : String(propertyName) -r-x unSet Void : String(propertyName)

Si on revient au Groovy et à GroovyMBean, cela signifie qu’il faut ré-instancier à chaque niveau de la hiérarchie une nouvelle instance à partir des ObjectName récupérés :

def server = ... def domain = new GroovyMBean(server, 'com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean') def domainConfig = new GroovyMBean(server,domain.DomainConfiguration) domainConfig.JDBCSystemResources.each { moduleObjectName -> def module = new GroovyMBean(server, moduleObjectName) // ... }

A Groovier Mbean

Ce qu’il me manquait donc dans GroovyMBean c’est juste la capacité de transformer automatiquement les valeurs de type ObjectName en GroovyMBean.
J’ai donc surchargé légèrement GroovyMBean pour créer un nouveau composant que j’ai appelé GroovierMBean : celui-ci convertit à la volée les ObjectName pour que le script appelant récupère à la place un nouveau GroovierMBean directement exploitable pour continuer la navigation.

Associé à une autre petite classe utilitaire (WebLoMBean) pour faciliter l’accès remote au serveur JMX weblogic, il suffit maintenant que de quelques lignes pour, par exemple, vérifier que toutes les queues JMS d’un domaine ont une queue d’erreur configurée :

def domain = fr.ippon.groovy.util.WebLoMBean.getDomainMBean('t3://localhost:7001','weblogic','weblogic'); domain.DomainConfiguration.JMSSystemResources.each { module -> module.JMSResource.Queues.each { queue -> if(!queue.Name.endsWith("_error")) { if(queue.DeliveryFailureParams.ErrorDestination == null) { println "La queue ${queue.Name} n'a pas de queue d'erreur" } } } }

Vous aurez remarqué qu’aucune référence à GroovierMBean n’apparaît dans cet exemple : en effet, une fois récupéré l’instance
pointant sur le MBean racine du MBeanServer DomainRuntime du domaine WebLogic ( via l’appel à WebLoMBean ) il n’est ici plus nécessaire d’en réinstancier explicitement, pourtant la plupart des objets manipulés par le script sont des GroovierMBean.
Pour des besoins plus compliqués il sera parfois plus simple de rechercher les mbeans de manière classique en interrogeant le serveur JMX puis d’utiliser explicitement GroovierMBean pour accéder aux MBeans dépendants

J’espère que cette petite présentation permettra à ceux que la complexité de JMX rebutait de se lancer dans la manipulation des mbeans et peut-être par la même occasion de découvrir les possibilités du langage Groovy.

Ressources :

Vous trouverez attachées à cette page un zip contenant l’environnement nécessaire pour exécuter le script ci-dessus (nécessite une install de Ant, de Groovy et de WebLogic)

Author image
Fort de plus de 20 ans d'expérience autour de l'écosystème JavaEE, Fabien accompagne ses clients dans la conception et le cadrage de leurs projets.