Les nouveautés de Maven 2.1.0

Bonjour à tous,

Vous pouvez dès à présent télécharger Maven 2.1.0. Comme j’avais pu vous l’annoncer dans mon précédent billet, cette nouvelle version apporte quelques nouveautés assez intéressantes que je vous décris ici :

  • Sécurisation des mots de passe
  • Résolution en parallèle des artefacts
  • Le build multi-modules incrémental

Sécurisation des mots de passe

Les mots de passe que vous utilisez pour accéder depuis Maven aux serveurs (de référentiels de binaires, de sites web, …) sont stockés dans les settings de l’utilisateur ${home}/.m2/settings.xml (par défaut).
Maven 2.0.X ne permettait de stocker ces mots de passe qu’en clair. Cela posait un évident problème de sécurité si un tiers se procurait ce fichier. Problème encore plus important en entreprise car ces mots de passes étaient souvent ceux des annuaires de l’entreprise et ne permettaient donc pas seulement d’accéder à des ressources “Maven” mais à différents systèmes.

Maven 2.1.0 offre donc des options pour chiffrer vos mots de passe, de manière à ce que ces derniers ne soient pas facilement consultés.
Il permet, en plus, d’utiliser un système de clef privée qui peut facilement être déporté sur une ressource amovible comme un clef USB.

Mise en place de la clef privée

Pour mettre en oeuvre ce système nous commençons par générer notre clef privée.
La commande “mvn --encrypt-master-password <password>” (ou “mvn -emp <password>“) permet de chiffrer le mot de passe en paramètre. Il s’agit là plus d’un système de clef privé que d’un mot de passe principal comme noté dans la documentation Maven. Vous n’aurez plus à retenir et à saisir ce mot de passe, puisque Maven va utiliser sa version chiffrée pour (dé)crypter les mots de passe des serveurs. Ce qui devient important c’est la sécurisation de cette clef privée.

Nous chiffrons le “mot de passe” principal ainsi :
[sourcecode language=’bash’]
arnaud@leopard:~$ mvn –encrypt-master-password toto
{dZPuZ74YTJ0HnWHGm4zgfDlruYQNda1xib9vAVf2vvY=}
[/sourcecode]
Nous créons un fichier ~/.m2/settings-security.xml avec le contenu suivant :
[sourcecode language=’xml’]

{dZPuZ74YTJ0HnWHGm4zgfDlruYQNda1xib9vAVf2vvY=}

[/sourcecode]
Le tag master contient la clef privée générée précédemment.

A partir de ce moment vous pouvez comme cela est décrit à l’étape suivante chiffrer vos mots de passe de serveurs.
Ceci vous permet d’avoir un premier niveau de sécurisation de vos mots de passe puisque ces derniers ne sont plus lisibles.
Par contre vous pouvez toujours vous les faire voler très facilement car il suffit que quelqu’un s’approprie les fichiers ~/.m2/settings.xml et ~/.m2/settings-security.xml de votre compte pour avoir votre identité depuis Maven sur les serveurs avec lesquels il dialogue.

Pour aller plus loin dans la sécurisation vous pouvez donc déporter votre clef privée sur une lecteur amovible comme une clef USB. Pour cela vous déplacez votre fichier ~/.m2/settings-security.xml sur un disque externe puis vous recréez un nouveau fichier
~/.m2/settings-security.xml avec cette fois-ci le contenu suivant :
[sourcecode language=’xml’]

/Volumes/clefUsbArnaud/secure/settings-security.xml

[/sourcecode]
Dans le tag relocation vous indiquez le chemin vers le véritable fichier settings-security.xml.
Et voilà votre environnement est mieux sécurisé puisqu’un voleur ne pourra plus rien faire en dérobant votre fichier settings.xml de Maven. il devra aussi récupérer le fichier settings-security.xml qui se trouve sur votre clef USB.

Chiffrement d’un mot de passe de serveur

Pour chiffrer le mot de passe d’un serveur il faut utiliser la commande “mvn --encrypt-password <password>” (ou “mvn -ep <password>“). Cette dernière chiffre votre mot de passe à partir de votre mot de passe principal (clef privée). Vous stockez ensuite cette version chiffrée de votre mot de passe dans la déclaration de votre serveur dans le fichier ~/.m2/settings.xml.
Par exemple, nous chiffrons le mot de passe “titi” :
[sourcecode language=’bash’]
arnaud@leopard:~$ mvn –encrypt-password titi
{SbC9Fl2jA4oHZtz5Fcefp2q1tMXEtBkz9QiKljPiHss=}
[/sourcecode]
Puis nous l’enregistrons dans nos settings :
[sourcecode language=’xml’]





