Vous êtes sur la page 1sur 75

Orange septembre

2020

de Spring à Spring Boot


le build d'un projet avec Maven
sommaire
– introduction
– fichier de configuration pom.xml
– gestion des dépendances
– repositories
– plugins
– profils
– architectures de projets
– résumé des bonnes pratiques

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
introduction
problèmes rencontrés sans Maven
Chaque projet a sa propre arborescence, d'où la nécessité de définir explicitement le processus de construction de l'application :

– où sont les sources ?


– que faut-il compiler ?
– où mettre les exécutables ?
– y a-t-il des tests ? Où ?

Problèmes fréquents rencontrés ?

– quelles dépendances me sont réellement utiles, dans quelles versions ?


- souvent : copier/coller général à partir d'un autre projet, y compris les librairies
– des cycles de dépendances peuvent être bien cachés :
- classe A -> classe B -> classe C -> classe D -> classe A
– oubli d'incrémenter les versions au cours de la vie du projet.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
introduction
solutions apportées par Maven
Maven est un outil d'automatisation de build et gestion de projets Java, au coeur du processus d'intégration continue.

Maven s'appuie sur des mécanismes internes et la notion de convention over configuration pour :

– éviter un maximum de configuration pour builder un projet


– définir un cycle de build des projets
– gérer nativement les versions
– centraliser les librairies sous forme de repository
– gérer les dépendances directes et transitives
– intégrer des plugins pour étendre ses capacités.

Maven sait comment un projet doit être construit (comment compiler, créer un jar...).

Le projet va définir quoi construire (une application web war, une librairie jar, la liste des dépendances directes avec leurs versions...).

Par conséquent, tout pousse à adapter le projet à Maven, plutôt que l'inverse.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
introduction
fonctionnalités

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
introduction
arborescence des projets
Maven impose l'arborescence des fichiers au sein d'un projet :

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
fichier de configuration pom.xml
Un fichier central pom.xml (Project Object Model) permet de décrire un projet Maven.

Il va contenir :

– l'identificateur du projet
– le type de packaging souhaité
– des propriétés
– les dépendances nécessaires
– les plugins nécessaires
– les éventuels sous-projets (modules)
– un éventuel projet parent
– ...

<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
...
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
fichier de configuration pom.xml
identification du projet
Un projet Maven est identifé selon 3 paramètres :

– groupId : famille de composants (en général, de niveau projet)


– artifactId : nom du composant
– version : version du composant

Chaque projet Maven ne produit qu'un seul artefact nommé [artifactId]-[version].[extension].

<project ...>
...
<groupId>com.orange.monprojet</groupId>
<artifactId>monprojet-consumer-jpa</artifactId>
<version>1.5.3</version>
...
</project>

Dans cet exemple : monprojet-consumer-jpa-1.5.3.jar

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
fichier de configuration pom.xml
versions du projet
Maven impose la mise en place d'une gestion rigoureuse des versions du projet :

– versions Release : [version majeure].[ajout de fonctionnalité].[correction de bug]


- une version release est fixe dans le temps

exemple : 1.7.5

– versions -SNAPSHOT : [version majeure].[ajout de fonctionnalité].[correction de bug]-SNAPSHOT


- une version snapshot est en cours de développement
- elle sera probablement modifiée dans le temps

exemple : 1.7.6-SNAPSHOT (future version release 1.7.6)

Le plugin release permet de tager une version (N)-SNAPSHOT en version release (N), et de passer en version (N+1)-SNAPSHOT.

Certains frameworks (Spring, Hibernate...) ajoutent un suffixe (.RELEASE, .Final...) à leurs versions release.

exemples : spring-core-4.1.7.RELEASE.jar, hibernate-jpa-2.1-api-1.0.0.Final.jar

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
fichier de configuration pom.xml
packaging du projet
Indiquer le packaging final souhaité (le quoi) pour le projet (war, jar...). Grâce à ses conventions, Maven sait comment faire pour créer
l'artefact voulu.

