Apache Maven
1. Introduction à Maven
1.1. Présentation
Couramment appelé Maven, Apache Maven est un outil de gestion et d’automatisation de production des projets logiciels Java en général et Java EE en particulier. Maven est géré par l’organisation Apache Software Foundation. L’outil était précédemment une branche de l’organisation Jakarta Project.
L’objectif recherché est de produire un logiciel à partir de ses sources, en optimisant les tâches réalisées à cette fin et en garantissant le bon ordre de fabrication.
On peut le comparer au système make sous Unix ou à l’outil Ant.
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 tâches pré-définies, comme la compilation de code Java ou encore sa modularisation.
Un élément clé et relativement spécifique de Maven est sa capacité à 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 à partir des dépôts logiciels connus. Il propose ainsi la synchronisation transparente de modules nécessaires.
1.2. Project Object Model (POM)
Chaque projet ou sous-projet est configuré par un POM qui contient les informations nécessaires à Maven pour traiter le projet (nom du projet, numéro de version, dépendances vers d’autres projets, bibliothèques nécessaires à la compilation, noms des contributeurs, etc.). Ce POM se matérialise par un fichier pom.xml
à la racine du projet. Cette approche permet l’héritage des propriétés du projet parent. Si une propriété est redéfinie dans le POM du projet, elle recouvre celle qui est définie dans le projet parent. Ceci introduit le concept de réutilisation de configuration. Le fichier pom
du projet principal est nommé pom
parent. Il contient une description détaillée de votre projet, avec en particulier des informations concernant le versionnage et la gestion des configurations, les dépendances, les ressources de l’application, les tests, les membres de l’équipe, la structure et bien plus.
1.3. Convention plutôt que configuration
Maven impose une arborescence et un nommage des fichiers du projet selon le concept de Convention plutôt que configuration. Ces conventions permettent de réduire la configuration des projets, tant qu’un projet suit les conventions. Si un projet a besoin de s’écarter de la convention, le développeur le précise dans la configuration du projet.
Voici une liste non-exhaustive des répertoires d’un projet Maven :
/src
: les sources du projet/src/main
: code source et fichiers source principaux/src/main/java
: code source/src/main/resources
: fichiers de ressources (images, fichiers annexes, etc.)/src/main/webapp
: webapp du projet/src/test
: fichiers de test/src/test/java
: code source de test/src/test/resources
: fichiers de ressources de test/src/site
: informations sur le projet et/ou les rapports générés suite aux traitements effectués/target
: fichiers résultat, les binaires (du code et des tests), les packages générés et les résultats des tests
Voir : Introduction to the Standard Directory Layout
1.4. Cycle de vie d’un projet Maven
Les buts (goals en anglais) principaux du cycle de vie d’un projet Maven sont:
- compile
- test
- package
- install
- deploy
L’idée est que, pour n’importe quel but, tous les buts en amont doivent être exécutés sauf s’ils ont déjà été exécutés avec succès et qu’aucun changement n’a été fait dans le projet depuis. Par exemple, quand on exécute mvn install, Maven va vérifier que mvn package s’est terminé avec succès (le jar existe dans target/
), auquel cas cela ne sera pas ré-exécuté.
D’autres buts sont exécutables en dehors du cycle de vie et ne font pas partie du cycle de vie par défaut de Maven (ils ne sont pas indispensables). Voici les principaux :
- clean
- assembly:assembly
- site
- site-deploy
- etc.
Ils peuvent néanmoins être rajoutés au cycle de vie via le POM.
1.5. Gestion des dépendances
Dans l’outil Maven, la gestion des dépendances s’appuie sur deux notions :
- l’héritage
- les relations transitive (ou transitivité)
La notion de relation transitive est implémentée pour la relation “dépend de” et l’ensemble projet Java.
Exemple : Soit trois projets (A, B, C), si A dépend de B et B dépend de C Alors A dépendra de C
Par défaut dans Maven, la transitivité est configurée en automatique. Cette configuration peut générer des contraintes avec les projets volumineux :
- l’inclusion de jars dans les EAR
- l’inclusion de versions non-désirées
- la présence de dépendances pour différentes versions à différents niveaux de la transitivité (un projet A dépend d’un projet C.x et d’un projet B, et ce dernier dépend du projet C.y)
- une perte d’informations (des dépendances effectives, par exemple) et la présence de dépendances inutiles à d’autres projets.
Dans l’attente d’une amélioration du plugin, cette option est désactivable en configurant l’option provided.
1.6. 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.
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”.
1.7. Rapports
Les rapports générés par Maven portent notamment 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 normes de codage
1.8. Plugins
Les plugins permettent l’ajout de fonctionnalités. Ces plugins sont disponibles sur le site de Maven, ou, à défaut, peuvent être développés. Pour utiliser un plugin, il suffit de le déclarer dans le POM.
Il est à noter 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).
Source : Apache Maven
1.9. Télécharger Apache Maven 3.6.0
Downloading Apache Maven 3.6.0
https://www-us.apache.org/dist/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
Maven 3.3+ require JDK 1.7 or above to execute
1.10. Installer Apache Maven
yum -y install maven
2. Démonstration Maven
Création, construction, test et empaquetage d’un webapp “MaWebApp”
2.1. Création d’un projet webapp avec Archetype
Création d’un dossier de travail
mkdir maven-works
cd maven-works
Génération du projet.
mvn archetype:generate \
-DgroupId=com.sample.webproject \
-DartifactId=MaWebApp \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false
Résultat :
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-webapp:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: /root/maven-works
[INFO] Parameter: package, Value: com.sample.webproject
[INFO] Parameter: groupId, Value: com.sample.webproject
[INFO] Parameter: artifactId, Value: MaWebApp
[INFO] Parameter: packageName, Value: com.sample.webproject
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: /root/maven-works/MaWebApp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.057s
[INFO] Finished at: Thu Apr 04 18:41:22 UTC 2019
[INFO] Final Memory: 14M/54M
[INFO] ------------------------------------------------------------------------
2.2. Dossier de configuration de Maven
ls ~/.m2/
ls ~/.m2/repository
2.3. Structure de l’application créée
cd MaWebApp/
tree ./
./
├── pom.xml
└── src
└── main
├── resources
└── webapp
├── index.jsp
└── WEB-INF
└── web.xml
5 directories, 3 files
2.4. Fichier pom.xml
cat pom.xml
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.webproject</groupId>
<artifactId>MaWebApp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>MaWebApp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>MaWebApp</finalName>
</build>
</project>
2.5. Page index.jsp
cat src/main/webapp/index.jsp
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
2.6. Fichier WEB-INF/web.xml
cat src/main/webapp/WEB-INF/web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
2.7. Build et Test
mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MaWebApp Maven Webapp 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ MaWebApp ---
[INFO]
[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ MaWebApp ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ MaWebApp ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ MaWebApp ---
[debug] execute contextualize
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /root/maven-works/MaWebApp/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ MaWebApp ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ MaWebApp ---
[INFO] No tests to run.
[INFO] Surefire report directory: /root/maven-works/MaWebApp/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ MaWebApp ---
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file:/root/.m2/repository/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar) to field java.util.Properties.defaults
WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
[INFO] Packaging webapp
[INFO] Assembling webapp [MaWebApp] in [/root/maven-works/MaWebApp/target/MaWebApp]
[INFO] Processing war project
[INFO] Copying webapp resources [/root/maven-works/MaWebApp/src/main/webapp]
[INFO] Webapp assembled in [36 msecs]
[INFO] Building war: /root/maven-works/MaWebApp/target/MaWebApp.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.788s
[INFO] Finished at: Thu Apr 04 18:47:45 UTC 2019
[INFO] Final Memory: 8M/37M
[INFO] ------------------------------------------------------------------------
2.8. Archive produite
Un dossier target/
a été ajouté au projet et contient le fichier MaWebApp.war
à déployer sur un serveur de servlet.
tree ./
./
├── pom.xml
├── src
│ └── main
│ ├── resources
│ └── webapp
│ ├── index.jsp
│ └── WEB-INF
│ └── web.xml
└── target
├── classes
├── maven-archiver
│ └── pom.properties
├── MaWebApp
│ ├── index.jsp
│ ├── META-INF
│ └── WEB-INF
│ ├── classes
│ └── web.xml
├── MaWebApp.war
└── surefire
3. Configurer Maven
4. Maven en 5 Minutes
5. Archetypes Maven
En bref, Archetype est une boîte à outils de modèles de projet Maven. Un archétype est défini comme un motif ou un modèle original à partir duquel toutes les autres choses du même genre sont faites. Le nom s’accorde bien avec le fait que nous essayons de fournir un système qui offre un moyen cohérent pour générer des projets Maven. Archetype aidera les auteurs à créer des modèles de projet Maven pour les utilisateurs et fournira aux utilisateurs les moyens de générer des versions paramétrées de ces modèles de projet.
L’utilisation d’archétypes est un excellent moyen de permettre aux développeurs d’agir rapidement d’une manière conforme aux meilleures pratiques employées par votre projet ou votre organisation. Dans le cadre du projet Maven, nous utilisons des archétypes pour essayer de rendre nos utilisateurs opérationnels le plus rapidement possible en fournissant un exemple de projet qui démontre plusieurs des fonctionnalités de Maven, tout en présentant aux nouveaux utilisateurs les meilleures pratiques employées par Maven. En quelques secondes, un nouvel utilisateur peut disposer d’un projet Maven fonctionnel qui lui servira de tremplin pour explorer d’autres fonctionnalités de Maven. Nous avons également essayé de rendre le mécanisme de l’archétype additif, c’est-à-dire de permettre à des parties d’un projet d’être capturées dans un archétype afin que des parties ou des aspects d’un projet puissent être ajoutés aux projets existants. L’archétype du site de Maven en est un bon exemple. Si, par exemple, vous avez utilisé l’archétype de démarrage rapide pour générer un projet fonctionnel, vous pouvez alors créer rapidement un site pour ce projet en utilisant l’archétype de site dans ce projet existant.
Les archétypes peuvent servirnormaliser le développement de J2EE au sein de l’organisation, en fournissant des archétypes pour les EJB, ou WAR, ou pour les services Web. Une fois ces archétypes créés et déployés dans le référentiel de votre organisation, ils peuvent être utilisés par tous les développeurs de votre organisation.
6. Guide de démarrage Maven
7. Guide pour créer des assemblages
8. Liens
https://maven.apache.org/what-is-maven.html
https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
https://maven.apache.org/guides/getting-started/index.html
https://www.tutorialspoint.com/maven/index.htm
https://www.baeldung.com/maven
https://www.mkyong.com/maven/how-to-create-a-web-application-project-with-maven/
https://dzone.com/articles/how-to-create-a-web-project-using-maven-in-eclipse-1
https://www.studytonight.com/maven/maven-web-application
https://crunchify.com/how-to-create-dynamic-web-project-using-maven-in-eclipse/
https://spilth.gitbooks.io/pragmatic-guide-to-maven-3/content/index.html et https://github.com/spilth/maven-book/blob/master/src/pragmatic-guide-to-maven.md
How to deploy Maven projects to Artifactory with GitLab CI/CD
https://javapointers.com/tutorial/create-web-application-using-maven-and-netbeans/
https://javapointers.com/tutorial/add-tomcat-server-netbeans/