Libellés

mardi 5 juillet 2011

Maven : créer un projet multi-module

Maven, le très célèbre outil de build et gestionnaire de dépendances nous offre quelques possibilités bien sympatique.

Vous connaissez sûrement les projets multi-modules, qui permettent de découper un projet pour plus de modularité.

Par exemple vous construisez un projet P. Ce projet est constitué de plusieurs sous-projet A, B, C ayant comme dépendances respectives :

P :
  - A (A1, O)
  - B (O)
  - C (C1, A)

Comme vous le voyez, C dépend de A, mais pas de B. De plus la dépendance O est partagée entre plusieurs sous-projet.

Maven va bous permettre de gérer ses trois sous projet en réduisant le nombre de lignes de code copiées collées.



Voici le pom de P, le projet coordinateur :

<project ....>

    <groupId>org.groupId</groupId>
    <artifactId>P</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <modelVersion>4.0.0</modelVersion>
    
    <modules>
        <module>A</module>
        <module>B</module>
        <module>C</module>
    </modules>
</project>


Il faut remarquer deux choses :
 
  - le packaging == pom, qui nous dit que ce projet n'aura pas de code source
  - la section modules qui représente notre structure.


Ensuite à la racine de ce projet, nous allons créer les 3 sous projets : A, B, C

/my-project
|--pom.xml
|--A
|  `--pom.xml
|--B
|  `--pom.xml
`--C
   `--pom.xml     



Voici le pom du sous-projet A  :

<project ...>
    <parent>
        <artifactId>P</artifactId>
        <groupId>org.groupId</groupId>
        <version>1.0.0</version>
    </parent>
    
    <modelVersion>4.0.0</modelVersion>
    <artifactId>A</artifactId>
    
....


Dans la balise parent, on défini la dépendance vers notre projet parent P.

Nous remarquons que pour A, il n'y a pas de balise groupId ni de balise version à définir A.
En effet, ces valeurs sont héritées du pom parent, pratique !!!!



Maintenant prenons le cas où certains sous-projets aient des dépendances en commun. A et B dépendent de O.

On pourrait tout a fait déclarer dans A et dans B les dépendances complètes (avec la version) :
<dependencies>
    <dependency>
        <groupId>com.aProject</groupId>
        <artifactId>O</artifactId>
        <version>5.6.7</version>
    </dependency>
</dependencies>


Mais le jours, on l'on changera la version de O ( 5.6.7 ---> 5.6.8 ) dans A, on oubliera sûrement de changer la version de O dans B, et l'on se retrouvera avec un pom dégelasse avec plein de dépendances différentes.

La solution consiste donc à ne pas déclarer les versions dans les poms des sous-projets, mais dans le pom parent.


Je vous donne un exemple :

<project ....>

    <groupId>org.groupId</groupId>
    <artifactId>P</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <modelVersion>4.0.0</modelVersion>
    
    <modules>
        <module>A</module>
        <module>B</module>
        <module>C</module>
    </modules>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8.2</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>




Dans le pom d'un sous-projet, la section de dépendance ressemblera à :
<dependencies>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Cool, on a supprimé la version !!!!



Maintenant voyons le cas où C dépend de A, c'est à dire étudions les dépendances entre sous-projets.

Voici la section de dépendance de C :
<dependencies>
    ....
    <dependency>
        <groupId>${parent.groupId}</groupId>
        <artifactId>A</artifactId>
        <version>${parent.version}</version>
    </dependency>
    ....
</dependencies>


On est obligé de spécifier la version, mais regardez bien, nous faisons référence à une variable interne : ${parent.version}, de même pour la balise groupId. Zéro problème pour maintenir ce pom !!!


Et maintenant nous pourrions avoir envie de créer nos propres variables dans le pom parent et d'utiliser n'importe où.
Aussitôt dit, aussitôt fait. Editez votre pom parent et ajoutez la section :
<properties>
    <foo.bar>FooBarValue</foo.bar>
</properties>

Maintenant on peut utiliser cette valeur de partout ce cette façon : ${foo.bar}

Il y a bien sur une limite, la section parent ne peut être défini à partir de variable défini dans le pom parent. Sinon ce n'est pas évident pour deviner qui est le parent quand on lit le pom d'un sous-projet.

Aucun commentaire:

Publier un commentaire