Technologies

Développement d’un contrôle de code en intégration continue

Publié le : Auteur: Philippe HACQUIN Laisser un commentaire
technologies

Cet article illustre un outillage simple destiné à contrôler avec PMD les sources d’une application Java EE 5, ainsi que sa mise en oeuvre en intégration continue dans une configuration Maven.

Le besoin

J’ai rencontré récemment un problème concernant une classe Java Entity (EJB 3) comportant de facto une annotation @Table.

Cette annotation était qualifiée avec son attribut schema, rappelant le schéma de base de données ayant servi à générer le code Java de ce bean entité. Le problème est que dans les différents environnements de test ou production, le nom de schéma de base est différent de celui en environnement de développement. Et donc, lorsque le schéma est mauvais dans ne serait-ce qu’une classe d’un bean entité, l’initialisation du persistence manager échoue au démarrage de l’application qui devient par conséquent inexploitable.

Cette erreur assez anodine, indétectable dans notre environnement de développement, s’est révélée finalement être très pénalisante car sa correction nécessite évidemment une relivraison d’application, ce qui implique une nouvelle session de tests, une release Maven, de nombreux coups de fils et courriers électroniques échangés avec les intervenants impliqués dans les circuits de validation des applications et mise en production, sans compter que toute relivraison de ce style est évidemment accompagnée d’une pression hiérarchique non négligeable, et doit donc être réalisée en un temps record (et comme chacun sait, toute action précipitée sur un sujet complexe conduit souvent à d’autres complications).

J’ajoute que la génération de code s’appuyait sur les Hibernate Tools; ce problème ne se serait jamais manifesté avec un outillage MDA adapté…

L’analyse du problème

Comment détecter au plus tôt cette erreur ?

  • Dans Eclipse, installer un plugin qui effectuerait ce contrôle ? Nos installations Eclipse cumulaient déjà beaucoup de plugins (JBoss Tools, Websphere tools, …) avec certains conflits, je ne voulais pas compliquer les choses de ce côté-là
  • J’avais mis en place une chaine d’intégration continue avec Hudson, y effectuer le contrôle me semblait une bonne idée. Pourquoi pas, mais alors : dans Checkstyle, PMD, Findbugs, autre ?

Findbugs effectue ses contrôles par analyse du bytecode, ce qui n’est pas trivial mais me semblait peut être plus efficace en termes de rapidité. En revanche, j’ai trouvé la documentation expliquant la manière de développer les extensions un peu trop concise à mon gré (AddingDetectors.txt dans la distribution findbugs-2.0.2).

Mais si Findbugs analyse le bytecode, cela veut dire que l’on doit compiler les sources avant. Quel intérêt de compiler si le contrôle Findbugs échoue ?

J’avais déjà développé il y a quelques années un contrôle spécifique dans Checkstyle. Cet outil effectue une analyse de sources, les contrôles s’écrivent en Java et manipulent des données organisées en arbres de syntaxe (AST). Un rapide coup d’oeil à la documentation (Writing Checks) m’apprend qu’un visualiseur d’arbre syntaxique d’un source existe, pour faciliter l’écriture des règles.

Enfin, PMD : la documentation de développement de règles supplémentaires est tout à fait exploitable (How to write a PMD rule). Deux syntaxes existent à ce sujet : Java et XPATH. PMD est livré avec un outil « PMD rule designer » avec support de Java 6 (et même Java 7 …).

Alors, Checkstyle ou PMD ? J’opte pour PMD : mon premier contrôle sera fait en Java, et je réserve la syntaxe XPATH, déclarative et évitant une classe Java supplémentaire, pour les contrôles que j’aurai à ajouter à l’avenir.

Reformulation technique du besoin : pour toutes les classes annotées @Table, s’assurer que l’attribut schema n’est pas spécifié.

L’intégration dans un build Maven

