Fractionner un gros projet pour créer un projet Maven multi-module

23

Je travaille sur une application Spring-MVC dans laquelle nous utilisons Maven pour la gestion des dépendances. Comme le projet est grand, nous pensons à diviser le projet en plusieurs parties. J'avais des doutes, et j'espère que j'aurai des réponses ici.

Actuellement, nous déployons un seul fichier WAR comme ROOT.warsur Apache tomcat sur notre serveur. Comme le projet est grand, il y a des parties dans la webapp comme les notifications et les e-mails, les services tiers, PUSH (Cometd), les API REST, etc. Actuellement, tous sont matraqués et dépendent les uns des autres. Par exemple, l' Notificationobjet dépend également de l' Personobjet, car les notifications sont adaptées aux utilisateurs.

L'intention principale de diviser le gros projet est de pouvoir travailler sur des modules individuels, pour des corrections de bugs, l'ajout de fonctionnalités, des tests, etc. Est-ce possible?

Comme je l'ai déjà mentionné précédemment, il existe des dépendances et des mappages entre les objets. Comment ceux-ci seront-ils gérés dans différents sous-modules, ou est-ce que les instructions d'importation changeront pour inclure d'autres projets?

Comme je l'ai dit, l'intention est de travailler sur des modules individuels et de pouvoir les déployer (de préférence à chaud). Actuellement, nous n'avons qu'un seul fichier WAR en tant que ROOT.war. Le fractionnement créera-t-il plusieurs fichiers de guerre, qui sont ensuite appelés URL domain-name.com/module_name/some_mapping?

Je vérifie actuellement la documentation, mais c'est l'objectif principal que nous voulons atteindre avec le module multi fourni par Maven et intéressé à savoir si cela est faisable. Si d'autres informations sont nécessaires, veuillez me le faire savoir.

Actuellement, j'utilise un POM parent du printemps comme suit:

<parent>
    <groupId>io.spring.platform</groupId>
    <artifactId>platform-bom</artifactId>
    <version>1.1.3.RELEASE</version>
    <relativePath />
</parent>
Nous sommes Borg
la source
1
Je laisse aux autres le soin de répondre. L'idée est très solide. Vous pouvez commencer avec un POM parent avec dependencyManagement et un pot pour les DAO comme Person. Une bibliothèque très basique. Etc. Bien sûr, pas de dépendances cycliques.
Joop Eggen

Réponses:

20

C'est possible ?

Oui certainement. J'ai dans le passé structuré quelques projets comme celui-ci, voici quelques morceaux qui, je l'espère, vous aideront à démarrer.

Il y a deux caractéristiques principales de Maven que vous utiliserez pour tisser des choses ensemble:

Diviser et conquérir

Vous devrez diviser vos projets en plusieurs projets indépendants. Ici, par indépendant, je veux dire que toutes les références au code en dehors du projet se font via des dépendances dans Maven et non directement en fusionnant l'arborescence source.

Selon l'état de votre arborescence source, cela pourrait représenter beaucoup de travail. Cela dit, vous ne le faites pas pour chausse-pied à Maven, mais plutôt comme un moyen de structurer et de désinfecter votre base de code. Considérez-le comme votre boîte à outils, beaucoup plus facile de trouver des choses ici:

Belle cabane à outils

qu'ici:

Atelier d'outils pas si agréable

Maven s'appuie fortement sur les conventions, donc mieux vos affaires sont organisées, plus Maven peut vous aider. Cela dit, cela peut vous obliger à vous réorganiser pour mieux correspondre à sa propre convention et si je dois donner un conseil ici, c'est qu'il est BEAUCOUP plus facile de modifier vos données pour qu'elles correspondent aux conventions de Maven que d'essayer de configurer Maven pour comprendre votre convention.

Si ces projets pouvaient être utilisables en dehors de l'application principale, ils pourraient vivre en tant que bibliothèques véritablement indépendantes et incluses via des dépendances maven. Ils doivent vivre dans leur propre référentiel (pas dans l'arborescence source de l'application) et ne doivent dépendre d'aucune partie de l'application principale.

