Configurer automatiquement Eclipse avec Maven

En ce beau matin d’hiver, me voilà bien décidé à effectuer un peu de ménage sur notre projet. Ma cible d’aujourd’hui : la chasse aux warnings.

Grosso modo, j’observe qu’il y a 3 types de warning :

  • imports inutilisés (60%)
  • unchecked casts (30%)
  • variables ou méthodes private non utilisées (10%)

Je prends mon bâton de pèlerin et je nettoie. Cependant, je me rends bien compte que ces warnings sont pour la majorité des erreurs d’inattention qui pourraient être facilement évitées.

A quoi bon nettoyer, si c’est pour se retrouver dans la même situation dans trois mois ? Donc, en plus de ma maintenance corrective, je pars également à la recherche d’une action préventive.

Première idée évidente, configurer Eclipse pour que celui-ci effectue ce genre de nettoyage lors d’une sauvegarde d’un fichier. Facile, il suffit de paramétrer ceci dans Properties -> Java Editor -> Save Actions (Plus de détails ici).

Cependant, à quoi bon le faire uniquement sur mon Eclipse ? Quel intérêt, si les autres membres de l’équipe ne bénéficient pas eux aussi de la même configuration ? Comment faire en sorte que ma configuration soit facilement partagée avec les autres ?

Le projet étant un projet maven, le maven-eclipse-plugin semble offrir la solution.

Construire sa configuration cible idéale

Le plus facile est de le faire via Eclipse. On choisit un projet java et on se définit la configuration voulue dans les properties. Je ne vais pas vous conseiller particulièrement, ceci étant souvent une affaire de gout. Allez jeter un coup d’œil notamment dans :

  • Java Code Style : Clean Up, Code Templates, Formatter
clean-up-ok
  • Java Compiler -> Errors/Warning : pour redéfinir le niveau des alertes. Il peut être intéressant de bloquer directement depuis l’IDE certaines sources d’erreurs, comme par exemple : x == x ou x =x…
errors-warning-ok
  • Java Editor -> Save Action (vu précédemment) :
save-action-ok

Enregister sa configuration dans Maven

Une fois le paramétrage effectué, il suffit d’aller récupérer le résultat dans le répertoire .settings du projet. Vous trouverez dans ce répertoire les fichiers contenant la configuration réalisée précédemment (org.eclipse.jdt.ui.prefs, org.eclipse.jdt.core.prefs, etc.). Ce sont des fichiers de propriétés contenant ce genre d’information :

#Wed Dec 15 14:36:54 CET 2010
cleanup.add_default_serial_version_id=true
cleanup.add_generated_serial_version_id=false
cleanup.add_missing_annotations=true
cleanup.add_missing_deprecated_annotations=true
cleanup.add_missing_methods=false
cleanup.add_missing_nls_tags=false
cleanup.add_missing_override_annotations=true
cleanup.add_missing_override_annotations_interface_methods=true
...

Il suffit maintenant d’extraire tout le contenu nous intéressant et de le mettre dans la configuration du maven-eclipse-plugin. Par exemple :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>fr.xebia.build.tools</groupId>
  <artifactId>testConfMaven</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.7</version>
        <configuration>
          <downloadSources>true</downloadSources>
          <additionalConfig>
            <file>
              <name>.settings/org.eclipse.jdt.ui.prefs</name>
              <content><![CDATA[
 eclipse.preferences.version=1
 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
 sp_cleanup.add_default_serial_version_id=true
 sp_cleanup.add_missing_annotations=true
 sp_cleanup.add_missing_deprecated_annotations=true
 sp_cleanup.add_missing_override_annotations=true
 sp_cleanup.add_missing_override_annotations_interface_methods=true
 sp_cleanup.always_use_blocks=true
 sp_cleanup.make_private_fields_final=true
 sp_cleanup.make_variable_declarations_final=true
 sp_cleanup.never_use_parentheses_in_expressions=true
 sp_cleanup.organize_imports=true
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.remove_private_constructors=true
 sp_cleanup.remove_trailing_whitespaces_all=true
 sp_cleanup.remove_unnecessary_casts=true
 sp_cleanup.remove_unused_imports=true
 sp_cleanup.remove_unused_private_fields=true
 sp_cleanup.remove_unused_private_types=true
 sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
 sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
                ]]>
              </content>
            </file>
          </additionalConfig>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

