Apache Maven

Un article de Wikipédia, l'encyclopédie libre.

Apache Maven
Développeur Apache Software Foundation
Dernière version 2.0.9
Environnement Multi-plateforme
Type Build Tool
Licence Apache 2.0 licence
Site web maven.apache.org

Apache Maven est un outil logiciel libre pour la gestion et l'automatisation de production des projets logiciels Java. L'objectif recherché est comparable au système Make sous Unix : produire un logiciel à partir de ses sources, en optimisant les taches réalisées à cette fin et en garantissant le bon ordre de fabrication.

Il est semblable à l'outil Ant, mais fournit des moyens de configuration plus simples, basés sur le format XML. Maven est géré par l'organisation Apache Software Foundation. Précédemment Maven était une branche de l'organisation Jakarta Project.

Maven utilise un paradigme connu sous le nom de Project Object Model (POM) afin de décrire un projet logiciel, ses dépendances avec des modules externes et l'ordre à suivre pour sa production. Il est livré avec un grand nombre de taches pré-définies, comme la compilation de code Java ou encore sa modularisation.

Maven est un outil très riche qui gagne beaucoup de terrain. C’est aussi un outil jeune, mais dont l'évolution est remarquable.

Un élément clé et relativement spécifique de Maven est son aptitude à fonctionner en réseau. Une des motivations historiques de cet outil est de fournir un moyen de synchroniser des projets indépendants : publication standardisée d'information, distribution automatique de modules jar. Ainsi en version de base, Maven peut dynamiquement télécharger du matériel sur des entrepôts logiciels connus. Il propose ainsi la synchronisation transparente de modules nécessaires.

Maven1 et Maven2 ont été développés en parallèle mais les versions futures seront basées sur la structure de la deuxième version. Les parties suivantes de l'article traitent en priorité Maven2.

Sommaire

[modifier] Fonctionnement général

Maven2 est un logiciel permettant une gestion des projets Java en général et J2EE en particulier. Il est basé sur une optique objet (d’où le Projet Object Model) et il est à ANT ce que le C++ est au C. Les plugins rajoutent des fonctionnalités à cet outil lui permettant d’être plus puissant, ces plugins sont disponibles sur le site de Maven, et, à défaut, peuvent être développés.

En découvrant Maven2, le premier apport qui se dégage est la structure des projets. En effet, Maven2 impose une structure aux projets, dont l'uniformité qui en découle rendra plus aisée la compréhension des projets. La structure obtenue isole, dans un premier temps, les sources des résultats de traitements. Dans les sources, on trouve deux parties, une pour le code lui-même et une autre pour les tests (unitaires, d’intégration…). Et au niveau de chacune des parties, le code est séparé des ressources (images, fichiers annexes..), la webapp étant elle aussi séparée du code java. Au niveau des résultats du traitement on trouve les binaires (du code et des tests), les packages générés et les résultats des tests.

Également présent, un répertoire site qui inclut le site que génère Maven afin de fournir des informations sur le projet et/ou les rapports générés suite aux traitements effectués.

Ces rapports portent sur :

  • les dépendances du projet,
  • les résultats des tests lancés, incluant
  • des statistiques sur les résultats,
  • le pourcentage d’efficacité de ces tests...
  • le pourcentage de code testé,
  • la complexité du code,
  • le respect de telle ou telle norme de codage,
  • etc…

Cette structure engendre des problèmes lors de l’importation sous Eclipse, les packages sont pris à partir de l'emplacement src/java. Pour remédier à cela, on ajoute d’autres racines de sources (s’il y en a) qui sont généralement des sous répertoires de src/java.

Pour la webapp, une configuration d’Eclipse permet de changer le répertoire par défaut (il existe un plugin maven pour Eclipse que l’on verra plus loin).

