Tutoriel Apache Maven

1. Introduction

La création d'un projet logiciel comprend généralement des tâches telles que le téléchargement de dépendances, la mise en place de fichiers JAR supplémentaires sur un chemin de classe, la compilation du code source en code binaire, l'exécution de tests, l'empaquetage du code compilé dans des artefacts déployables tels que des fichiers JAR, WAR et ZIP, et le déploiement de ces artefacts vers un serveur d'applications ou un référentiel.

Apache Maven automatise ces tâches, minimisant le risque que les humains commettent des erreurs lors de la construction manuelle du logiciel et séparant le travail de compilation et d'empaquetage de notre code de celui de construction de code.

Dans ce didacticiel, nous allons explorer cet outil puissant pour décrire, créer et gérer des projets logiciels Java à l'aide d'une information centrale - le modèle d'objet de projet (POM) - qui est écrite en XML.

2. Pourquoi utiliser Maven?

Les principales caractéristiques de Maven sont:

  • configuration de projet simple qui suit les meilleures pratiques: Maven essaie d'éviter autant de configuration que possible, en fournissant des modèles de projet (nommés archétypes )
  • gestion des dépendances: cela inclut la mise à jour automatique, le téléchargement et la validation de la compatibilité, ainsi que le rapport des fermetures de dépendances (également appelées dépendances transitives)
  • isolation entre les dépendances de projet et les plugins: avec Maven, les dépendances de projet sont récupérées à partir des référentiels de dépendances tandis que les dépendances de tout plugin sont extraites des référentiels de plugin, ce qui entraîne moins de conflits lorsque les plugins commencent à télécharger des dépendances supplémentaires
  • système de référentiel central: les dépendances de projet peuvent être chargées à partir du système de fichiers local ou de référentiels publics, tels que Maven Central
Afin d'apprendre comment installer Maven sur votre système, veuillez consulter ce tutoriel sur Baeldung.

3. Modèle d'objet de projet

La configuration d'un projet Maven se fait via un Project Object Model (POM) , représenté par un fichier pom.xml . Le POM décrit le projet, gère les dépendances et configure les plugins pour créer le logiciel.

Le POM définit également les relations entre les modules de projets multi-modules. Regardons la structure de base d'un fichier POM typique :

 4.0.0 org.baeldung org.baeldung jar 1.0-SNAPSHOT org.baeldung //maven.apache.org   junit junit 4.12 test      //...    

Examinons de plus près ces constructions.

3.1. Identificateurs de projet

Maven utilise un ensemble d'identificateurs, également appelés coordonnées, pour identifier de manière unique un projet et spécifier comment l'artefact du projet doit être empaqueté:

  • groupId - un nom de base unique de la société ou du groupe qui a créé le projet
  • artifactId - un nom unique du projet
  • version - une version du projet
  • emballage - une méthode d'emballage (par exemple WAR / JAR / ZIP )

Les trois premiers d'entre eux ( groupId: artifactId: version ) se combinent pour former l'identifiant unique et sont le mécanisme par lequel vous spécifiez les versions de bibliothèques externes (par exemple les JAR) que votre projet utilisera.

3.2. Dépendances

Ces bibliothèques externes utilisées par un projet sont appelées dépendances. La fonction de gestion des dépendances de Maven assure le téléchargement automatique de ces bibliothèques à partir d'un référentiel central, vous n'avez donc pas à les stocker localement.

Il s'agit d'une fonctionnalité clé de Maven et offre les avantages suivants:

  • utilise moins de stockage en réduisant considérablement le nombre de téléchargements depuis les référentiels distants
  • rend l'extraction d'un projet plus rapide
  • fournit une plate-forme efficace pour échanger des artefacts binaires au sein de votre organisation et au-delà sans avoir besoin de créer des artefacts à partir de la source à chaque fois

Pour déclarer une dépendance sur une bibliothèque externe, vous devez fournir le groupId, artifactId et la version de la bibliothèque. Jetons un œil à un exemple:

 org.springframework spring-core 4.3.5.RELEASE 

Au fur et à mesure que Maven traite les dépendances, il téléchargera la bibliothèque Spring Core dans votre référentiel Maven local.

3.3. Référentiels

Un référentiel dans Maven est utilisé pour contenir des artefacts de construction et des dépendances de différents types. Le référentiel local par défaut se trouve dans le dossier .m2 / repository sous le répertoire de base de l'utilisateur.