A noter, on peut également mettre cette configuration dans des fichiers externes, qui seraient embarqués dans une dépendance maven :

<plugin>
  <artifactId>maven-eclipse-plugin</artifactId>
  <version>2.7</version>
  <configuration>
    <additionalConfig>
      <file>
        <name>.settings/org.eclipse.jdt.ui.prefs</name>
        <location>settings/org.eclipse.jdt.ui.prefs</location>
      </file>
      <file>
        <name>.checkstyle</name>
        <location>/.checkstyle</location>
      </file>
    </additionalConfig>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>fr.xebia.build.tools</groupId>
      <artifactId>xebia-eclipse-conf</artifactId>
      <version>0.0.1</version>
    </dependency>
  </dependencies>
</plugin>

Notre projet xebia-eclipse-conf est une dépendance maven du projet et possède la structure suivante :

|-src
|—main
|—–resources
      |–.checkstyle
      |–settings
        |–org.eclipse.jdt.ui.prefs

Une fois la configuration faite, il suffira aux développeurs d’exécuter la commande mvn eclipse:m2eclipse ou mvn eclipse:eclipse (si vous n’utilisez pas m2Eclipse) puis de faire un refresh sur votre projet.

Nous utilisons la version 2.7 du maven-eclipse-plugin, car le goal eclipse:m2eclipse a été supprimé de la version 2.8 (voir l’explication de Jason van Zyl). Cependant, aucune autre alternative valable n’existe à notre connaissance pour générer les fichiers de configuration d’Eclipse. Le salut pourra venir des « Extension points », cependant cette solution ne paraît pas encore utilisable en l’état.

Point d’attention

Ce n’est pas parce que l’on peut tout faire, qu’il est souhaitable de tout mettre dans notre configuration. Le mieux est l’ennemi du bien, et il convient donc de trouver un juste équilibre entre ce qui est vraiment utile et ce qui pourrait devenir une contrainte pour certaines personnes. Quoi qu’il arrive, il est important que l’équipe valide ensemble le contenu plutôt qu’une personne isolée fasse selon ses goûts.

Voilà pour l’astuce ! Maintenant, vous allez me dire que dans votre équipe un vilain petit canard utilise Intellij Idea. Je ne connais pas encore le pendant de cette méthode. Peut-être que le maven-idea-plugin fait l’affaire. Si vous connaissez une solution viable, n’hésitez pas à poster la solution en commentaire.

Billets sur le même thème :

