Modules et gestion de dépendances avec Maven

Modules Maven

Vous connaissez déjà Maven grâce à cette article et vous vous demander parfois à quoi peux servir un projet Maven multi-module.

Lorsque vous réaliser un grand projet, il n’est pas rare de réaliser plusieurs petites applications inter-connectés qui réalise chacune des tâches distinctes:

  • L’application Métier
  • Une Interface Web
  • Un application batch de traitement de données
  • Une interface Client Lourd

Maven propose donc une architecture multi-module permettant de regrouper ces différentes applications au sein d’un projet parent. Cette modularité permet une meilleur maintenabilité dans le temps, mais aussi d’identifier clairement les inter-connexions entre modules.

Par exemple, pour stopper le développement de mon client lourd à base de Swing qui ne sert plus à grand chose, je n’ai pas à aller modifier tout le code de mon gros projet volumineux, je ferme simplement le module correspondant, et je n’y touche plus.

Le projet parent a aussi l’avantage de pouvoir regrouper la configuration commune à l’ensemble de nos modules:

  • Gestion des dépendances et des versions. Un seul endroit pour faire une monté de version de Spring par exemple
  • Gérer des variables à réutiliser dans les POM des modules
  • Configurer les paramètres de connexion aux outils externes : git, jenkins, jira, etc.

Création du projet parent

Pour créer un projet multi-module, il faut d’abord créer un répertoire parent du nom de votre projet, et créer un fichier pom.xml, et ensuite créer des sous-répertoire pour chaque module. Chaque module doit avoir son propre pom.xml.

Voici le code du pom parent.

<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>fr.w3blog.demo</groupId>
  <artifactId>springrest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
          <module>springrest-model</module>
  </modules>
</project>

Et celui d’un module.

<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>
  <parent>
    <groupId>fr.w3blog.demo</groupId>
    <artifactId>springrest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springrest-model</artifactId>
</project>

La plupart des IDE doivent vous permettre de créer cette arborescence automatiquement. Sous Eclipse, les modules sont considérés comme des projets à part entière, il vous suffit donc sur un projet maven de créer un nouveau projet et de sélectionner Module Maven dans le type de projet à créer.

Ajout des dépendances avec Maven

Comment ajouter une librairie à notre projet? Nous allons prendre comme exemple la librairie hibernate et l’inclure à notre projet.

Avec un projet Java classique, nous aurions téléchargé l’archive jar depuis un site internet que nous aurions inclus dans le répertoire WEB-INF/lib de notre projet web. Mais il aurait fallut très certainement recommencer pour télécharger la librairie javax.validation pour permettre à notre programme de reconnaître les annotations Beans Validation dont Hibernate a besoin pour contrôler ces données.

C’est là que la gestion des dépendances de Maven intervient, car elle connait les dépendances entre les librairies et est capable de résoudre automatiquement ces problèmes. Il nous suffit donc de déclarer la dépendance à Hibernate dans le fichier pom.xml de notre projet.

A la première compilation, Maven se charge automatiquement d’aller chercher la bonne librairie sur le repository central de Maven. Maven détecte également les dépendances nécessaire au bon fonctionnement d’hibernate, comme  la librairie validation-api, et va donc la télécharger. C’est d’ailleurs pour cette raison, que le tout premier lancement d’une commande Maven sur un nouveau poste est très longue car Maven va télécharger tout ce dont il besoin pour fonctionner, aussi bien les dépendances du projet, que ces propres dépendances pour lui permettre de compiler.

<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>
  <parent>
    <groupId>fr.w3blog.demo</groupId>
    <artifactId>springrest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>springrest-model</artifactId>

        <dependencies>
           <dependency>
               <groupId>org.hibernate</groupId>
               <artifactId>hibernate-core</artifactId>
               <version>3.6.10.Final</version>
           </dependency>
           <dependency>
               <groupId>org.hibernate</groupId>
               <artifactId>hibernate-annotations</artifactId>
               <version>3.5.6-Final</version>
           </dependency>
           <dependency>
               <groupId>org.hibernate</groupId>
               <artifactId>hibernate-validator</artifactId>
               <version>4.3.1.Final</version>
           </dependency>
        </dependencies>

</project>

Si vous avez regardé l’article sur la création d’un projet Maven, vous aller surement reconnaitre les notions de groupId et artefactId.

Si votre IDE est configuré correctement, il doit mettre à jour automatiquement son Classpath et inclure les librairies, ce qui va vous permettre de faire de l’autocompletion sur les classes et les annotations.

Dans le cas contraire ou si vous utiliser la ligne de commande, il faudra executer la commande suivante dans le répertoire parent du projet

mvn install

Votre projet devrait ressembler à ceci.

maven-dependance

Dépendance Maven dans Eclipse

Gérer les dépendances dans le module parent

La syntaxe maven de déclaration des dépendances est assez lourde, il faut préciser la version de la librairie pour chaque dépendance. Monter de version une librairie ou un framework comme Spring pourrait vite devenir problématique. Heureusement, il existe le gestionnaire de dépendance dans maven, associé au multi-module, il présente de nombreux avantages.

Plutôt que de préciser le numéro de version dans chacun de nos sous-module, il est possible de définir une seul fois la version dans le module parent.

Voici à quoi ressemble le module enfant.

	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-core</artifactId>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-jdbc</artifactId>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-orm</artifactId>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-tx</artifactId>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-test</artifactId>
	   </dependency>

La déclaration des version ne se fait qu’une seule fois dans le POM du module parent, ce qui facilite la maintenance.

Voici la gestion des dépendances dans le POM parent :

  <properties>
  	<spring.version>3.2.0.RELEASE</spring.version>
  </properties>
  
  
  <dependencyManagement>
  	<dependencies>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-core</artifactId>
	       <version>${spring.version}</version>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-jdbc</artifactId>
	       <version>${spring.version}</version>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-orm</artifactId>
	       <version>${spring.version}</version>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-tx</artifactId>
	       <version>${spring.version}</version>
	   </dependency>
	   <dependency>
	       <groupId>org.springframework</groupId>
	       <artifactId>spring-test</artifactId>
	       <version>${spring.version}</version>
	   </dependency>
  	</dependencies>
  
  </dependencyManagement>

Grâce au propriété maven, la version peux être écrite qu’une seule fois. spring.version défini dans la balise properties permet de définit une variable qui peux être réutilisée dans le fichier de configuration Maven.

Gérer dans les dépendances aux version dans le POM parent permet d’effectuer une monté de version de Spring très rapidement. Il suffit de mettre à jour la variable à un seul endroit