Si un artefact ou un plug-in est disponible dans le référentiel local, Maven l'utilise. Sinon, il est téléchargé à partir d'un référentiel central et stocké dans le référentiel local. Le référentiel central par défaut est Maven Central.

Certaines bibliothèques, telles que le serveur JBoss, ne sont pas disponibles dans le référentiel central mais sont disponibles dans un référentiel alternatif. Pour ces bibliothèques, vous devez fournir l'URL du référentiel alternatif dans le fichier pom.xml :

  JBoss repository //repository.jboss.org/nexus/content/groups/public/  

Veuillez noter que vous pouvez utiliser plusieurs référentiels dans vos projets.

3.4. Propriétés

Les propriétés personnalisées peuvent faciliter la lecture et la maintenance de votre fichier pom.xml . Dans le cas d'utilisation classique, vous utiliseriez des propriétés personnalisées pour définir des versions pour les dépendances de votre projet.

Les propriétés Maven sont des espaces réservés de valeur et sont accessibles n'importe où dans un pom.xml en utilisant la notation $ {name} , où name est la propriété.

Voyons un exemple:

 4.3.5.RELEASE    org.springframework spring-core ${spring.version}   org.springframework spring-context ${spring.version}  

Désormais, si vous souhaitez mettre à niveau Spring vers une version plus récente, il vous suffit de modifier la valeur à l'intérieur dupropriété et toutes les dépendances utilisant cette propriété dans leur les balises seront mises à jour.

Les propriétés sont également souvent utilisées pour définir les variables de chemin de construction:

 ${project.build.directory}/tmp/   //... ${project.resources.build.folder} //... 

3.5. Construire

The build section is also a very important section of the Maven POM. It provides information about the default Maven goal, the directory for the compiled project, and the final name of the application. The default build section looks like this:

 install ${basedir}/target ${artifactId}-${version}  filters/filter1.properties  //... 

The default output folder for compiled artifacts is named target, and the final name of the packaged artifact consists of the artifactId and version, but you can change it at any time.

3.6. Using Profiles

Another important feature of Maven is its support for profiles. A profile is basically a set of configuration values. By using profiles, you can customize the build for different environments such as Production/Test/Development:

  production    //...      development  true     //...     

As you can see in the example above, the default profile is set to development. If you want to run the production profile, you can use the following Maven command:

mvn clean install -Pproduction

4. Maven Build Lifecycles

Every Maven build follows a specified lifecycle. You can execute several build lifecyclegoals, including the ones to compile the project’s code, create a package, and install the archive file in the local Maven dependency repository.

4.1. Lifecycle Phases

The following list shows the most important Maven lifecycle phases:

  • validate – checks the correctness of the project
  • compile – compiles the provided source code into binary artifacts
  • test – executes unit tests
  • package – packages compiled code into an archive file
  • integration-test – executes additional tests, which require the packaging
  • verify – checks if the package is valid
  • install – installs the package file into the local Maven repository
  • deploy – deploys the package file to a remote server or repository

4.2. Plugins and Goals

A Maven plugin is a collection of one or more goals. Goals are executed in phases, which helps to determine the order in which the goals are executed.

The rich list of plugins that are officially supported by Maven is available here. There is also an interesting article how to build an executable JAR on Baeldung using various plugins.

To gain a better understanding of which goals are run in which phases by default, take a look at the default Maven lifecycle bindings.

To go through any one of the above phases, we just have to call one command:

mvn 

For example, mvn clean install will remove the previously created jar/war/zip files and compiled classes (clean) and execute all the phases necessary to install new archive (install).

Please note that goals provided by plugins can be associated with different phases of the lifecycle.

5. Your First Maven Project

In this section, we will use the command line functionality of Maven to create a Java project.

5.1. Generating a Simple Java Project

In order to build a simple Java project, let's run the following command:

mvn archetype:generate -DgroupId=org.baeldung -DartifactId=org.baeldung.java -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

The groupId is a parameter indicating the group or individual that created a project, which is often a reversed company domain name. The artifactId is the base package name used in the project, and we use the standard archetype.

Since we didn't specify the version and the packaging type, these will be set to default values — the version will be set to 1.0-SNAPSHOT, and the packaging will be set to jar.

If you don't know which parameters to provide, you can always specify interactiveMode=true, so that Maven asks for all the required parameters.

After the command completes, we have a Java project containing an App.java class, which is just a simple “Hello World” program, in the src/main/java folder.

