lundi 2 juin 2008

Maven : war dépendant d'un autre war

Comment utiliser la gestion de dépendances de maven entre war.

La problématique posée était la suivante : comment capitaliser et partager des éléments communs dans plusieurs applications web. Ce type de besoin provient en fait à l'existence d'un "framework" proposant des composants communs chez mon client pour permettre de réutiliser des jsp, des scripts Javascripts, des tlds, des images, ... on va l'appeller le "framework war"

Le but pour moi est de récupérer dans les sources de mon application web dans le répertoire racine de la webapp, l'ensemble des composants du framework war.

En cherchant un peu, on peut voir que le plugin war de maven propose un goal war:inplace qui semblerait coller à mon besoin!!! cool!!

Je définis alors en dépendance de mon application web mon framework war :
<?xml version="1.0"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fr.sevellec.test</groupId>
<artifactId>my-application-webapp</artifactId>
<packaging>war</packaging>
<name>my application de test pour le fwk</name>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>fr.sevellec.fwk</groupId>
<artifactId>fwk-war</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
</dependencies>
</project>

En plus de la définition des dépendances, il faut préciser le comportement du goal war:inplace :
<!-- plugin WAR -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.0.2</version>
<executions>
<execution>
<id>inplace</id>
<phase>generate-sources</phase>
<goals>
<goal>inplace</goal>
</goals>
</execution>
</executions>

<configuration>
<warSourceDirectory>webapp</warSourceDirectory>
<dependentWarExcludes>
WEB-INF/web.xml,META-INF/**,WEB-INF/classes/**,WEB-INF/lib/**,WEB-INF/conf/**
</dependentWarExcludes>
<warSourceExcludes>/webapp/WEB-INF/lib/**</warSourceExcludes>
<useCache>false</useCache>
</configuration>
</plugin>

La complexité ensuite réside dans les ressources existants à la fois dans mon application web et à la fois dans mon framework war (par exemple, web.xml, struts-config.xml,...). Si j'execute la commande war:inplace, les ressources du framework war vont venir écraser les ressources existantes qui auraient été modifiées. Il faut alors mettre en place un système d'exclusion comme on peu le voir dans la configuration du plugin war :
<dependentWarExcludes>
WEB-INF/web.xml,META-INF/**,WEB-INF/classes/**,WEB-INF/lib/**,WEB-INF/conf/**
</dependentWarExcludes>

J'ai défini des dépendances au niveau de mon framework war. Je les récupère par transitivité dans le war de mon application web. Super! En revanche, l'utilisation du goals war:inplace rapatrie l'ensemble des dépendances transitives de mon framework war dans le dossier WEB-INF/lib de mon application web. Ce comportement me pose problème car en utilisant eclipse/sysdeo/tomcat ou eclipse/wtp/tomcat pour faire du développement en mode "exploded", la gestion du chargement des librairies est déléguées au plugin sysdeo ou WTP. La présence des librairies dans WEB-INF/lib pendant le développement perturbent le comportement des plugins sysdeo ou WTP.
Pour supprimer ces librairies génante en mode "exploded", j'ai utilisé le plugin ant-tun de maven et exécuté un delete... Je sais, ce n'est pas forcément très élégant mais ça à le mérite de fonctionner :

<!-- plugin ANT -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<delete dir="${basedir}/webapp/WEB-INF/lib" />
<delete dir="${basedir}/webapp/WEB-INF/classes" />
<delete dir="${basedir}/webapp/META-INF" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
L'ordre de déclaration des plugins dans le pom.xml de ma webapp à une importance. Il faut déclarer le plugin war avant le plugin ant car les goals des 2 plugins s'exécutent dans la même phase.

4 commentaires:

Thomas Recloux a dit…

Hello,

J'en étais arrivé à la même réflexion, mais il me semble qu'à l'époque les dépendances de type war ne ramenaient pas leurs propres dépendances.

Ce qui me gène avec cette solution c'est que l'on "pollue" les sources avec le contenu du war explosé, et quand le gestionnaire de source (clearcase) ne propose pas d'ignorer des fichiers/répertoires c'est lourd.

Autre solution que j'avais exploré : faire en sorte que le war "framework" soit décompressé dans un répertoire dédié, coté plugin war pas de soucis, par contre le plugin eclipse n'ajoute pas ce répertoire comme source et donc avec WTP, ca ne fonctionne pas.

Anonyme a dit…

Salut,

Je cherche à créer des dépendances entre WAR mais dans des projets Netbeans (sans Maven). Avez-vous une idée ?

Actuellement, il est impossible d'ajouter une dépendance de type web application à un projet Netbeans.

Merci !

Jérémy Sevellec a dit…

Hum désolé, je ne maitrise pas Netbeans...

Anonyme a dit…

Merci pour ta réponse,

J'ai migré ma web appli Netbeans pour en faire un projet maven.

J'ai scrupuleusement suivi ton explication, mais je n'arrive pas à appliquer la transitivité des dépendances dès lors que j'indique "war" comme type de dépendance.

As tu une idée de la cause du problème ?