Un autre problème rencontré au niveau de la génération du site quand on utilise la commande « mvn site », est celui des liens vers les composants. Ici le plugin générait le site avec des liens internes (les liens mènent à des répertoires au sein du répertoire du site lui-même); or lors de la génération une variable, qui se réfère au artifactId, est utilisée.

Cela signifie que pour un projet incluant des sous-projets, on obtient un répertoire dans chaque sous-projet et non pas le site dans un seul répertoire au niveau du POM parent. De fait, les liens ne fonctionnent pas ni entre les sous-projets, ni entre un projet parent et ses fils.

Pour régler ce problème, on lance un « mvn site-deploy » en indiquant une adresse sans paramètre (de Maven) dans l’adresse du déploiement, soit une adresse fixe.

L’utilisation de la même variable pour décrire les projets parents et leurs modules cause des problèmes à plusieurs niveaux (on verra d’autres exemples par la suite).

[modifier] Gestion des dépendances

La gestion des dépendances au sein de Maven est simplifiée par les notions d’héritage et de transitivité, la déclaration de ces dépendances est alors limitée.

Par contre la transitivité recèle encore des lacunes et peut causer des petits soucis sur les gros projets. En effet, la transitivité est automatique par défaut et engendre ainsi des réactions qu’on ne désirait pas spécialement, comme :

  • inclure un jar dans un ear,
  • inclure telle ou telle version au lieu d’une autre,
  • avoir des dépendances avec des versions différentes mais à des niveaux différents de la transitivité (un projet A dépend d’un projet C.x et du projet B, et ce dernier dépend du projet C.y …)

Sans oublier qu’en utilisant la transitivité dans les gros projets, on perd de l’information (par exemple : les dépendances effectives) et on se retrouve dépendants de projets alors qu'il n'y a pas de dépendance dans le code.

Pour résoudre ces différents problèmes, il suffit de désactiver cette option avec l’option "provided" en attendant une amélioration du plugin.

[modifier] Projet Object Model (POM)

Le POM est un fichier XML qui contient toutes les informations nécessaires à Maven pour traiter le projet. Nous y trouvons le nom du projet, le numéro de version, les dépendances vers d'autres projets, les librairies nécessaires à la compilation, les noms des contributeurs ...
Chaque projet contient à sa racine un fichier "pom.xml". Et si le projet contient plusieurs sous-projets, chacun de ces derniers doit en avoir un aussi. On nomme le fichier pom du projet principal: pom parent.

[modifier] Référentiel (ou entrepôts)

Un autre apport de l'outil Maven est son organisation des projets et plugins. Maven dispose de plusieurs référentiels à plusieurs niveaux. Le but du référentiel est de rendre disponible aussi bien les plugins utilisés ou envisagés de l’être que les projets générés par Maven. On peut bien sûr y installer des projets pour les utiliser (sans qu’ils ne soient générés par Maven). Il y a trois référentiels :

  • Un au niveau de la machine du développeur, appelé repository local, il inclut tout ce que le développeur a utilisé et a développé.
  • Un au niveau du site Maven qui contient l’ensemble des plugins. Il est en augmentation continue. Il est ouvert à tout le monde, en conséquence des mises à jour pourraient être incohérentes ou incompatibles avec d’autres.
  • Pour éviter ceci, il y a un troisième référentiel (facultatif) qui peut être déclaré au niveau de l’entreprise ou la structure utilisant Maven, il joue l’intermédiaire entre les deux premiers référentiels, il inclut les plugins (=> maîtrise des versions et des mises à jour) et les projets (les rendant accessible à l’ensemble des développeurs).

Pour créer un référentiel pour l’entreprise (ou un référentiel commun en général), on peut utiliser les protocoles ftp, scp, file et http.

Remarque: le plugin fourni pour le protocole ftp pose problème car pas encore au point.

Pour installer un jar dans le référentiel (sans qu’il ne soit un projet maven), il faut bien générer le POM avec lui. Sans cela Maven essaye de se connecter dans les différents référentiels pour le chercher d'où une réelle perte de temps vu que le jar n’est pas supposé être présent dans ces référentiels.