Les parties centrales de votre application, une fois divisées en projets, peuvent être regroupées sous forme de modules. En règle générale, vous les placerez comme sous-dossier du dossier source principal de votre application.

Votre POM parent pour votre application contiendra également la déclaration du module. Vous y placerez également toutes les dépendances courantes pour votre application ainsi que la plupart des plugins de build et leur configuration. Ici aussi, je vous recommande vivement de placer un groupe de propriétés pour des choses telles que la version de l'application que vous pouvez réutiliser dans les modules. Il est beaucoup plus facile à gérer lorsque tout a la même version et le fait d'avoir la version au même endroit fait que cela fonctionne.

Outillage

Si vous êtes une équipe plus grande que 1, je vous recommande également fortement d'installer un référentiel pour vos dépendances Maven. Regardez Artifactory , Nexus ou Archiva . Vous pouvez configurer le fichier POM pour qu'il s'installe directement sur ceux-ci, donc une fois exécuté, cela ne devrait pas être une surcharge, mais cela fera gagner beaucoup de temps à votre équipe pour résoudre les dépendances avec le bon pot au bon endroit.

Concernant l'outillage, la prochaine étape logique est ici un système d'intégration continue ( Jenkins , il y en a bien d'autres). Il gérera la construction de la source en exécutant les tests et en poussant vers l'artifactory, avec tout cela en place, tout ce que vous avez à faire est de travailler le code et le reste fonctionne.

Étant donné que vous empaquetez votre application en tant que maven de guerre, vous pouvez gérer la construction de la guerre et placer toutes les dépendances à leurs emplacements appropriés sans avoir à fusionner les fichiers jar ou tout autre travail similaire, donc ne vous inquiétez pas.

Exemple

Je pourrais continuer beaucoup plus longtemps ici mais rien ne vaut un bon exemple. Recherchez sur github des projets de même ampleur et voyez comment ils ont construit leurs fichiers pom et leurs hiérarchies de dossiers. Regardez plus d'un, certains s'adapteront mieux à votre configuration que d'autres, aucun n'incarne vraiment la vérité, mais vous devriez en trouver suffisamment pour alimenter vos réflexions sur la façon de le faire.

Prenez Jenkins par exemple:

Vous pouvez voir que leur POM parent est assez étendu.

Ils utilisent des modules comme vous pouvez le voir dans cette section:

<modules>
    <module>core</module>
    <module>war</module>
    <module>test</module>
    <module>cli</module>
</modules>

Et à chaque module correspond un sous-dossier du même nom qui contient également un POM. Vous pouvez en imbriquer autant que vous le souhaitez, mais gardez-le dans les niveaux de santé mentale;).

Commencer petit

Si vous n'avez jamais utilisé Maven, je vous suggère de ne pas commencer tout de suite avec les modules. Allez-y lentement, commencez par dire l'une des bibliothèques les plus simples que vous puissiez avoir et faites-en un projet maven. Faites ensuite de votre application principale un simple projet maven. Une fois que cela fonctionne, commencez à ajouter des dépendances simples, puis divisez votre premier module et ainsi de suite.