We also have an example test class in src/test/java. The pom.xml of this project will look similar to this:

 4.0.0 org.baeldung org.baeldung.java jar 1.0-SNAPSHOT org.baeldung.java //maven.apache.org   junit junit 4.1.2 test   

As you can see, the junit dependency is provided by default.

5.2. Compiling and Packaging a Project

The next step is to compile the project:

mvn compile

Maven will run through all lifecycle phases needed by the compile phase to build the project's sources. If you want to run only the test phase, you can use:

mvn test

Now let's invoke the package phase, which will produce the compiled archive jar file:

mvn package

5.3. Executing an Application

Finally, we are going to execute our Java project with the exec-maven-plugin. Let's configure the necessary plugins in the pom.xml:

 src   maven-compiler-plugin 3.6.1  1.8 1.8    org.codehaus.mojo exec-maven-plugin 1.5.0  org.baeldung.java.App    

The first plugin, maven-compiler-plugin, is responsible for compiling the source code using Java version 1.8. The exec-maven-plugin searches for the mainClass in our project.

To execute the application, we run the following command:

mvn exec:java

6. Multi-Module Projects

The mechanism in Maven that handles multi-module projects (also called aggregator projects) is called Reactor.

The Reactor collects all available modules to build, then sorts projects into the correct build order, and finally, builds them one by one.

Let's see how to create a multi-module parent project.

6.1. Create Parent Project

First of all, we need to create a parent project. In order to create a new project with the name parent-project, we use the following command:

mvn archetype:generate -DgroupId=org.baeldung -DartifactId=parent-project

Next, we update the packaging type inside the pom.xml file to indicate that this is a parent module:

pom

6.2. Create Submodule Projects

In the next step, we create submodule projects from the directory of parent-project:

cd parent-project mvn archetype:generate -DgroupId=org.baeldung -DartifactId=core mvn archetype:generate -DgroupId=org.baeldung -DartifactId=service mvn archetype:generate -DgroupId=org.baeldung -DartifactId=webapp

To verify if we created the submodules correctly, we look in the parent-project pom.xml file, where we should see three modules:

 core service webapp 

Moreover, a parent section will be added in each submodule’s pom.xml:

 org.baeldung parent-project 1.0-SNAPSHOT 

6.3. Enable Dependency Management in Parent Project

Dependency management is a mechanism for centralizing the dependency information for a muti-module parent project and its children.

When you have a set of projects or modules that inherit a common parent, you can put all the required information about the dependencies in the common pom.xml file. This will simplify the references to the artifacts in the child POMs.

Let's take a look at a sample parent's pom.xml:

   org.springframework spring-core 4.3.5.RELEASE  //...  

By declaring the spring-core version in the parent, all submodules that depend on spring-core can declare the dependency using only the groupId and artifactId, and the version will be inherited:

  org.springframework spring-core  //... 

Moreover, you can provide exclusions for dependency management in parent's pom.xml, so that specific libraries will not be inherited by child modules:

  org.springframework spring-context  

Finally, if a child module needs to use a different version of a managed dependency, you can override the managed version in child's pom.xml file:

 org.springframework spring-core 4.2.1.RELEASE 

Please note that while child modules inherit from their parent project, a parent project does not necessarily have any modules that it aggregates. On the other hand, a parent project may also aggregate projects that do not inherit from it.

For more information on inheritance and aggregation please refer to this documentation.

6.4. Updating the Submodules and Building a Project

We can change the packaging type of each submodule. For example, let's change the packaging of the webapp module to WAR by updating the pom.xml file:

war

Now we can test the build of our project by using the mvn clean install command. The output of the Maven logs should be similar to this:

[INFO] Scanning for projects... [INFO] Reactor build order: [INFO] parent-project [INFO] core [INFO] service [INFO] webapp //............. [INFO] ----------------------------------------- [INFO] Reactor Summary: [INFO] ----------------------------------------- [INFO] parent-project .................. SUCCESS [2.041s] [INFO] core ............................ SUCCESS [4.802s] [INFO] service ......................... SUCCESS [3.065s] [INFO] webapp .......................... SUCCESS [6.125s] [INFO] -----------------------------------------

7. Conclusion

Dans cet article, nous avons discuté de certaines des fonctionnalités les plus populaires de l'outil de compilation Apache Maven.

Tous les exemples de code sur Baeldung sont construits à l'aide de Maven, vous pouvez donc facilement consulter notre site Web de projet GitHub pour voir diverses configurations Maven.