mon.server
arnaud {SbC9Fl2jA4oHZtz5Fcefp2q1tMXEtBkz9QiKljPiHss=}





[/sourcecode]

Résolution en parallèle des artefacts

Il est très souvent reproché à Maven de télécharger la terre entière lorsque l’on vient de l’installer ou lorsque l’on construit pour la première fois un projet. Maven ne peut pas faire grand chose sur le nombre de dépendances téléchargées. Cela incombe aux descripteurs de projets. Soit ceux des librairies utilisées dans votre projet ou ceux de plugins Maven utilisés lors de la construction.

Par contre Maven 2.1.0 vous permet enfin d’utiliser un peu mieux votre bande passante en téléchargeant en parallèle plusieurs artefacts. Par défaut Maven pourra télécharger jusqu’à 5 artefacts appartenant à des groupIds différents. Vous pouvez faire varier ce nombre en modifiant votre configuration à l’aide de la propriété maven.artifact.threads. Vous pouvez la définir soit ponctuellement en ligne de commande (-Dmaven.artifact.threads=3) soit en permanence dans la variable d’environnement MAVEN_OPTS.

Il ne faut pas s’attendre à des merveilles avec cette optimisation qui de toute façon n’agit que lorsque vous avez à télécharger des nouvelles dépendances (pas tous les jours normalement). Dans mon cas j’ai pu sur un petit projet passer de 4 minutes à 3 minutes pour le temps de premier build avec un repository local vide.

Le build multi-modules incrémental

Lorsq’un projet Maven est constitué de plusieurs modules on peut facilement perdre du temps à reconstruire l’ensemble des modules pour valider une modification faite seulement dans un seul. Contrairement à Make qui ne lance une target que si les sources ont été modifiées plus récemment que les artefacts générés, Maven ne savait pas, il y a encore peu de temps, ne reconstruire que les modules impactés par la modification de l’un d’entre eux.

Ceci a été corrigé par le plugin reactor qui permet d’ajouter ce type de comportement à Maven, et ce même en version 2.0.X.

La version 2.1.0 de Maven permet d’avoir nativement ce type de service sans recourir au plugin reactor. Il faut cependant noter que le plugin offre des services additionnels comme la reconstruction en fonctions des sources modifiées par rapport au gestionnaire de versions qui ne sont pas adressées nativement par Maven 2.1.0.

Imaginons que nous avons 3 modules : moduleA, moduleB, et moduleC. Nous partons du principe que moduleB dépend de moduleA, et moduleC, dépend de moduleB.

