> Note : Gradle permet de faire sensiblement la même chose.
> Par faute de temps, nous nous concentrerons sur Maven.
> Mais en bonus, par la suite, vous pouvez essayer de refaire le TP avec Gradle.
## Exo 1 : Créer un projet maven depuis zéro
### Installer maven
Si vous utilisez SdkMan!
```shell
sdk install maven
```
Si vous lancez un terminal depuis IntelliJ Idea, normalement une version de maven est chargée avec le terminal.
Vérifiez que maven est bien installé
```shell
mvn -version
```
Vous devriez obtenir une réponse similaire à ceci :
```text
Apache Maven 3.9.11 (3e54c93a704957b63ee3494413a2b544fd3d825b)
Maven home: /...
Java version: 25.0.1, vendor: Eclipse Adoptium, runtime: /___/.sdkman/candidates/java/25.0.1-tem
Default locale: fr_FR, platform encoding: UTF-8
OS name: "mac os x", version: "15.7.3", arch: "aarch64", family: "mac"
```
### Pom minimaliste
1 - A la racine de ce dépôt, créer un fichier `pom.xml`
Le `pom.xml` est le fichier qui décrit les dépendances d’un projet Maven.
C’est un peu le même principe que `composer.json` en PHP et le `package.json` de javascript.
Sauf que Maven est plus ancien, c’est en XML.
```xml
<?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>tp06.maven</groupId>
<artifactId>hello-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
```
Vérifier que le fichier est valide à l’aide de la commande `mvn install`.
```shell
mvn compile
```
Le résultat devrait être en succès.
```text
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.653 s
[INFO] Finished at: 2026-01-19T22:10:53+01:00
[INFO] ------------------------------------------------------------------------
```
Un dossier `target` est créé.
Il ne contient rien d'intéressant pour le moment.
> 🚨 Il est important d'exclure le dossier `target` de git car on ne veut versionner que les sources
`.gitignore`
```.gitignore
target
```
### Intégration avec IntelliJ Idea
Clic droit sur `pom.xml` > `Add as maven project`
Une fois le Projet maven associé au projet Idea, on dispose d'intégrations intéressantes.
Menu latéral Maven dans IntelliJ Idea