L’exécution de contrôles PMD dans Maven est prise en charge par le Maven PMD plugin. Au moment de la réalisation, celui-ci n’existait qu’en version 2.7.1 qui ne supportait que PMD 4.3. Information nécessaire car dans le même temps PMD était disponible en 5.0.1, et les API ne sont pas les mêmes …

La réalisation

Le projet Eclipse

Le projet est finalement très simple : une classe Java, un fichier ressource au format XML. Tout cela étant géré par Maven, on fabrique aussi un POM à la racine du projet.

javaProject

L’initialisation du projet est considérablement simplifiée si l’on dispose dans Eclipse du plugin m2e (Maven Integration for Eclipse, directement disponible dans l’Eclipse Marketplace, inclus dans les JBoss Tools, …).

Le POM

pmdExtensionPOM

On n’y trouve qu’une dépendance sur la version de PMD utilisée.

La classe Java

Elle contient le contrôle de présence de l’attribut schema sur une annotation Table (désolé pour les commentaires en anglais, c’est une contrainte de mon client actuel):
pmdExtensionClass

Les points essentiels à noter:

  • Le premier argument de la méthode visit est un ASTNormalAnnotation, ce qui permet de ne traiter que les annotations Java dans les sources
  • Le premier bloc if permet de ne traiter que les annotations @Table; le second bloc if permet d’identifier un attribut schema sur cette annotation
  • Le code utilise l’API PMD en version 4.3. Il évolue un peu en version 5.0 (ce qui sera le cas si vous utilisez les versions récentes du Maven PMD plugin).

La syntaxe du code peut paraître compliquée, mais l’utilisation de l’outil « PMD rule designer » avec un code source comportant une erreur à contrôler simplifie grandement la tâche.

Le descripteur de règles PMD

Il comporte la description de la nouvelle règle, et peut être accompagné d’autres règles standard PMD pour contrôler les sources du module en développement. On peut consulter les ‘rulesets’ standard dans les sources PMD (PMD rulesets).

L’élément rule comporte le nom complet de la classe implémentant la règle, un nom et un message qui apparaîtront en cas d’échec dans les rapports Maven.

pmdRuleset

Le déploiement

Intégration dans les builds des modules EJB

La gestion de persistance dans nos applicatifs est faite en conteneur EJB, c’est donc dans les modules EJB que l’on trouve nos classes Entity. Les POM de ces modules doivent évoluer pour indiquer à Maven l’exécution des contrôles PMD avec notre nouvelle règle.

ejbModulePOM

Donc, pour utiliser PMD 5.0, c’est dans ce POM qu’il faut préciser une version de maven-pmd-plugin en version 3.0 et plus.

Le principe vaut pour tout autre module pouvant comporter des classes entité: JAR simple ou WAR.

Trois remarques sur cet extrait de POM:

  • les descripteurs des règles appliquées sont désignés dans des éléments ruleset
  • on trouve dans les dépendances de ce plugin la version de PMD utilisée …
  • … ainsi que la version du module contenant notre classe de règle personnalisée PMD

Intégration dans Hudson

On arrive maintenant à l’objectif final, s’assurer que les builds en intégration continue échoueront en cas de violation de la règle. Là, sauf erreur de ma part, on a au moins deux possibilités:

  • Installer dans Hudson le plugin PMD
  • Mettre en oeuvre Sonar

Notre serveur d’IC ayant des ressources un peu limitées, j’ai mis de côté Sonar et opté pour la première solution. Je ne vais pas m’étendre sur ce plugin, son installation est très simple, et en fonctionnement il nous remonte tout nouvel échec lors de l’analyse d’un source avec la nouvelle règle PMD sans souci.

Conclusion

J’espère avec cet article avoir aidé à appréhender PMD comme un outil qui aide le développeur dans son travail quotidien, et faire un peu oublier son côté « intégriste » par rapport à quelques unes de ses règles pas toujours claires et quelques fois contestables.

Soyez certains aussi qu’il m’a fallu moins de temps pour développer cette règle que pour rédiger cet article avec WordPress …