Si nous modifions le code de moduleB et que nous reconstruisons classiquement notre projet, Maven va relancer la construction des 3 modules.
[sourcecode lang=”bash”]
arnaud@leopard$ mvn clean install
[INFO] Scanning for projects…
[INFO] Reactor build order:
[INFO] ModuleA
[INFO] ModuleB
[INFO] ModuleC
[INFO] Reactor
[INFO] ————————————————————————
[INFO] Building ModuleA
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building ModuleB
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building ModuleC
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building Reactor
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] ModuleA ……………………………………….. SUCCESS [4.469s]
[INFO] ModuleB ……………………………………….. SUCCESS [0.056s]
[INFO] ModuleC ……………………………………….. SUCCESS [0.065s]
[INFO] Reactor ……………………………………….. SUCCESS [2.300s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 7 seconds
[INFO] Finished at: Mon Mar 23 01:32:29 CET 2009
[INFO] Final Memory: 13M/26M
[INFO] ————————————————————————
[/sourcecode]

Maven 2.1.0 propose quelques nouvelles options pour optimiser notre construction :

Option Description
-amd,–also-make-dependents If project list is specified, also build projects that depend on projects on the list
-rf,–resume-from Resume reactor from specified project
-am,–also-make If project list is specified, also build projects required by the list
-pl,–projects Build specified reactor projects instead of all projects

Pour ne reconstruire que le moduleB modifié :
[sourcecode lang=”bash”]
arnaud@leopard$ mvn clean install -pl moduleB
[INFO] Scanning for projects…
[INFO] ————————————————————————
[INFO] Building ModuleB
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 4 seconds
[INFO] Finished at: Mon Mar 23 01:35:08 CET 2009
[INFO] Final Memory: 9M/19M
[INFO] ————————————————————————
[/sourcecode]

Pour reconstruire le moduleB ainsi que les modules qui en dépendent :
[sourcecode lang=”bash”]
arnaud@leopard$ mvn clean install -pl moduleB -amd
[INFO] Scanning for projects…
[INFO] Reactor build order:
[INFO] ModuleB
[INFO] ModuleC
[INFO] ————————————————————————
[INFO] Building ModuleB
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building ModuleC
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] ModuleB ……………………………………….. SUCCESS [3.565s]
[INFO] ModuleC ……………………………………….. SUCCESS [0.077s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 4 seconds
[INFO] Finished at: Mon Mar 23 01:38:37 CET 2009
[INFO] Final Memory: 9M/19M
[INFO] ————————————————————————
[/sourcecode]

Pour reconstruire le moduleB ainsi que les modules qui nécessaires à sa construction :
[sourcecode lang=”bash”]
arnaud@leopard$ mvn clean install -pl moduleB -am
[INFO] Scanning for projects…
[INFO] Reactor build order:
[INFO] ModuleA
[INFO] ModuleB
[INFO] ————————————————————————
[INFO] Building ModuleA
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building ModuleB
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] ModuleA ……………………………………….. SUCCESS [3.828s]
[INFO] ModuleB ……………………………………….. SUCCESS [0.072s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 4 seconds
[INFO] Finished at: Mon Mar 23 01:41:29 CET 2009
[INFO] Final Memory: 9M/20M
[INFO] ————————————————————————
[/sourcecode]

Pour relancer le build multi-modules complet à partir du moduleB :
[sourcecode lang=”bash”]
arnaud@octo-ahe$ mvn clean install -rf moduleB
[INFO] Scanning for projects…
[INFO] Reactor build order:
[INFO] ModuleB
[INFO] ModuleC
[INFO] Reactor
[INFO] ————————————————————————
[INFO] Building ModuleB
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building ModuleC
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Building Reactor
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] ModuleB ……………………………………….. SUCCESS [3.726s]
[INFO] ModuleC ……………………………………….. SUCCESS [0.100s]
[INFO] Reactor ……………………………………….. SUCCESS [3.034s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 7 seconds
[INFO] Finished at: Mon Mar 23 01:43:47 CET 2009
[INFO] Final Memory: 13M/26M
[INFO] ————————————————————————
[/sourcecode]

MAJ 22 mai 2009 : A la demande de petitoheme voici le petit projet utilisé pour présenter le build multi-modules incrémental : Un simple projet multi-modules

16 thoughts on “Les nouveautés de Maven 2.1.0”

  1. Bravo pour ce tutorial simple et clair à mettre en place.

    Je le garde sous le coude quand je migrerais sur la version 2.1 🙂

  2. Bien le build multi-modules incrémental, parce que quand on a 15-20 sous-modules ca peut faire gagner beaucoup de temps.

  3. Je m’en vais le tester de suite car ce sont deux avancées majeures (résolution en parallèle et reactor) pour avoir un outil de build efficace.

  4. Autre grosse amélioration dans la 2.1.0 que j’ai oublié de noter : L’amélioration des performances pour résoudre les dépendances dans le réacteur.
    Sur un projet volumineux (150 modules) qui passait 8 minutes à résoudre les dépendances pour calculer l’ordre d’exécution dans le réacteur en 2.0.10, avec maven 2.1.0 on tombe à moins d’une minute.

  5. Il serait possible d’avoir les sources du projet build multi-project? 😉
    Merci d’avance.

  6. Bonjour Arnaud,

    voila je suis derière un proxy qui empeche l’exécution de maven, que dois je changer sur le fichier settings.xml ?

    merci
    Bien cordialement
    Abdel

  7. Il te faut rajouter potentiellement qquechose comme :
    <proxies>
    <proxy>
    <active>true</active>
    <protocol>http</protocol>
    <host>proxyhost</host>
    <port>proxyport</port>
    <nonProxyHosts>*.monentreprise.fr</nonProxyHosts>
    </proxy>
    <proxy>
    <active>true</active>
    <protocol>https</protocol>
    <host>proxyhost</host>
    <port>proxyport</port>
    <nonProxyHosts>*.monentreprise.fr</nonProxyHosts>
    </proxy>
    </proxies>

    cf : http://maven.apache.org/guides/mini/guide-proxies.html

  8. Juste parce que je me suis fait embêter pour le settingssecurity :
    FATAL ERROR: Error encrypting password: org.codehaus.plexus.util.xml.pull.XmlPullParserException: Expected root element ‘settingsSecurity’ but found ‘settingssecurity’ (position: START_TAG seen … @1:18)

    Il faut mettre un S majuscule (dans un fichier XML, c’est mal !) au S de security.

    1. Merci pour ce retour. Effectivement les erreurs Maven 2 sur la validation des fichiers et erreurs rencontrées ne sont pas très “user friendly”. Nous essayons d’améliorer cela pour Maven 3.

Comments are closed.