mardi 17 juin 2008

Vista et Flavie

Quand vous êtes triste ou déprimé... n'oubliez pas de regarder cette (vieille) pub de Flavie Flament qui présente Windows Vista. Ensuite tout ira mieux pour vous!! Un grand moment de publicité :-)

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.