Une dernière remarque, de taille : dans le référentiel, il y a une structure bien définie et inchangeable (qui permet à Maven de trouver son chemin), où les jar et les projets sont organisés selon le groupId, artifactId puis la version.

Donc une fois une déclaration faite (dépendance ou autre), Maven cherche dans l’emplacement suivant :

{emplacement Repository}/groupId/artifactId/version

Les noms des packages, eux, sont comme suit :

{artifactId}-{version}.{package}

Et à l’opposé du répertoire "target" où on peut définir le nom de notre package, il n’est pas permis de changer les noms ou la structure des packages sous peine de non-reconnaissance de package et donc de "BUILD FAILED".

[modifier] Utilisation des plugins

Pour utiliser un plugin, il suffit de le déclarer dans le POM.

À savoir que la déclaration est héritée par défaut. La déclaration se fait d’une manière simple : groupId (si aucun n’est déclaré, il prend celui par défaut org.apache.maven), artifactId et éventuellement la version (sinon, c’est la dernière version qui est utilisée).

Après cette déclaration, lors du lancement d’une tâche, Maven vérifie sa présence dans le référentiel local. S’il ne trouve pas le plugin, il se connecte alors au référentiel central pour le télécharger. En cas d'échec de récupération, on termine l’exécution avec un message d’erreur (à savoir qu’on peut éviter ceci et demander à Maven de continuer et de donner le résultat du traitement –avec les messages d’erreurs- à la fin).

Par contre, le paramétrage des plugins est rendu difficile par le peu de documentation des différentes fonctions qu’ils offrent. Même sur Internet, le résultat de leur recherche s'est avéré peu fructueux.

Aussi, une liste détaillée des plugins disponibles avec leurs fonctions n’existe pas, on a juste leurs noms (qu’on trouve sur le référentiel de maven).

[modifier] Maven et Eclipse

Eclipse permet de générer des packages, mais ces derniers ne respectent pas la structure de Maven et ne sont pas non plus installés dans le référentiel. Cela implique que sans l’utilisation d’un outil externe, il faut installer manuellement tous les packages générés.

Heureusement, un plugin Maven pour Eclipse est disponible, il permet à Eclipse d’utiliser Maven en arrière-plan et donc avoir Eclipse avec la puissance de Maven.

Ceci nous permet d’avoir des projets Maven générés et stockés dans le référentiel et ainsi avoir un bon fonctionnement de Maven.

Il permet notamment de dépendre de projets qui sont dans le référentiel, et donc on n’a pas besoin de les importer sous Eclipse comme c’est le cas dans les outils existant. Le classpath est généré par Maven.

Par contre son utilisation comporte quelques lacunes.

Si on lance la commande qui génère le classpath ‘mvn eclipse:eclipse’ à partir d’un POM parent, alors l’ensemble des modules doivent être présents dans l’espace de travail. La dépendance est faite à l’intérieur de cet espace, et pour avoir une dépendance à partir du référentiel, il faut lancer la commande pour chaque module !!

Un autre problème (actuellement sans solution), porte sur l’héritage quand on ne respecte pas la hiérarchie dans les répertoires.

Remarques
  • Dans le POM, le chemin d’accès au POM du module est défini dans le tag module, et donc on peut utiliser des ../ pour aller à des répertoires qui sont au même niveau (une structure en plan).
  • Dans le cas d’une structure en plan, le plugin Eclipse ne reconnaît pas le POM parent, car par défaut il cherche dans les répertoires au-dessus (et à priori impossible de le changer).
  • Ce plugin permet à Eclipse de rajouter Maven comme un outil externe, au même titre que ANT.

[modifier] Intégration continue

-- à compléter --

[modifier] Lien externe

b:Accueil

Wikibooks propose un ouvrage abordant ce sujet : Apache Maven.