<project ...>
...
<packaging>jar</packaging>
...
</project>

Il existe un type de packaging particulier (nous y reviendrons) qui permet de spécifier que ce projet est seulement un pom technique (il n'y a
pas de code à compiler, etc...).

<project ...>
...
<packaging>pom</packaging>
...
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances
Une dépendance représente un artefact nécessaire à un projet (généralement une librairie xxx.jar).

Seules les dépendances directes sont spécifiées dans le projet, grâce à leur identificateur (groupId, artifactId, version).

Maven va les télécharger depuis des dépôts publics ou privés, ainsi que les dépendances transitives.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances
scopes de dépendances
Plusieurs scopes définissent l'usage, la portée d'une dépendance :

– compile (scope par défaut) :


- dépendance utilisée pour la compilation et l'exécution
- dépendance ajoutée au war déployé sur le serveur d'applications
– runtime :
- dépendance utilisée pour l'exécution, mais pas pour la compilation
- dépendance ajoutée au war déployé sur le serveur d'applications
– test :
- dépendance utilisée seulement pour les tests
- dépendance non ajoutée au war déployé sur le serveur d'applications
– provided :
- dépendance utilisée pour la compilation et l'exécution
- dépendance non ajoutée au war déployé car fournie par le serveur d'applications
– import :
- import des dependencyManagement d'un pom.xml dans un autre pom.xml

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances
Seule les dépendances directes d'un projet sont à définir dans le pom.xml. Il faut spécifier pour chacune d'elles son groupId, son artifactId,
sa version et son scope (compile est facultatif car c'est le scope par défaut).

<project ...>
...
<dependencies>
...
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<scope>compile</scope>
</dependency>
...
</dependencies>
...
</project>

Attention : pour une version release du projet, il ne faut jamais dépendre de librairies en version -SNAPSHOT !

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances
propriétés
Il arrive souvent que pour un même framework (par exemple), il soit nécessaire d'ajouter plusieurs dépendances qui ont toutes la même
version.

Il est possible de définir des propriétés (dont le nom de balise est libre) dans le pom.xml, et d'y faire référence autant de fois que l'on veut
dans le pom.xml. Ainsi, il suffit de modifier cette propriété pour changer toutes les versions de librairies d'un même framework.

Il est conseillé de regrouper sous forme de propriétés toutes les versions des dépendances du projet :

– pour mutualiser la déclaration des versions de composants qui forment un ensemble cohérent (comme les frameworks)
– pour avoir une vision d'ensemble de toutes les dépendances directes utilisées.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
gestion des dépendances
propriétés
<project ...>
...
<properties>
<springsecurity.version>3.2.4.RELEASE</springsecurity.version>
...
</properties>
...
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
...
</dependencies>
...
</project>
de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
recherche d'artefact
Il est simple d'utiliser les identificateurs des artefacts gérés par son projet car on les connaît.

Comment faire pour connaître ceux des librairies externes ?

– sur Eclipse, le plugin m2Eclipse permet d'indexer des repositories


– sur internet, via un moteur de recherche Maven.

exemple : MVNRepository :

– permet surtout d'obtenir les identificateurs (fourniture du code à copier/coller dans son pom.xml)
– n'héberge pas les artefacts en question.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
Pourquoi utiliser des repositories ? Pour simplifier la réutilisabilité des composants.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
stockage des artefacts
Dans un repository, un artefact est stocké dans un répertoire (chemin basé sur son identificateur) contenant plusieurs fichiers :

– l'artefact lui-même (généralement un .jar)


– les sources de l'artefact (un .jar)
– le pom.xml de l'artefact (définissant son identificateur et éventuellement ses propres dépendances directes)
– le fichier de hashage (.sha1) de chacun de ces fichiers (pour s'assurer de l'intégrité de leur téléchargement).

<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories

Les dépôts sont définis dans le fichier de configuration Maven settings.xml. Localisation par défaut du repository local (propriété
localRepository) :

– sous Linux : ~/.m2/repository


– sous Windows : C:\Documents and Settings\utilisateur\.m2\repository
de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
inconvénients des dépôts distants sur internet
Le téléchargement des artefacts peut être fastidieux :

– débits limités
– serveurs encombrés
– téléchargements nombreux en provenance de chaque poste utilisant Maven

Les artefacts peuvent ne plus être disponibles dans le temps. La reproductibilité du build peut ne pas être assurée.

Certains projets ont besoin d'artefacts propriétaires non présents sur les repositories publics.

exemples : librairies Oracle...

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
solution du Maven Repository Manager
2 modes d'utilisation :

– hosted : dépôt Maven hébergeant les artefacts (projets et librairies internes, propriétaires et tout autre artefact Maven) dont on maîtrise
le contenu
– proxy : pointe sur plusieurs dépôts publics pour télécharger une unique fois les artefacts qu'il n'héberge pas encore.

Avantages :

– économie de bande passante : téléchargement unique des artefacts depuis les dépôts publics
– simplification de la configuration : agrégation de tous les dépôts publics sous une seule URL
– travail collaboratif : mutualisation des dépôts sur le gestionnaire
– gain de temps : mise à disposition sur le réseau interne de ces artefacts (meilleur débit)
– sécurité : contrôles d'accès.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
solution du Maven Repository Manager

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
configuration du proxy d'entreprise
Pour utiliser le proxy d'entreprise, il faut spécifier (sur le poste client) les miroirs appropriés dans le fichier settings.xml, qui redirigent les
requêtes vers le(s) proxy(ies) Maven :

<mirrors>
...
<mirror>
<id>artifactory.proxy.central</id>
<mirrorOf>central</mirrorOf>
<name>Artifactory Proxy mirroring central (maven 2) repository</name>
<url>renseigner_url</url>
</mirror>

<mirror>
<id>orange.central.mirror</id>
<name>Orange Central Mirror</name>
<mirrorOf>central</mirrorOf>
<url>renseigner_url</url>
</mirror>
...
</mirrors>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
repositories
gains sur la gestion de configuration
Traditionnellement, chaque projet devait gérer en configuration (git, svn...) toutes les librairies qu'il utilise pour chaque version du projet. Les
mêmes librairies dans les mêmes versions et/ou dans des versions différentes sont donc stockées plusieurs fois pour chaque projet.

Exemples : en gestion de configuration pour le projet "toto" :

– v1.0 : slf4j_1.6.2, junit_4.8, spring_3.0.1_RELEASE...


– v1.1 : slf4j_1.6.2, junit_4.8, spring_3.2.8_RELEASE...
– v2.0 : slf4j_1.7.6, junit_4.8, spring_4.1.1_RELEASE...

projet "titi" : idem, avec beaucoup de librairies communes aussi au projet "toto".

Sachant que dans une version de projet, le ratio code source/librairies externes ne doit pas dépasser les 5% (grand max), on imagine l'espace
disque énorme qui est gâché pour dupliquer ces librairies sur les serveurs. De plus, cela nuit aux performances de la gestion de configuration.

Avec Maven et le repository d'entreprise, chaque librairie va être stockée en 1 et 1 seul exemplaire. Le projet ne gère que ses vraies sources
en configuration (pom.xml + code).

Les librairies seront récupérées depuis le dépôt Maven (local ou d'entreprise) lors du build.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
extensibilité de Maven
Dans Maven, tout est plugin ou presque. Le noyau de Maven ne sert qu'à appeler des plugins, qui réalisent les actions nécessaires lors du
build.

Les plugins permettent de faire tout ce qu'on peut faire en Java :

– générer du code
– compiler des sources
– manipuler des fichiers
– créer des rapports
– manipuler la gestion de configuration
– lancement de serveurs d'applications
– ...

Grâce aux plugins, il est possible de créer de nouvelles actions ou d'adapter celles existantes.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
extensibilité de Maven
Il existe des plugins de base :

– compiler : compiler des sources


– surefire : exécuter des tests
– install : déploiement d'artefact dans un repository Maven
– clean : suppression des fichiers générés
– ...

Beaucoup de nouveaux plugins ont été créés par les éditeurs pour répondre à des besoins particuliers :

– eclipse : génération de fichiers projets pour Eclipse


– cargo : déploiement (war...) sur un serveur applicatif
– swagger : génération de code à partir d'une API json Swagger
– cxf : génération de code à partir d'un WSDL
– ...

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
déclaration dans le pom.xml
Comme pour les dépendances, les plugins sont identifiés par les 3 paramètres groupId, artifactId et version, et sont regroupés dans une
section du pom.xml qui leur est propre.

Par convention, l'artifactId d'un plugin est en général de la forme maven-[nomPlugin]-plugin (exemple : maven-compiler-plugin).

En ligne de commande, pour lancer un plugin, il suffit de taper : mvn [nomPlugin] (exemple : mvn compiler).

De plus, il y a souvent la possibilité de paramétrer ces plugins :

– pour pointer vers un fichier particulier


– pour changer le nommage par défaut des packages lors de la génération de code....

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
déclaration dans le pom.xml
Par exemple :

<build>
<plugins>
...
<plugin>
<groupId>org.springdoc</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
...
</plugins>
...
</build>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
goals
Un plugin possède un ou plusieurs goals, qui effectuent concrètement les actions.

Par exemple :

maven-compiler-plugin possède 2 goals :

– compile : compile les sources java de src/main/java


– testCompile : compile les sources java de test de src/test/java

maven-surefire-plugin possède 1 goal :

– test : exécute les tests unitaires de src/test/java

Un goal peut être appelé directement via la commande : mvn [nomPlugin]:[nomGoal]

Exemple : mvn compiler:compile

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
cycle de vie
Maven définit plusieurs cycle de vie (life cycle) permettant d'ordonnancer des phases prédéfinies :

– standard : enchaînement des phases liées au build de l'application, pouvant varier suivant le type d'artefact à produire (jar, war...)
– clean : suppression des fichiers générés dans /target, pour ne garder que les sources
– site : génération du site web du projet (analyses de code, résultat des tests...).

Quand on demande l'exécution d'une phase du cycle de vie (mvn [nomPhase]), toutes les phases précédentes sont automatiquement
lancées dans le bon ordre, et donc tous les goals de tous les plugins liés à ces phases là.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
cycle de vie standard (simplifié)

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
cycle de vie
Par exemple, la commande mvn install va :

– récupérer les librairies nécessaires à la compilation


– compiler les sources
– compiler et exécuter les tests unitaires
– packager l'artéfact et le déployer dans le repository Maven local.

Remarque : normalement, à partir des sources d'un projet Maven, il est donc possible de construire une application, même sans
la connaître.

Cela évite les lignes de commandes interminables où tous les plugins et leurs goals doivent être mentionnés, dans le bon ordre :

Exemple : mvn compiler:compile compiler:testcompile surefire:test jar:jar install:install

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
cycle de vie
A chaque phase est associée un plugin par défaut, pour réaliser les actions (via les goals) liées à cette phase.

Les goals se greffent sur les phases du cycle de vie.

Il est possible d'ajouter des actions à n'importe quelle phase grâce à des plugins (et donc des goals) spécifiques.

– le lancement de la phase 2 exécute les goals dans cet ordre :


- Goal1, Goal3, Goal2
– le lancement de la phase 4 exécute les goals dans cet ordre :
- Goal1, Goal3, Goal2, Goal3

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
cycle de vie
La liaison du goal d'un plugin à une phase du cycle de vie se fait dans la déclaration du plugin, dans la partie <executions> :

– id : identifiant de la liaison
– phase : phase du cycle de vie
– goal : goal du plugin à appeler.

<plugin>
...
<configuration>
...
</configuration>
<executions>
<execution>
<id>swagger-generate</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
documentation
Deux principales sources d'informations sur les plugins :

– le site officiel de Maven, partie plugins


– le site de la fondation MojoHaus, partie plugins

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
documentation
La documentation sur les plugins se présente généralement sous la forme de site généré par Maven.

– Goals : description des différents goals du plugin


– Usage : comment utiliser le plugin
– FAQ : principaux cas d'utilisation ou problèmes rencontrés
– Examples : exemples d'utilisation particulière ou poussée

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
plugins
documentation
Les descriptions des plugins et des goals sont disponibles également en ligne de commande :
mvn help:describe –DgroupId=[groupId] -DartifactId=[plugin] -Dversion=[version]

exemple : mvn help:describe -DgroupId=org.apache.maven.plugins -DartifactId=maven-compiler-plugin -Dversion=3.3

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
profils

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
profils
déclaration des profils
Les <profiles> permettent de personnaliser un build selon différents cas de figure (environnement de déploiement cible par exemple).

Chaque <profile> peut surcharger les valeurs par défaut déclarées dans le pom.xml :

– des properties
– des dépendances
– des plugins pour surcharger leur configuration
– ...

<profiles>
<profile>
<id>tomcat-test</id>
<!-- surcharge de configuration -->
...
</profile>
</profiles>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
profils
activation des profils
Lors du build, il est possible de choisir le profil que l'on souhaite activer :

– en ligne de commande : mvn clean install -P<idProfile>


– ou dans l'IDE (dans Eclipse : Run As \ Maven build...).

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
découpage des projets
Suivant la taille et l'architecture des projets (au sens applications), ils peuvent être (ou non) découpés en modules, dépendants les uns des
autres. Ces modules peuvent être soit :

– des composants fonctionnels


– des couches de l'application (provider, consumer, business...)
– un mélange des 2.

L'intérêt de ces modules, c'est d'améliorer la maintenabilité et l'évolutivité de l'application en isolant des parties.

Par exemple cela permet de changer la couche provider d'une technologie vers une autre (SOAP -> REST), sans avoir à retoucher le reste du
projet.

Note : dans le cadre de microservices, chaque microservice représente un projet Maven simple développé indépendamment
des autres microservices, sans utilisation de modules à proprement parler.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
découpage des projets
Pour Maven un module :

– est 1 sous-projet Maven (chacun ayant son pom.xml) appartenant à une même arborescence de projets Maven
– produit un artefact (en général un jar).

1 projet Maven multi-modules est donc une agrégation de plusieurs modules, définis dans un pom agrégateur, permettant
d’ordonnancer la construction de chaque module selon leurs dépendances.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
agrégation des modules
Le pom agrégateur :

– a un packaging de type pom


– liste les modules faisant partie d'une même application, pour les rassembler sous un seul projet.

Une fois ces informations définies dans le pom.xml, Maven :

– exécute une phase de build sur tous les modules


– résout les dépendances entre modules pour déterminer l'ordre de build.

<project>
...
<packaging>pom</packaging>
...
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
agrégation des modules

Ordre de construction des modules :

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
agrégation des modules
La gestion des dépendances (et des plugins) sur plusieurs modules amène certains inconvénients :

– une configuration redondante : dépendances communes répétées dans chaque module


– une homogénéité difficile à maintenir : à chaque modification d'une dépendance (version...), penser à modifier chacun des pom.xml
des modules
– une configuration dispersée : difficile d'avoir une vision d'ensemble des dépendances utilisées par un projet, avec leur version (et
détecter d'éventuels conflits).

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage entre modules
Il convient de mutualiser dans le pom parent (ayant un packaging de type pom) du module parent les informations communes des différents
modules, pour que ceux-ci puissent en hériter :

– groupId
– version
– les dépendances
– les plugins et leur configuration
– propriétés.

Les sous-modules doivent préciser quel est leur parent :

<project>
...
<parent>
<groupId>com.orange.monprojet</groupId>
<artifactId>agregateur</artifactId>
<version>2.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
...
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage entre modules

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage entre modules

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage entre modules

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage entre modules

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances
Définir une dépendance dans le pom parent provoque :

– son héritage dans tous les sous-modules


– l'inclusion automatique de cette dépendance (jar) dans le war final.

Or cette dépendance n'est pas forcément nécessaire dans tous les modules. D'ailleurs, certaines librairies devraient être interdites d'utilisation
suivant les modules (accès à une base de données depuis un module provider REST...).

Pour gérer plus finement les dépendances, tout en gardant l'avantage de la mutualisation dans le pom parent, il existe la balise
<dependencyManagement>, qui signifie que :

– au moins un module devrait normalement utiliser cette dépendance


– chaque module qui voudra l'utiliser devra le spécifier explicitement (sans la version)
– si au moins un module l'utilise, elle sera effectivement téléchargée et incluse dans le war
– si aucun module n'en fait la demande, elle sera ignorée.

Il est important de centraliser la définition des versions des dépendances dans le pom parent en tant que
<dependencyManagement>.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances
Dans le pom parent :

<project ...>
...
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${springdata.version}</version>
</dependency>
...
</dependencies>
</dependencyManagement>
...
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances
Le pom du module ne reprécise que le groupId et l'artifactId d'une dépendance qui doit être déclarée dans le <dependencyManagement>
du pom parent.

Dans le pom.xml du module :

<project ...>
...
<dependencies>
...
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
...
</dependencies>
...
</project>

La version de la dépendance est héritée, et donc mutualisée. Chaque module qui en aura besoin utilisera la même.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances : résolution des conflits
Parmi toutes les dépendances (directes ou transitives), il se peut que certaines entrent en conflit.

Dans ce cas, il est possible de les résoudre en lançant des lignes de commandes :

– mvn dependency:tree : permet de connaître l'ensemble des dépendances de votre projet


– mvn dependency:analyze : permet de repérer les dépendances inutilisées
– il est possible d'exclure les dépendances non utiles pour résoudre les conflits.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances : scope import
Ce scope n'est utilisable que dans la section dependencyManagement et pour des dépendances de type pom. Il permet d'importer les
dependencyManagement définis dans un autre pom.

<project ...>
<groupId>com.monprojet</groupId>
<artifactId>monprojetA</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.monprojet</groupId>
<artifactId>pomB</artifactId>
<version>1.0.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances : scope import
Ce projet pomB (packaging pom) possède une dépendance vers spring-core en tant que dependencyManagement. Cette dépendance sera
importée dans le projet monprojetA.

<project ...>
<groupId>com.monprojet</groupId>
<artifactId>pomB</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances : scope import
Au final, les dépendances de dependencyManagement du projet pomB sont copiées/collées dans celles du projet monprojetA :

<project ...>
<groupId>com.monprojet</groupId>
<artifactId>monprojetA</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.1.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

Attention : les dependencyManagement ne sont pas transitifs.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des dépendances : notion de BOM
Le BOM (Bill of Materials) est un pom technique qui va permettre d'exploiter le scope import :

– il ne comporte qu'une section dependencyManagement centralisant les versions que l'on va utiliser dans le projet
– il sert d'annuaire de dépendances et leurs versions.

L'intérêt va apparaître sur les gros projets ou les ensembles de projets.

Grâce au BOM, on peut définir plusieurs pom techniques, chacun spécialisé dans certaines fonctionnalités (et donc nécessitant certaines
dépendances). Et chaque projet va pouvoir choisir quels sont les BOM à inclure dans ses dépendances.

Cela permet d'avoir une homogénéité des dépendances sur un groupe de projets (ou même au niveau d'une entreprise).

Spring Boot s'appuie sur ce principe. Il fournit des BOM spécialisés dans la gestion des bases de données, d'autres dans les
API REST...

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
projets multi-modules
héritage des plugins
Le même principe de <dependencyManagement> a été appliqué sur les plugins pour répondre aux mêmes problématiques, mais avec la
balise <pluginManagement>.

<project ...>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
</plugin>
...
</plugins>
</pluginManagement>
...
</build>
...
</project>

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
bonnes pratiques

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
bonnes pratiques organisationnelles
Avec un projet Maven, il est important de répartir les rôles de façon judicieuse dans un projet :

– responsable technique :
- garant de la solution technique, des choix d'architecture et d'évolutions
- assure la cohérence des pom.xml : cohérence globale des technologies utilisées et des licences
– développeurs :
- si possible, un développeur par module, afin d'éviter les merge en gestion de configuration
- faire valider toute modification d'un pom.xml (d'un module, ou parent) auprès du responsable technique.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
bonnes pratiques architecturales
Suivant le type de projet, les choix d'architecture en terme de projet Maven peuvent varier :

– quand utiliser un projet simple ?


- très petite application
- un seul développeur
- composant utilitaire transverse aux projets
– quand utiliser un projet multi-modules ?
- besoin d'une séparation des couches ou des composants
- besoin d'assemblage
- équipe de plusieurs développeurs.

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
bonnes pratiques architecturales
En général, les projets optent pour une architecture hiérarchique (comme expliqué jusqu'ici) :

– regroupant tout ce qui a le même cycle de vie que le projet (en terme de version et livraison)
– projet de petite ou moyenne taille
– équipe travaillant sur l'intégralité du projet
– les modules peuvent être eux-mêmes des projets multi-modules.

D'autres architectures sont possibles (cf annexes).

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
documentation
– Site Maven
– Site MojoHaus : plugins
– Site MVNRepository : recherche de dépendances

de Spring à Spring Boot - le build d'un projet avec Maven (Orange internal)
merci
annexes
architectures des projets multi-modules

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)


projets multi-modules
agrégation et héritage
Les projets Maven multi-modules reposent donc sur 2 notions majeures :

– agrégation :
- pom agrégateur ou pom chapeau
- contient les balises <modules> <module> ... </module> </modules>
– héritage :
- pom parent
- mutualise les dépendances et les plugins communs aux modules
- les modules héritent du pom parent via la balise <parent>...</parent>

La séparation de ces notions est possible :

– pom agrégateur et pom parent peuvent être différents


– 3 architectures types sont possibles
- architecture à plat (cf Annexes)
- architecture hiérarchique
- architecture mixte (cf Annexes)

Remarque : un module peut lui-même être un projet multi-modules !

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)


projets multi-modules
architecture à plat (flat) v1
Avantages :

– mutualisation des dépendances, des plugins et des versions de A et B


– build ordonné

Inconvénients :

– l'ensemble des sources du projet sont nécessaires pour travailler sur un module
– architecture incompatible avec le plugin release

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)


projets multi-modules
architecture à plat (flat) v2
Avantages :

– mutualisation des dépendances, des plugins et des versions de A et B


– indépendance du développement de chaque module

Inconvénients :

– si dépendance entre A et B, ordonner le build manuellement


– architecture incompatible avec le plugin release

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)


projets multi-modules
architecture hiérarchique (à privilégier)
Avantages :

– mutualisation des dépendances, des plugins et des versions de A et B


– build ordonné
– utilisation possible du plugin release

Inconvénients :

– l'ensemble des sources du projet sont nécessaires pour travailler sur un module

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)


projets multi-modules
architecture mixte
Avantages :

– mutualisation des dépendances, des plugins et des versions de A et B


– utilisation possible du plugin release
– indépendance du développement de chaque module

Inconvénients :

– gestion séparée des versions de l'agrégateur et du parent : synchronisation manuelle

de Spring à Spring Boot - Spring Framework : la mécanique de base (Orange internal)

Vous aimerez peut-être aussi