Maintenant que vous vous êtes familiarisé avec Maven, penchons-nous sur l'organisation de votre projet.
Du simple patron MVC à une architecture multi-tiers
Le patron MVC
Vous connaissez déjà le patron de conception MVC (Modèle-Vue-Contrôleur). (Si ce n'est pas le cas, vous pouvez vous reporter au cours : Développez des sites web avec Java EE)
Pour rappel, avec cette organisation, lorsqu'un utilisateur interagit avec votre application :
son action est prise en charge par le Contrôleur,
qui fait alors appel au Modèle. Celui-ci va réaliser l'action fonctionnelle et éventuellement interagir avec une base de données.
Une fois le travail du Modèle terminé, le Contrôleur met à jour la Vue qui est renvoyée à l'utilisateur.
Améliorer le patron MVC à l'aide du patron DAO
Cette organisation est bien, mais il est possible de l'affiner, en structurant notamment la partie Modèle. En effet, cette partie contient tout le cœur de fonctionnement de l'application, de la logique métier à la gestion des données.
Une manière d'améliorer les choses est d'utiliser par exemple le patron DAO (Data Access Object), permettant de mieux gérer la persistance des données en l'isolant du reste du traitement.
(Si vous ne connaissez pas le patron DAO, vous pouvez vous reporter au cours : Développez des sites web avec Java EE)
Séparer les responsabilités avec une architecture multi-tiers
Je vous propose d'aller plus loin, en adoptant une architecture multi-tiers.
Avec cette architecture en couches, l'utilisateur interagit avec votre application :
via la couche Présentation. Cette couche contient les parties Contrôleur et Vue du patron MVC.
Une fois l'action utilisateur identifiée, la couche Présentation fait appel à la couche Métier. Celle-ci est responsable de la logique métier de l'application, c'est-à-dire de l'implémentation des règles de gestion fonctionnelles.
Si des accès à la base de données sont nécessaires, alors la couche Métier appelle la couche Persistance. C'est dans cette couche que l'on retrouve le patron DAO.
Et toutes ces couches partagent une « vision commune » du domaine fonctionnel en s'appuyant sur le Modèle. En effet, ce modèle contient les JavaBeans manipulés dans l'application.
Une chose importante est que chaque couche n'appelle que la couche immédiatement en dessous d'elle et n'a aucune connaissance des couches supérieures.
Cette approche présente plusieurs avantages :
Imaginez que votre projet comporte une application web et des batches de traitement en masse. Eh bien, vous pouvez créer 2 couches de présentation (une pour l'application web, l'autre pour les batches) et partager les mêmes couches métier, persistance et modèle.
Un autre avantage est qu'il est possible de développer et tester les couches séparément en mettant en place des interfaces.
Séparer les couches applicatives avec Maven
Les modules Maven
Vous pouvez matérialiser le découpage de l'architecture multi-tiers grâce à des modules Maven. Chaque couche de l'architecture fait alors l'objet d'un module dédié.
Les modules sont des sortes de « sous-projets » Maven, rattachés à un projet Maven principal (appelé projet parent). Ils fournissent chacun leurs propres livrables et il est possible de créer des dépendances entres eux.
Voici ce que cela peut donner avec notre projet contenant des batches et une application web :
Vous remarquez que j'ai renommé la couche persistance en module consumer. J'ai, en effet, généralisé la responsabilité de cette couche à la consommation de « services » externes, par exemple une base de données ou des webservices.
Ainsi, votre projet Maven principal va devenir un meta-projet, agrégeant des modules. Dans le jargon de Maven, on appelle cela un projet multi-modules.
Les projets multi-modules
Un projet multi-modules est organisé comme ceci :
🗁 projet-x
├── 🗁 module-a
│ ├── 🗎 pom.xml
│ └── 🗁 src
│ ├── 🗁 main
│ │ └── 🗁 java
│ │ └── ...
│ └── ...
├── 🗁 module-b
│ ├── 🗎 pom.xml
│ └── ...
├── 🗎 pom.xml
Les modules sont dans des sous-dossiers dans le répertoire du projet parent.
Ils ont chacun une arborescence classique de projet Maven avec leur propre fichier pom.xml
, leur répertoire src/main/java
...
Créer un projet multi-modules
Mettons cela en pratique. Nous allons créer un projet de gestion de ticket d'incident. Il contiendra une application web et un jeu de batches.
Créer le squelette d'un projet multi-modules
Pour créer un projet multi-modules :
Commencez par créer le projet parent à l'aide de l'archétype
maven-archetype-quickstart
:mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.1 \ -DgroupId=org.exemple.demo \ -DartifactId=ticket \ -Dversion=1.0-SNAPSHOT
Allez dans le répertoire du projet qui vient d'être créé :
cd ticket
Supprimez le répertoire
src
, il ne sert à rien :rm -r ./src
Éditez le fichier
pom.xml
:Modifiez le packaging du projet. Il faut utiliser le packaging
pom
au lieu dejar
:<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>org.exemple.demo</groupId> <artifactId>ticket</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> ... </project>
Supprimez la dépendance vers
junit
:<project> ... <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> ... </project>
Créez ensuite tous les modules (sous-projets Maven) à l'aide d'archétypes :
ticket-batch (archétype
maven-archetype-quickstart
)ticket-webapp (archétype
maven-archetype-webapp
)ticket-business (archétype
maven-archetype-quickstart
)ticket-consumer (archétype
maven-archetype-quickstart
)ticket-model (archétype
maven-archetype-quickstart
)
## module : ticket-batch mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.1 \ -DgroupId=org.exemple.demo \ -DartifactId=ticket-batch \ -Dpackage=org.exemple.demo.batch ## module : ticket-webapp ## Remarquez ici l'utilisation de l'archetype "webapp" mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-webapp \ -DgroupId=org.exemple.demo \ -DartifactId=ticket-webapp \ -Dpackage=org.exemple.demo.webapp ## module : ticket-business mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.1 \ -DgroupId=org.exemple.demo \ -DartifactId=ticket-business \ -Dpackage=org.exemple.demo.business ## module : ticket-consumer mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.1 \ -DgroupId=org.exemple.demo \ -DartifactId=ticket-consumer \ -Dpackage=org.exemple.demo.consumer ## module : ticket-model mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DarchetypeVersion=1.1 \ -DgroupId=org.exemple.demo \ -DartifactId=ticket-model \ -Dpackage=org.exemple.demo.model
Une fois ceci fait, le fichier pom.xml
du projet parent devrait ressembler à ceci (j'ai ajouté des commentaires pour que cela soit plus lisible) :
```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>
<!-- =============================================================== -->
<!-- Informations du projet -->
<!-- =============================================================== -->
<!-- ===== Informations Maven ===== -->
<groupId>org.exemple.demo</groupId>
<artifactId>ticket</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- ===== Informations générales ===== -->
<name>ticket</name>
<url>http://maven.apache.org</url>
<!-- =============================================================== -->
<!-- Properties -->
<!-- =============================================================== -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- =============================================================== -->
<!-- Modules -->
<!-- =============================================================== -->
<modules>
<module>ticket-batch</module>
<module>ticket-webapp</module>
<module>ticket-business</module>
<module>ticket-consumer</module>
<module>ticket-model</module>
</modules>
</project>
```
Vous remarquez que les modules sont listés dans la balise <modules>
.
Définir les dépendances entre les modules
L'arborescence de votre projet multi-modules est créée, passons maintenant à la définition des dépendances entre les modules.
Nous le verrons plus en détail dans le chapitre suivant, mais nous allons gérer ces dépendances en deux temps :
Dans le POM du projet parent, nous listerons les dépendances et leur version de manière globale pour le projet.
Dans le POM de chaque module, nous définirons quelles sont les dépendances à utiliser.
Dans le POM du projet parent
Ouvrez le POM du projet parent et ajoutez-y une section dependencyManagement
:
<project>
...
<!-- =============================================================== -->
<!-- Gestion des dépendances -->
<!-- =============================================================== -->
<dependencyManagement>
<dependencies>
<!-- ===== Modules ===== -->
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-batch</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-business</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-consumer</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- ===== Bibliothèques tierces ===== -->
...
</dependencies>
</dependencyManagement>
...
</project>
Dans les POM des modules
Il ne vous reste plus qu'à définir les dépendances à utiliser dans les POM des modules dans la section dependencies
.
Les dépendances à définir sont celles-ci :
Commençons, par exemple, avec le module ticket-business. Il faut ajouter les dépendances vers les modules :
ticket-consumer
ticket-model
Ouvrez le POM du module ticket-business ajoutez-y les dépendances suivantes :
<project>
...
<!-- =============================================================== -->
<!-- Dépendances -->
<!-- =============================================================== -->
<dependencies>
<!-- ===== Modules ===== -->
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-consumer</artifactId>
</dependency>
<dependency>
<groupId>org.exemple.demo</groupId>
<artifactId>ticket-model</artifactId>
</dependency>
<!-- ===== Bibliothèques tierces ===== -->
<!-- JUnit -->
...
</dependencies>
...
</project>
Il ne vous reste plus qu'à procéder de même pour les autres modules.
Après cela, votre projet est prêt, vous pouvez commencer les développements, en répartissant les différents éléments dans leurs couches respectives. ;-)
Construire un projet multi-modules
La construction d'un projet multi-modules se fait comme pour un projet simple :
Vous vous placez dans le répertoire du projet parent.
Vous lancez vos commandes de build Maven dans ce répertoire. Ceci va lancer le build sur chacun des modules.
Par exemple, pour packager votre projet, faites :
cd /chemin/vers/projet-multi-modules mvn package
Ceci va générer les livrables de chaque module dans le repertoire target
de chacun de ces modules.
Résumons
Nous avons vu comment structurer votre projet en utilisant une architecture multi-tiers. Dans cette architecture en couches, chaque couche communique avec celle immédiatement inférieure et n'a aucune connaissance des couches supérieures.
Vous avez pu voir qu'il était possible de matérialiser cette organisation dans un projet Maven grâce aux modules.
Et enfin, je vous ai montré comment créer et construire un projet multi-modules.
Votre projet et maintenant bien structuré, les différents éléments le constituant sont clairement identifiés. Afin de terminer son organisation, il ne vous reste plus qu'à gérer les dépendances vers les bibliothèques tierces. C'est justement ce que nous allons voir dans le prochain chapitre.