Développer en Java/Introduction à Apache Maven

Qu'est-ce que Maven et pourquoi faut-il l'utiliser ?

modifier

 

Wikipédia propose un article sur : « Apache Maven ».

Maven permet de faciliter et d'automatiser certaines tâches de la gestion d'un projet Java. Il permet notamment :

  • d'automatiser certaines tâches : compilation, tests unitaires et déploiement des applications qui composent le projet ;
  • de gérer des dépendances vis à vis des bibliothèques nécessaires au projet ;
  • de générer des documentations concernant le projet.

Pour gérer les dépendances du projet vis à vis de bibliothèques, Maven utilise un ou plusieurs dépôts (appelés repositories) qui peuvent être locaux (.maven/repository) ou distants (http://www.ibiblio.org/maven par défaut)

Maven est extensible grâce à un mécanisme d'extension qui permet d'ajouter des fonctionnalités.

Maven comparé à Ant

modifier

Au premier abord, il est facile de croire que Maven fait double emploi avec Ant. Ant et Maven sont tous les deux développés par le groupe Jakarta, ce qui prouve bien que leur utilité n'est pas aussi identique. Ant dont le but est d'automatiser certaines tâches répétitives est plus ancien que Maven. Maven propose non seulement ces fonctionnalités mais en propose de nombreuses autres.

Mettre en place Maven

modifier

Installez Maven sur votre machine

modifier

Ici, la procédure diffère selon le système d'exploitation que vous utilisez. L'installation sous Linux est extrêmement simple, l'installation sous Windows l'est moins.

Installation sous Windows

modifier

Il faut télécharger la version la plus récente de Maven sur le site officiel et la dézipper.

Avec assistant
modifier

Un assistant permet de fournir les informations concernant l'installation :

  • sur la page « Licence Agreement » : lire la licence et si vous l'acceptez cliquer sur le bouton « I Agree ».
  • sur la page « Installations Options » : sélectionner les éléments à installer et cliquer sur le bouton « Next ».
  • sur la page « Installation Folder » : sélectionner le répertoire dans lequel Maven va être installé et cliquer sur le bouton « Install ». Par défaut, sous Windows :
C:\Program Files\Apache Software Foundation\maven-2.0.3
  • une fois les fichiers copiés, il suffit de cliquer sur le bouton « Close ».

Un élément de menu nommé « Apache Software Foundation / Maven --version » est ajouté dans le menu « Démarrer / Programmes ».

Pour utiliser Maven, la variable d'environnement système nommée MAVEN_HOME doit être définie avec comme valeur le chemin absolu du répertoire dans lequel Maven est installé. Par défaut, cette variable est configurée automatiquement lors de l'installation sous Windows.

C:\Program Files\Apache Software Foundation\maven-2.0.3\bin";%PATH%

Il est aussi particulièrement pratique d'ajouter le répertoire %MAVEN_HOME%/bin à la variable d'environnement PATH. Maven étant un outil en ligne de commande, cela évite d'avoir à saisir son chemin complet lors de son exécution.

Il faut s'assurer également que le JDK est installé. Le répertoire par défaut sous Windows est C:\Program Files\Java\jdkn° de version (Exemple: C:\Program Files\Java\jdk1.5.0_14).

Enfin, il faut créer un repository local en utilisant la commande ci dessous dans une boîte de commandes DOS :

C:\>install_repo.bat %HOMEDRIVE%%HOMEPATH%
Sans assistant
modifier

Il suffit de placer les fichiers dans un répertoire qui sera spécifié dans la variable d'environnement M2_HOME.

Ensuite, définir les variables d'environnement correspondantes, par exemple :

  • JAVA_HOME = C:\Program Files\Java\jdk1.7.0_03\
  • M2_HOME = C:\Program Files\Java\apache-maven-3.0.4\
  • path = C:\Program Files\Java\apache-maven-3.0.4\bin

Installation sous GNU/Linux

modifier
  Paquet logiciel

Rien n'est plus simple : utilisez votre gestionnaire de paquets.


Installation sous Mac OS X

modifier

avec le gestionnaire de paquets Homebrew

$ brew install maven

ou macPorts

$ sudo port install maven3

Testez votre installation

modifier
$ mvn --version

Configurez Maven

modifier

Dans votre répertoire personnel, vous trouverez un dossier « .m2 » contenant un fichier « settings.xml » qui va vous permettre de configurer Maven.

Si vous êtes derrière un proxy réseau

modifier

Maven utilise abondamment HTTP.

Utilisez une source de bibliothèques proche de chez vous

modifier

Créez un premier projet

modifier

Maven se base sur les conventions pour trouver tous les composants de vos projets, suivez-les et Maven se débrouillera sans aucune configuration.

Arborescence d'un projet Maven

modifier

Voici l'arborescence minimum d'un projet Maven.

mon_projet
un dossier qui va contenir toutes les données du projet
mon_projet/src
ce dossier va contenir tous les fichiers sources créés par les développeurs pour le projet
mon_projet/src/main
mon_projet/src/main/java
contient les codes sources Java, rangés selon le hiérarchie des packages. (par exemple, mon_projet/src/main/java/org/wikibooks/fr/Exemple.java pour la classe org.wikibooks.fr.Exemple)
mon_projet/src/main/resources
les ressources nécessaires au code Java. Fichiers de configuration, icônes, fichiers de données...
mon_projet/src/test
contient toutes les données nécessaire pour tester l'application
mon_projet/src/test/java
contient les codes sources des tests
mon_projet/src/test/resources
les ressources qui sont utilisées dans les tests
mon_projet/pom.xml
un fichier XML qui décrit le projet pour permettre à Maven d'interagir avec lui.

Le « Project Object Model » : fichier pom.xml

modifier

Tous les projets Maven sont identifiés de façon unique. Pour cela, un projet est identifié par 3 valeurs :

Un groupId
Il désigne l'organisation responsable de ce projet. Il arrive souvent qu'on suive les conventions sur les noms de package pour définir le groupId. Votre groupId doit être propre à votre organisation et être composé d'un nom de domaine dont vous avez le contrôle pour être sûr qu'aucun autre projet qui n'est pas de vous ne porte le même groupId. Bon exemple, si vous travaillez dans une entreprise, utilisez le nom de domaine de votre entreprise (com.maboite), si vous êtes étudiants, utilisez le domaine de votre formation (fr.monuniversite.moncours), si c'est un logiciel libre, utilisez l'adresse du site du projet ou de la forge, etc.
Un artifactId
Il identifie le projet lui même : pour faire simple, c'est le nom que portera le fichier .jar qui sera généré par la construction du projet. Il faut donc veiller à ce que son nom soit sans ambigüité. Bons exemples : junit, commons-io, http-client ; mauvais exemples : test, core, module.
Une version
Pour finir d'identifier une application ou une bibliothèque, on ajoute une troisième composante, la version.

Commençons par un pom minimal :

<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/maven-v4_0_0.xsd">
  <!-- Toujours utiliser 4.0.0 pour maven 2.x -->
  <modelVersion>4.0.0</modelVersion>

  <!-- groupId, artifactId et version actuelle -->
  <groupId>org.wikibooks.fr</groupId>
  <artifactId>projet-minimal</artifactId>
  <version>1.0</version>

  <!-- la façon dont sera packagée l'application -->
  <packaging>jar</packaging>

  <!-- un nom pour le projet -->
  <name>Un projet d'exemple pour le livre Développer en Java de Wikibooks</name>

  <!-- l'adresse du site qui présente cette application -->
  <url>http://fr.wikibooks.org/wiki/Développer_en_Java/Introduction_à_Apache_Maven</url>
</project>

Gérez les dépendances de votre projet

modifier

Maven gère toutes les dépendances de vos projets. Pour cela, il stocke toutes les bibliothèques de vos projets dans un dépôt local situé "~/.m2/repository". À chaque fois que vous demanderez à Maven de construire le projet, Maven ira chercher toutes les dépendances dans votre dépôt local. Si Maven ne trouve pas la dépendance dans votre dépôt local, il ira automatiquement la télécharger depuis un dépôt sur Internet et l'ajoutera à votre dépôt local. Au début, votre dépôt est vide, donc Maven téléchargera beaucoup de choses lors des premières utilisations.

Votre dépôt local est bien rangé, Maven organise tout et range toutes les bibliothèques selon le groupId, l'artifactId et les versions. À tout moment, vous pouvez supprimer l'intégralité de votre dépôt local pour faire le ménage. Maven ne re-téléchargera que le nécessaire.

 

Sur le docker, il faut partager le repo local du conteneur avec la machine hôte, sous peine de tout télécharger à chaque compilation[1].

Cela se fait en créant un volume et en le montant à chaque run :

docker volume create --name maven-repo
docker run -it -v maven-repo:/root/.m2 maven mvn archetype:generate

Comment trouver des bibliothèques ?

modifier

Lorsque Maven cherche une dépendance sur Internet, il s'oriente vers un dépôt principal où se trouvent l'essentiel des bibliothèques Java disponibles et qui s'appelle « central ». Et l'application en ligne Nexus permet de parcourir son contenu et de faire des recherches par groupId, artifactId et version[2]. Une fois que vous avez trouvé la bibliothèque qui remplit vos besoin, l'application peut vous donner le petit code XML à ajouter au POM du projet.

Déclarer une dépendance

modifier

Si votre application a besoin d'une dépendance, c'est simple, il suffit d'ajouter au POM la dépendance : son groupId, artifactId et version. Par exemple, pour que les développeurs bénéficient de l'API commons lang, il suffit d'ajouter dans le POM :

  <!-- ... -->

  <dependencies>

    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.5</version>
    </dependency>

  </dependencies>

Pour compiler ou lancer le projet, Maven ira chercher la dépendance dans le dépôt local, ou sur Internet si besoin.

Les différents « scope »

modifier

Une dépendance a une portée (scope), c'est à dire qu'elle est utilisée pour certaines tâches. Il existe les portées (scopes) suivantes :

compile
c'est le scope par défaut. La dépendance est utilisée pour compiler le code et est nécessaire à son exécution. Lorsque l'application sera construite par Maven, cette dépendance sera ajoutée dans le fichier jar généré.
test
cette dépendance est nécessaire seulement pour la compilation et l'exécution des tests. Quand Maven construira l'application, il n'ajoutera pas cette dépendance au jar généré étant donné que cette bibliothèque n'est pas utilisée dans l'application principale mais seulement dans les tests (remarque : les tests bénéficient, eux, des dépendances compile).
runtime
la dépendance n'est pas disponible à la compilation mais est fournie au lancement de l'application. Par exemple, un pilote de base de données (JDBC).
provided
la dépendance ne sera pas jointe à l'application mais sera fournie quand elle sera déployée. Par exemple, une application peut dépendre d'un élément qui ne lui sera fourni que lorsqu'elle sera déployée dans le serveur d'application. Comme il y a plusieurs serveurs d'application différents, on confie à ce dernier le soin de fournir la dépendance.

Par la suite, nous aurons l'usage des ces différents scopes.

Un POM d'exemple complet

modifier
<?xml version="1.0" encoding="UTF-8"?>
<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, artifactId et version actuelle -->
  <groupId>org.wikibooks.fr</groupId>
  <artifactId>projet-minimal</artifactId>
  <version>1.0</version>

  <!-- la façon dont sera packagée l'application -->
  <packaging>jar</packaging>

  <!-- un nom pour le projet -->
  <name>Un projet d'exemple pour le livre Développer en Java de Wikibooks</name>

  <!-- l'adresse du site qui présente cette application -->
  <url>http://fr.wikibooks.org/wiki/Développer_en_Java/Introduction_à_Apache_Maven</url>

  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>1.4</version>
    </dependency>

    <!-- test -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <properties>
  </properties>

  <build>
  </build>

</project>

Profitez des fonctionnalités de Maven

modifier

Tout est en place, le projet est prêt. On peut maintenant passer à l'action et profiter des nombreuses possibilités offertes par Maven.

Construire le projet

modifier

La construction d'un projet se passe en différentes phases successives qui décrivent le cycle de vie (Build Lifecycle) :

validate
vérifie que le POM est correct et complet
compile
compile les sources du projet qui se trouvent dans src/main/java et place les fichiers compilés (.class) dans target
test
compile les tests qui se trouvent dans src/test/java et lance l'intégralité des tests, les tests compilés sont placés dans target
package
génère un package de l'application dans target/artifactId-version.jar
install
utilise le package généré à la phase package et l'ajoute au dépôt local. À utiliser pour une bibliothèque : elle peut dès lors être utilisée comme dépendance pour un autre projet.
deploy
déploie l'application (varie selon la configuration)

Une autre phase est :

clean
détruit le répertoire target

Voici quelques exemples d'utilisation :

# on peut lancer une phase avec mvn phase, par exemple
mvn compile # exécute la phase validate puis la phase compile
mvn package # fait appel à toutes les phases précédentes

# on peut donner plusieurs phases en paramètres, par exemple
mvn clean test # exécute la phase clean puis la phase test

# Enfin, quel que soit la phase, on peut demander à Maven de sauter les tests, pour gagner du temps
mvn install -Dmaven.test.skip # saute la compilation et l'exécution des tests
# ou 
mvn install -DskipTests # compile les tests mais saute l'exécution

Il y a d'autres phases intermédiaires mais nous avons choisi de ne vous présenter que celles qui sont utilisées 80% du temps.

Exploiter les nombreuses possibilités offertes par les extensions Maven

modifier

L'outil mvn peut faire appel à des extensions. Chaque extension est proposée avec un ensemble d'actions possibles appelées goal. On utilise alors mvn extension:goal.

Pour la plupart des extensions, il existe un goal help. Par exemple, mvn javadoc:help devrait donner l'aide pour l'extension javadoc et tous les goals que propose cette extension.

Générer un site internet pour le projet

modifier
mvn site:site

Générer la javadoc

modifier

La documentation sera générée dans target/site/apidocs.

mvn javadoc:javadoc

Packager l'application

modifier

Générer un jar avec toutes les dépendances incluses. Utile pour proposer une version complète stand-alone de l'application.

mvn assembly:assembly -DdescriptorId=jar-with-dependencies

Générer un jar avec seulement les sources, idéal pour distribuer le code à des développeurs pour qu'ils l'intègrent à leur IDE.

mvn assembly:assembly -DdescriptorId=src

Exécuter une classe java

modifier

Si vous voulez exécutez le programme, vous pouvez faire

mvn package
cd target
java -jar mon-artifact.jar

Cela ne fonctionnera pas étant donné qu'il faut ajouter au CLASSPATH tout un tas de fichier jar qui se trouvent dans votre dépôt local. La plug-in exec vous permet d'exécuter un programme principal.

mvn exec:java -Dexec.mainClass=org.wikibooks.fr.ClassePrincipale -Dexec.args="argument1 argument2"
# attention : -Dexec.args="" passe l'argument "" (chaîne vide) à l'application

On peut aussi ajouter les informations sur le nom de la classe principale, les arguments et les réglages systèmes dans le POM.

Surveiller les mises à jours des dépendances

modifier

À tout moment, vous pouvez vérifier la disponibilité de nouvelles versions de vos dépendances avec

mvn versions:display-dependency-updates
[INFO] [versions:display-dependency-updates {execution: default-cli}]
[INFO] The following dependencies in Dependency Management are using the newest version:
[INFO]   commons-daemon:commons-daemon .................................. 1.0.1
[INFO]   commons-io:commons-io ............................................ 1.4
[INFO]   commons-lang:commons-lang ........................................ 2.5
[INFO]   commons-logging:commons-logging ................................ 1.1.1
[INFO]   junit:junit .................................................... 4.8.1
[INFO]   log4j:log4j ................................................... 1.2.16
[INFO] 
[INFO] The following dependencies in Dependency Management have newer versions:
[INFO]   org.mortbay.jetty:jetty .............................. 6.1.9 -> 6.1.25
[INFO]   org.quartz-scheduler:quartz ........................... 1.8.3 -> 1.8.4

Ce plug-in versions permet également de mettre à jour automatiquement les numéros de versions dans un projet.

Pour aller plus loin

modifier

Découvrir de nouvelles extensions

modifier

Utiliser les profils

modifier

Se documenter

modifier




Références

modifier