18 commentaires

  • Quelle énergie dépensée juste pour ne pas commiter les fichiers .settings sur le SCM ! :(

    Pour moi, le remède est pire que le poison .. car généralement, les principaux détracteurs contre la mise en conf des .settings utilisent l’argument du multi IDE.

    Or là, si on prend cet argument, c’est potentiellement encore pire (car on va devoir multiplier les artefacts de « fichiers externes » en fonction du nombre d’IDE).

    Et le principal inconvénient, c’est que si quelqu’un fait une modification en loose day de sa configuration IDE, il n’aura pas une petite étoile sur son fichier .settings qui lui signalera que :
    – Modifier les fichiers de conf qui ont été mis en place par le guru eclipse du projet, c’est mal..
    – … et, même si c’était justifié, il serait intéressant de commiter la modification et d’en faire bénéficier les copains d’à coté (alors que dans la solution présentée, il faudrait releaser l’artefact xebia-eclipse-conf + le déployer dans le repo d’entreprise + aligner le pom du projet sur cette nouvelle version .. « pff » pour une pauvre modif de fichier…)

    Pour résumer, je trouve que ce n’est vraiment pas une bonne idée :(

  • Bonjour Frédéric,

    Je comprends bien tes arguments et je n’y suis pas totalement opposé. La solution la plus simple est souvent la meilleure en effet.
    Cependant, selon moi il y a des limites à cette approche (d’où l’article ;) ) :
    – Comment partager une configuration entre plusieurs modules maven sans que chacun ait à modifier les préférences globales d’Eclipse?
    – Comment partager une configuration entre plusieurs projets?
    – Comment éviter que chacun se marche sur les pieds et commite à tour de rôle (volontairement ou non) sa préférence d’utilisation d’Eclipse ?

    Ce n’est peut-être pas le besoin de tout le monde, mais ce fut en tout cas le mien :)

    Merci pour ton commentaire.
    Nathaniel (Xebia)

  • Bonjour,

    Autrement il est possible d’exporter toute la configuration des préférences du workspace Eclipse depuis le menu File/Export/Preferences.

    Cet export, qui se présente sous la forme d’un fichier *.epf peut être stocker dans le SCM.
    Il suffit donc de le ré-importer ensuite depuis le menu File/Import/Preferences.

    Ce n’est peut-être pas aussi élégant que l’utilisation du plugin maven mais cela a déjà fait ses preuves sur mes projets :-)

    Antony (Ippon Technologies)

  • BOnjour,

    +1 pour embarquer les settings dans des dépendances Maven spécifiques. Avec un projet bien monté, tout cela devient transparent au développeurs. Les settings Eclipse avec formatage, imports, tout y passe. On peut même faire de même pour checkstyle et compagnie.
    A la charge du développeur de se plier un minimum au règles définies par sa boite, qui ne me semble pas un énorme effort dans ce cas.

    Christophe – PetalsLink

  • Ok je comprend l’argumentaire du « multi projet » où on souhaiterait partager la même conf IDE de manière transverse à plusieurs projets.

    Cependant, ça ne vous arrive jamais, à vous, d’avoir différentes typologies de projets ? Projet java « simple », projet web, projet EJB, projet EAR, Tests d’inté, et j’en passe ..
    Chaque typologie ayant des fichiers complètement différents (ne serait-ce que par les natures eclipse entrant en jeu, la conf du WTP etc..)

    Il faudrait alors faire un artefact maven à l’intersection de chaque « dimensions », les dimensions étant { IDE, typologie projet }
    Si on prend IDE = { Eclipse, Netbeans, IDEA } et TyposProjet = { Java simple, Web, EJB, EAR, Tests } ça donne quand même 15 artefacts à gérer !
    Bon ok je m’emporte …

    Peut-être que le meilleur des monde se situe « entre les deux ».
    Utiliser le plugin maven comme « starter kit » des settings, et ensuite, la mise en conf de ces derniers pour potentiellement les faire évoluer en fonction des spécificités du projet ?

  • Bonjour à tous,

    J’étais très emballé par ton article, la fin m’a quand même effrayé sur la disparition du goal eclipse:m2eclipse et qu’il faille utiliser une ancienne version.

    Dans notre cas pour partager les préférences utilisateurs des environnements Eclipse nous utilisons Workspace Mechanic qui est déployé en même temps que l’Eclipse.

    Mickael

  • Je confirme que l’intégration de fragments de conf IDE dans le POM est une solution ignoble (qui marche, certes). Passer par une dépendance maven est un peu moins pire. Ce qui me choque, c’est que le problème que tu évoque n’est pas propre à ton projet : cette conf, tu devrais l’appliquer à tous tes postes de dev quelque soit le projet considéré. Alors pourquoi ne pas mettre Eclispe préconfiguré dans une dépendance Maven :P

  • @ndelook : mdr pour le eclipse en dépendance Maven.. on finira par y arriver :-)

    Bon article, qui présente une des solutions possibles.

    La seule chose qui me chiffonne : M2Eclipse semble de plus en plus être la solution la plus largement choisie pour intégrer Maven et Eclipse. Dès lors qu’il est fortement recommandé de ne pas mélanger M2Eclipse et le maven eclipse plugin, cette solution n’est plus envisageable.

    Ce que je fais : j’utilise M2Eclipse, et… je commit les .settings, mais aussi les .project, et les .classpath ! WTF ??

    Il s’avère qu’il est aujourd’hui tout à fait possible d’avoir une conf Eclipse ne comportant aucun chemin absolu (merci M2_REPO). De plus, ces fichiers varient en général assez peu. Et justement, il est intéressant de voir précisément ce qu’on a changé.

    Cela s’avère aussi très pratique quand on a un plein de projets Maven multi machin multi truc, et que d’un seul coup Eclipse ne veut plus reconnaître un projet, ne veut plus lancer une webapp, etc. Un coup de diff, et on voit tout de suite ce qui a changé.

    Après tout, un outil de gestion de conf… c’est pas fait pour gérer la conf ?

    Quand à l’argument « les dévs vont changer la conf à chaque commit sans rendre compte » => Stop using SVN ! Il serait temps de s’intéresser en détail à ce que vous committez, et j’ai réalisé que depuis que j’utilise Git (ou git svn), je fais beaucoup plus attention à mes commits.

  • @Piwaï je pense qu’on va voir plus de projectconfigurators pour m2eclipse, j’en ai fait un pour checkstyle (c’est pas tellement compliqué), j’ai suggéré à l’équipe Google Eclipse d’en faire un aussi pour gwt, etc… Ca ne forcerait pas le « save Action » sur chaque poste de dev, mais ça serait déjà un grand pas vers des postes mieux auto-configurés.

    Maintenant, on revient au problème que chaque poste doit avoir les plugins adéquats installés. Tiens, pourquoi ne pas committer Eclipse dans SVN ? :P

  • Pour ma part, ça me perturbe fortement d’avoir une configuration d’IDE dans les sources du code et pour plusieurs raisons :

    – Ca pollue un projet avec des réglages spécifiques à un IDE, mes amis NetBeans et IntelliJ vont appréciés.

    – Comme dit plus haut, le mariage d’Eclipse et Maven, c’est quand même plus m2eclipse actuellement le plugin Maven pour Eclipse.

    – Qu’on fixe des règles commune pour l’ensemble des développeurs de règles, c’est normal, mais là on le met au niveau projet (et dans son source) au lieu de le régler au niveau poste de travail, un SCM ne doit pas devenir un gestionnaire de configuration de poste, mélange des genres délicats et dangereux.

    Ce qui serait utile, c’est de voir si une mécanique proche ne permettrait pas de configurer le poste Eclipse, mais globalement car là ça serait intéressant dans le cadre du déploiement de postes d’après des calibres bien précis.

  • Hello,
    -1 pour avoir des fichiers ide dans les sources (j’en tellement avec des paths genre c:\\Program Files\\Mon Jdk … )
    Si cette conf sert à vérifier des règles de code.
    Et hop le plugin sonar pour eclipse et voili les warnings qui viennent de sonar !

  • Pour le partage d’une configuration eclipse (avec ses plugins), il y a Pulse qui existe et qui propose de livrer des configuration d’eclipse toutes prêtes bundlées avec un ensemble de plugins et des préférences eclipse pré-configurées
    Je n’ai pas de retour d’XP dessus, j’avais proposé de l’utiliser il y a de ça bien longtemps… mais c’est tombé aux oubliette :(

    Et puis il y a aussi le eclipse marketplace (http://marketplace.eclipse.org/) qui permet de créer une url « perso » permettant de mettre à disposition un ensemble de repositories p2 qu’on affectionne tout particulièrement.
    Ca ne résoud pas la problématique projet cela dit..

    Chez nous, on utilise hudson pour créer un nouveau projet.
    Il se repose sur :
    – Un archetype maven qu’on lui passe en paramètre, et qui va se charger d’initialiser l’arbo projet (.settings inclus)
    Cet archetype peut se reposer sur un ensemble de propriétés qui seront filtrées durant la création du projet. Ces propriétés sont saisies via un build paramétré d’Hudson.
    – Un script ant qui va faire un svn add sur tous les modules, et mettre en ignore l’ensemble des répertoires à ne pas synchroniser (bin folder eclipse, répertoire target de maven ..)
    => Les .settings sont initiés au début, commités via hudson … et ils vivent tout au long du projet.
    Ces .settings sont toujours les mêmes d’un projet à un autre (sauf si on fait un peu évoluer l’archetype… ce qui arrive).

  • @Henri « c’est de voir si une mécanique proche ne permettrait pas de configurer le poste Eclipse » => voir Workspace Mechanic de Google.

  • Je n’ai jamais mis un seul fichier IDE en SCM depuis plusieurs années et je n’ai jamais rencontré un seul problème.

    En revanche, +1 pour mettre un Sonar et corriger tout ce code mort que l’on voudrait cacher sous le tapis.

  • Pourquoi je met ma conf de formatage IDE en SCM :

    – Comme j’aime bien avoir du code lisible, je souhaite qu’il soit correctement formaté par Eclipse.
    – Différents développeurs sur le même projet à différentes périodes, pas de règles de formatage définie => chacun a eu les siennes.
    – Comme je suis un flemmard qui n’aime pas faire Ctrl+F, je met en place les « Save actions » Eclipse, avec l’option « mettre en forme tout le fichier à chaque sauvegarde ».
    – Très vite, je me retrouves avec le problème suivant : je corrige un bug, une seule ligne dans un fichier. Je le formate par la même occasion. Du coup, dans le diff du SCM, c’est un gros bordel : impossible de voir rapidement quel micro changement j’ai réalisé.

    Solutions pour garder mes commits lisibles :
    – Soit je ne formate jamais les fichiers
    – Soit je commence toujours par formater un fichier / le commiter avant de le modifier lors d’un commit suivant
    – Soit je formate tous les fichiers du projet à ma sauce une bonne fois pour toute, en un commit.

    Cependant, les deux dernières solutions sont d’un intérêt très limité si un autre développeur travaille avec moi avec des règles de formatage différentes.

    Il faut donc unifier les règles de formatage. C’est d’ailleurs l’objet essentiel de cet article, il me semble. Et c’est là qu’on entre dans les discussions de « où placer cette conf de formatage ».

    Je ne connais pas d’outil permettant de créer une conf unique, multi IDE, stockée sur le SCM du projet, modifiable par tous, et appliquant toute modification de formatage à tous les fichiers.

    Une solution intéressante serait de placer un outil de ce type en pre commit hook, ou au sein de l’outil d’intégration continue.

  • Au-delà des règles de formatages, il y a aussi le « paramétrage » de son application web par exemple.

    Laisser un nouvel arrivant projet configurer son workspace, c’est *potentiellement* se confronter :
    – Au fait que ce nouvel arrivant soit complètement débutant eclipse (ou tout autre IDE), et ne sache tout bonnement pas paramétrer son environnement => il ne pourra pas être techniquement autonome
    – Qu’il configure « mal » son environnement.. Par exemple qu’il utilise un mauvais contextRoot pour son application web, ou encore qu’il gère mal l’ordre des classpaths de son application

    Le commit des éléments sur le SCM a les intérêts suivants pour moi :
    – Réduction à son maximum du coût d’entrée « technique » d’un nouvel arrivant sur le projet (dans notre cas où l’arbo est initiée par Hudson, il checkout ce qu’il y a sur le SCM, et c’est parti !)
    – Partage de l’évolution d’une configuration IDE entre les développeurs : si un fichier est modifié en local, soit il faut le commiter (car légitime), soit il faut le reverter (car conf locale désynchronisée de celle des autres). Charge aux développeurs de ne pas « updater n’importe quoi » (typiquement, à chaque fois que je vois, dans ma vue synchronize, qu’un truc a changé dans le .settings, je regarde ce qui a changé et si je ne suis pas d’accord, je dialogue avec le commiter de la modif pour qu’il la rollback le cas échéant)
    – Régulièrement, on regarde l’historique des .settings pour reporter ces évolutions dans nos archetypes maven (afin de faire bénéficier des évolutions les projets futurs)

    Par contre, il faut être vigilant à ce qui est commité, notamment au niveau du fichier .classpath où, comme le dit olivier, il est possible de positionner des paths de JRE en dur (il faut juste savoir bien utiliser l’onglet Windows > Preferences | Java > Installed JREs > Execution Environnment et les environnement d’exécution « pré configurés » dans eclipse (on n’a juste qu’à faire un mapping « en local » de [jre/jdk XXX] => [exec environnment])

    Après, je suis complètement d’accord que lorsqu’on sait qu’on travaille sur un projet où, potentiellement, on aura des intervenants qui utiliseront l’IDE de leur choix (typiquement : un projet opensource !), il vaudra mieux passer par un outillage mettant en place l’infrastructure projet (à coup de starter kit, de script ant, de plugin maven, de doc dans un wiki, qu’importe …)

    En revanche, lorsqu’on sait que tous les développeurs utiliseront le même IDE, je trouve dommage de ne pas bénéficier de cette homogénéité en commitant la conf de l’IDE sur le SCM.

  • Pour moi la mise en SCM des configs Eclipse, c’est une pratique antérieure à l’arrivée de maven, m2eclipse et checkstyle.

    Il y a beaucoup de pratiques qui deviennent obsolètes avec l’arrivée de nouveau outils. Et c’est un bonheur de pouvoir supprimer les .settings .project .classpath quand on souhaite recharger un projet :)

Laisser un commentaire