Pour en savoir plus rendez vous sur [la documentation des outils maven](https://www.jetbrains.com/help/idea/2025.3/maven-projects-tool-window.html?reference.toolWindows.mavenProjects&utm_source=product&utm_medium=link&utm_campaign=IU&utm_content=2025.3) dans IntelliJ.
Parmi les fonctionnalités les plus utiles:
Télécharger les sources et la documentation.

Executer des commandes maven : "Execute maven goals".

> 🚨 Quand vous modifiez le fichier pom.xml il faut penser à synchroniser les changements. Sinon ils ne seront pas pris en compte dans IntelliJ.

### Compilons du code !
Créer une classe `Main` a l'emplacement suivant.
`src/main/java/tp06/maven/Main.java`
```java
package tp06.maven;
public class Main {
static void main(String[] args) {
String target = "Maven";
if (args.length > 0) {
target = args[0];
}
System.out.println("Hello " + target + " !");
}
}
```
> 💡 Il est important de respecter la hiérarchie de dossier car maven s'appuie sur une convention par défaut pour les arborescences de fichiers.
> ```text
> ├── pom.xml
> └── src
> ├── main
> │ ├── java
> │ │ └── tp06
> │ │ └── maven
> │ │ └── Main.java
> │ └── resources
> └── test
> ├── java
> └── resources
> ```
Lancez la commande de compilation.
```shell
mvn compile
```
Retournons dans le dossier `target`.
On y trouve désormais les classes compilées.
```text
target
├── classes
│ └── tp06
│ └── maven
│ └── Main.class
└── ...
```
### Exécuter le code compilé
Pour ajouter des fonctionnalités à notre "build maven", on peut ajouter des plugins dans le POM.
Il en existe une multitude.
- Les plugins officiels peuvent se trouver à https://maven.apache.org/plugins/
```xml
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<mainClass>tp06.maven.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<!-- ... -->
</project>
```
Grâce à ce nouveau plugin, je peux indiquer à maven de lancer mon programme
```shell
mvn exec:java
```
### Plugins
Un certain nombre de plugins sont disponibles par défaut et sont préconfigurés avec des valeurs par défaut.
C'est le cas du plugin de compilation qu'on a utilisé précédemment.
> 💡 Quelques plugins courants
> - `clean` : supprime le code dans `target`
> - `compiler` : compilation du code et/ou des tests
> - `surefire` : execution de tests automatisés et de rapports
> - `exec` : exécution de code (ex. un programme Main)
> - `jar` : construit une archive jar pour le projet courant
> - `resources` : copie les ressources (fichiers additionnels externes au code mais inclus dans le classpath) dans le dossier de sortie
> - `site` : génère un site web avec des informations sur le projet
> - `install` : copie les artefacts du projet dans le dépôt local de l'utilisateur (en général dans `$HOME/.m2`)
> - `deploy` : déploiement d'un artefact sur un dépôt distant
Les plugins ont également des goals internes qu'on peut déclencher explicitement.
```shell
# Ex. lancer le goal help du plugin compiler
mvn compiler:help
```
Si on devait l'ajouter au POM, voici ce qu'on ajouterait.
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
```
Par défaut, pour les plugins officiels, la version est implicite.
On voit d'ailleurs la version du plugin dans le résultat console de l'exécution.
```shell
mvn compile
```
Par défaut dans mon cas, la version du plugin compiler est 3.13.0.
```text
👇
👇
[INFO] --- compiler:3.13.0:compile (default-compile) @ hello-maven ---
[INFO] Nothing to compile - all classes are up to date.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.234 s
[INFO] Finished at: 2026-01-19T22:32:18+01:00
[INFO] ------------------------------------------------------------------------
```
Si je veux utiliser une version précise (une version plus récente par exemple), je peux spécifier la version.
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.1</version>
</plugin>
```
```shell
mvn compile
```
> 💡 Il est parfois nécessaire d'utiliser une version récente du plugin compiler quand de nouvelles versions de Java sortent.
### Cycles de vie
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
### Profiles
Les profiles permettent de paramétrer différemment le projet.
Très pratique quand on veut lancer ou construire un projet pour un environnement différent.
```xml
<project>
<!-- ... -->
<profiles>
<profile>
<id>World</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>tp06.maven.Main</mainClass>
<arguments>World</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
```
Pour activer un profil en ligne de commande ajouter `-P` suivi de l'id du profile.
```shell
mvn -P World exec:java
```
```text
Hello World !
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.178 s
[INFO] Finished at: 2026-01-19T22:45:17+01:00
[INFO] ------------------------------------------------------------------------
```
## Exercice 2 : dépendances
Une fois qu'on a un Projet maven, on peut facilement ajouter des dépendances dans le pom.xml pour inclure du code extérieur dans notre projet.
- Directes : déclarées dans `<dependency>`
- Transitives : requises par les dépendances directes, elles sont également tirées
Pour afficher l'arbre des dépendances.
```shell
mvn dependency:tree
```
Exemple de rapport d'arbre de dépendances
```text
[INFO]
[INFO] ---------------< school.coda.template:template-java-mvn >---------------
[INFO] Building template-java-mvn 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:3.7.0:tree (default-cli) @ template-java-mvn ---
[INFO] school.coda.template:template-java-mvn:jar:1.0-SNAPSHOT
[INFO] +- org.xerial:sqlite-jdbc:jar:3.51.0.0:compile
[INFO] +- org.junit.jupiter:junit-jupiter:jar:5.11.4:test
[INFO] | +- org.junit.jupiter:junit-jupiter-api:jar:5.11.4:test
[INFO] | | +- org.opentest4j:opentest4j:jar:1.3.0:test
[INFO] | | +- org.junit.platform:junit-platform-commons:jar:1.11.4:test
[INFO] | | \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] | +- org.junit.jupiter:junit-jupiter-params:jar:5.11.4:test
[INFO] | \- org.junit.jupiter:junit-jupiter-engine:jar:5.11.4:test
[INFO] | \- org.junit.platform:junit-platform-engine:jar:1.11.4:test
[INFO] +- org.assertj:assertj-core:jar:3.26.3:compile
[INFO] | \- net.bytebuddy:byte-buddy:jar:1.14.18:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.397 s
[INFO] Finished at: 2026-01-19T23:39:11+01:00
[INFO] ------------------------------------------------------------------------
```
`school.coda:projet-a`
```xml
<project>
<groupId>school.coda</groupId>
<artifactId>projet-a</artifactId>
<version>1.0.9</version>
<dependencies>
<dependency>
<dependency>
<groupId>school.coda</groupId>
<artifactId>sqlite-helpers</artifactId>
<version>2.5</version>
</dependency>
</dependency>
</dependencies>
</project>
```
`school.coda:sqlite-helpers`
```xml
<project>
<groupId>school.coda</groupId>
<artifactId>sqlite-helpers</artifactId>
<version>2.5</version>
<dependencies>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.51.0.0</version>
</dependency>
</dependencies>
</project>
```
Dans cet exemple, `school.coda:projet-a` dépend de `school.coda:sqlite-helpers` qui lui-même dépend de
`org.xerial:sqlite-jdbc`.
`school.coda:projet-a` dépend transitivement (indirectement) de `org.xerial:sqlite-jdbc`.
### Dépendances de production
Ces dépendances seront utilisées dans le projet compilé livré.
**Exemples**
Driver JDBC pour la base de données SQLite
```xml
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.51.0.0</version>
</dependency>
```
> 💡 S'il n'est pas explicité : `<scope>compile</scope>`
Il existe différents scopes
- `compile` (défaut) : dépendance directe. transitive.
- `provided` : indique que les dépendances nécessaires doivent être fournies par le JDK ou un conteneur. Ces dépendances
**ne sont pas** transitives.
### Dépendances de test
Ces dépendances sont inclues pour l'exécution des tests automatisés mais ne seront pas inclues dans l'archive de production.
```xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
```
> 💡 utiliser le `<scope>test</scope>` pour indiquer qu'une dépendance ne doit être utilisée que dans les tests.
### Maintenance des dépendances
Il est important de mettre à jour ses dépendances.
En particulier quand elles sont sujettes à des failles de sécurité.
```shell
mvn io.github.mfoo:libyear-maven-plugin:analyze
```
## Exercice 3 : packaging et livrables
## Exercice 4 : install pour déployer localement
Créer un nouveau projet dans un dossier ailleurs que dans le projet courant.
`pom.xml` minimaliste
```xml
<?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>local.sample</groupId>
<artifactId>lib1</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
```
`src/main/java/local/sample/Lib1.java`
```java
package local.sample.lib1;
public class Lib1 {
public String hello() {
return "Hello Lib1";
}
}
```
Depuis ce dossier lancer la commande install.
```shell
mvn install
```
Cette commande copie les artefacts compilés dans le dépôt local.
---
Retournez dans votre projet initial
`pom.xml`
```xml
<dependency>
<groupId>local.sample</groupId>
<artifactId>lib1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
```
Lancez la compilation (ou rafraichissez maven dans IntelliJ)
```shell
mvn compile
```
Vous pouvez désormais importer le code du projet lib1 dans votre projet.
```java
package tp06.maven;
import local.sample.lib1.Lib1;
public class Main {
static void main(String[] args) {
System.out.println(new Lib1().hello());
}
}
```
> 💡 Bien entendu, cela ne fonctionne que dans votre dépôt local.
> Si vous voulez partager votre code au dela de votre machine, vous devrez le déployer d'un un dépôt maven distant.
## Exercice 5 : pom parent pour mettre en commun des configurations
## Exercice 6 : projets multi-modules
## Exercice 7 : faire un site
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.21.0</version>
</plugin>
```
```shell
mvn site:run
```
## Exercice 8 : déployer sur un nexus
<!--
TODO: Dans cette étape le prof va lancer un serveur nexus
pour expérimenter
-->
Ajouter l'adresse du nexus dans le pom.xml ou le pom parent.
```xml
<distributionManagement>
<repository>
<id>coda_lab</id>
<url>https://nexus.baldir.fr/repository/coda_lab/</url>
<name>coda_lab</name>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>coda_lab</id>
<url>https://nexus.baldir.fr/repository/coda_lab/</url>
<name>coda_lab</name>
</repository>
</repositories>
```
Ajouter l'id du serveur dans un fichier `~/.m2/settings.xml`.
```xml
<!-- Maven settings.xml template for publishing to Custom repository -->
<!-- Copy this file to ~/.m2/settings.xml and fill in your credentials -->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<servers>
<server>
<id>coda_lab</id>
<username>coda_deploy</username>
<password>deploy</password>
</server>
</servers>
</settings>
```