Maven est un excellent outil, mais il peut également être une super douleur dans le cou, surtout lorsque les choses ne vont pas dans votre sens. Commencer par tout le coup lors de votre premier coup est une recette pour un désastre (c'était pour moi!).

Si les choses sont un peu bizarres, vous pouvez toujours utiliser la mvn help:effective-pomcommande pour voir ce que Maven a réellement compris.

plugins

D'après votre commentaire, je comprends mieux ce que vous voulez réaliser. Dans ce cas, j'opterais pour l'approche des plugins. Créez un projet qui expose l'API des points d'extension où vous souhaitez isoler le travail. Ensuite, vous pouvez l'utiliser comme dépendance dans un nouveau projet qui le mettra en œuvre. Dans votre application principale, ajoutez simplement les dépendances appropriées pour ces implémentations (n'utilisez pas les modules maven cette fois) et vous devriez être prêt à partir. Finalement, le projet d'application principal ne portera presque aucun code source, tout ce qui est fait dans des projets externes et chargé via des dépendances.

Cependant, vous devrez redéployer toute l'application avec cette approche, que le cœur ait changé ou non, car la guerre est construite statiquement à partir des dépendances, la modification de l'une d'entre elles implique de reconstruire le tout. Cela semble pire qu'il ne l'est réellement. En effet, seuls les nouveaux changements seront réellement construits, le reste sera essentiellement une copie du ou des pots précédents. Mais comme tout est dans le fichier de guerre, il devra être reconstruit et le serveur devra être arrêté et redémarré.

Si vous devez aller plus loin, les choses deviennent un peu plus compliquées, mais pas impossibles. Je recommanderais que vous examiniez OSGI, Apache Felix pourrait vous aider à démarrer, bien qu'il existe également d'autres implémentations. Cela vous permettra de prendre le pot externe et de les transformer en plugins appropriés. Vous gagnerez beaucoup plus de contrôle sur le cycle de vie d'exécution des composants ouvrant la porte aux rechargements et mises à jour dynamiques. Cela nécessitera cependant des modifications majeures de votre cœur, ce n'est probablement pas un bon point de départ. Cependant, une fois que vous avez un projet bien séparé et que toutes les parties sont isolées comme vous le souhaitez, cela pourrait être une prochaine étape naturelle si le démarrage et l'arrêt de l'application lors de la mise à jour est un problème majeur.

La différence fondamentale entre les modules et les dépendances est la suivante:

  • Les modules vivront dans la même arborescence source que l'application principale, idéalement comme sous-dossiers.
  • Les dépendances peuvent être n'importe où.

Vous pouvez trouver la Bible ici .

En espérant que ça aide, bonne chance.

Newtopian
la source
En fait, le regroupement de modules via maven au lieu de l'arborescence source a clarifié beaucoup de questions que j'avais. Pouvez-vous me parler du déploiement d'un tel projet? L'une des autres raisons que nous envisageons est de permettre aux développeurs de travailler sur leur module requis et d'effectuer les modifications en temps réel. Une chose que nous souhaitons éviter est d'arrêter le serveur d'applications et de redémarrer, sauf pour le module principal. Comme 2 modules que je peux imaginer contiendront du code qui change souvent. Nous utilisons tomcat comme serveur d'applications, équilibré en charge par Apache. Je vous remercie.
Nous sommes Borg le
Les modules Maven se trouvent souvent dans la même arborescence source que l'application principale. L'utilisation de modules maven en dehors de l'arborescence source est en réalité plus compliquée que cela ne vaut vraiment la peine. Si vous hébergez les projets en dehors de l'arborescence source, optez pour des projets indépendants normaux et utilisez des dépendances normales.
Newtopian
Je pense que nous irons pour ajouter des parties de notre projet directement en tant que dépendances Maven. De cette façon, nous pouvons travailler directement sur des parties du projet. Juste une question que j'avais, si nous ajoutons l'un des sous-projets en tant que dépendance dans POM.xml, disons la version 2.0.0, puis avec quelques modifications, nous poussons un 2.0.1 du module vers sonatype, comment pouvons-nous dire directement au core-module d'opter pour 2.0.1, il suffira de changer le POM.xml dans ROOT.war et de supprimer le répertoire ROOT. L'intention principale n'est pas d'arrêter le serveur. Je vous remercie.
Nous sommes Borg le
pom.xml n'a aucune incidence une fois la guerre créée, c'est-à-dire que Tomcat (ou le conteneur que vous utilisez) n'utilise pas ce fichier. Le fichier est utilisé par Maven pour créer un nouveau fichier de guerre, que vous devrez à son tour déployer sur le serveur. Ainsi, le cycle consiste à travailler sur le code, créer un fichier jar, mettre à jour la version dans le POM de la guerre, créer un fichier war, mettre à jour le serveur avec le nouveau fichier war. Certains serveurs prendront en charge le redéploiement à chaud, bien que cela implique généralement de désactiver l'application pendant quelques secondes.
Newtopian