## Descripteur de projet : pom.xml Le fichier `pom.xml` est le descripteur de projet. 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>tp05.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> ``` ## Commandes usuelles - `mvn compile` - `mvn test` - `mvn install` - `mvn clean` ## Sources générées : target Un dossier `target` est créé lorsqu'on compile du code (ou autres actions). Pour supprimer ce dossier : `mvn clean` > [!important] > Il est important d'exclure le dossier `target` de git car on ne veut pas versionner que les sources `.gitignore` ```.gitignore target ``` ## Convention : arborescence > [!info] Hiérarchie standard d'un projet maven > ```text > ├── pom.xml > └── src > ├── main > │ ├── java > │ │ └── tp06 > │ │ └── maven > │ │ └── Main.java > │ └── resources > └── test > ├── java > └── resources > ``` ## Extensibilité de Maven Maven est extensible via des plugins. 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/ Ex. un plugin pour exécuter un programma java ```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> ``` Utilisation du plugin exec ```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 phases de 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> ``` > 💡 Il est parfois nécessaire d'utiliser une version récente du plugin compiler quand de nouvelles versions de Java sortent. ### Cycles de vie Les plugins standard de maven se déclinent en goals. Ces goals sont exécutés dans un certain ordre. C'est ce qu'on appelle le cycle de vie (lifecycle). Dans le cycle de vie par défaut les phases sont exécutées dans l'ordre suivant - `validate` - `compile` - `test` - `package` - `verify` - `install` - `deploy` Chaque phase est constituée de plusieurs goals. Les phases peuvent être executées ```sh mvn compile ``` https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference ### 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] ------------------------------------------------------------------------ ``` ## Dépendences 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 ``` ## Packaging et livrables ## Installer et déployer 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. ## Réutiliser des configurations avec un pom parent ## Projets multi-modules ## Site ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-site-plugin</artifactId> <version>3.21.0</version> </plugin> ``` ```shell mvn site:run ``` ## Déployer sur un repository (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> ``` ## À suivre [[Gradle]]