Developpez.com - Java
X

Choisissez d'abord la catégorieensuite la rubrique :


Utiliser Maven 2

Date de publication : 04/08/2008 , Date de mise à jour : 04/08/2008

Par Matthieu Lux (Tous les articles)
 

Cette documentation propose de faire un tour d'horizon de Maven 2 pour mieux le comprendre et l'utiliser. Maven est plutôt bien documenté même si on ne retrouve pas toujours l'information facilement, le document référence donc les pages proposant la documentation officiel sur chaque sujet. Le document fait référence à beaucoup de notions et de références qui pourront évolué dans le temps. Il ne sera donc pas toujours possible d'avoir toutes ces références à jour même si j'espere avoir le temps de faire les mises à jour nécessaire au fur et à mesure.
warning Le document est actuelement en cours de rédaction / relectures. Si vous avez des commentaires, merci de me les faire parvenir sur le forum : http://www.developpez.net/forums/d587280/java/communaute-java/contribuez/projets-java/cours-maven/ ou par mail : matthieu.lux at gmail dot com

               Version PDF   Version hors-ligne

1. La théorie de Maven
1.1. Philosophie
1.2. Installation et fonctionnement
1.3. Ce que Maven 2 apporte
2. Organisation des fichiers
3. Cycle de vie et goal Maven
3.1. Goals Maven
3.1.1. Définition
3.1.2. Localisation des goals
3.2. Cycle de vie et goals
4. Gestion des plugins Maven
4.1. Dans Maven, tout est plugin
4.2. Cartographie
4.2.1. Core
4.2.2. Packaging
4.2.3. Outils
4.2.4. Reporting
4.2.5. IDE
4.2.6. Tous les plugins
4.3. Configurer les plugins
5. Repository Maven
5.1. Définition d'un artifact
5.2. Repository Maven 2
5.3. Configurer des repositories
6. Gestion des dépendances du projet
6.1. Dépendances du projet
6.2. Installation du projet
7. Resources et filtrage
7.1. Resources
7.2. Filtrage
7.3. Stratégies et risques du filtrage
7.4. Stratégie de selection des ressources
8. Packaging
9. Integration avec Eclipse
9.1. External builder
9.1.1. Avantages
9.1.2. Inconvénients
9.2. m2Eclipse plugin
9.2.1. Avantages
9.2.2. Inconvénient
9.3. q4e
9.3.1. Avantages
9.3.2. Inconvénient
10. Integration avec Tomcat
10.1. Dans src/main/webapp : war:inplace
10.1. Avantages
10.1.1. Inconvénients
10.2. Dans target/<final-name> : war:exploded
11. Configuration du site
11.1. Structure
11.2. Contenu
11.3. Rapports
12. Heritage de pom
13. Intégration continue
13.1. Principes
13.2. Bénéfices
13.3. Intégration continue avec Maven
14. Archetypes
14.1. Utiliser un Archetype Maven
14.2. Créer un Archetype Maven
15. Projets modulaires
15.1. Définition
15.2. Utilisation
15.3. Intérêts et développements


1. La théorie de Maven


1.1. Philosophie

Que ce soit avec les Makefile ou les scripts Ant, la compilation d'un projet était réalisée via le scriptage des differentes étapes de la vie du projet. Même avec les directives très abouties de Ant, le script redéfinissait pour chaque projet des directives ressemblante à : "compiler les fichiers sources du répertoire src dans le repertoire classes".

Maven propose de renverser le problème. On ne va plus définir les opérations à faire, on va lui décrire le projet. A partir de ces information, c'est Maven qui saura et appliquera que la compilation pars des sources vers un répertoire de travail.

Maven propose une configuration par défaut très complète qui permet une standardisation de la structure des projets Java. Néamoins Maven permet toujours de surcharger les configurations pour s'adapter au plus de situations.

info La philosophie de Maven

1.2. Installation et fonctionnement

Pour installer Maven : le plus simple est de suivre la procédure officielle Télécharger Maven . Il faut surtout retenir que plusieurs variables d'environnements sont à positionner : JAVA_HOME si ce n'est pas déjà fait, M2_HOME et le plus important, avoir le répertoire bin de Maven dans le PATH afin de pouvoir lancer les commandes Maven dans la console.

Pour utiliser Maven : il faut se positionner en ligne de commande dans le répertoire du projet. Avec la commande mvn et les goals decrit plus bas, il sera alors possible de réaliser toutes les opérations necessaires sur le projet.

Un projet qui utilise Maven contient simplement un fichier pom.xml qui représente la configuration du projet pour Maven. Toutes les informations pour le projet sont à renseigner dans ce fichier.

La grande différence par rapport à un fichier build.xml Ant est que le fichier pom.xml décrit le projet pour que Maven sache le manipuler alors qu'un build.xml decrit entierement la procédure pour réaliser une opération technique.

info Les bases du pom.xml
idea Pour créer votre premier pom.xml, pratiquement tous les champs ont une valeur par défaut, ils sont dont tous optionnels, voici ce que pourrait être un fichier pom.xml minimal :

	<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>
		<groupId>com.developpez</groupId>
		<artifactId>cours-maven-example</artifactId>
		<packaging>jar</packaging>
		<name>Projet d'exemple pour le cours Maven</name>
		<version>1.0</version>
		
	</project>
				

1.3. Ce que Maven 2 apporte

Grâce à la définition du projet dans le pom.xml, Maven 2 va être capable de gérer toute la vie du projet. Il ne s'agit pas seulement de la compilation mais aussi du packaging de l'application (faire une archive War ou Ear n'est pas toujours évident), la gestion des dépendances, la génération des rapports de suivis des développements (checkstyles, test unitaires...) et même le déploiement de l'application sur un environnement d'execution.

Généralisé sur une grande majorité des projets Java Open Source (Spring, Hibernate, Struts...) Maven 2 permet d'uniformiser la gestion d'un projet Java et permet d'utiliser des outils qui permettent l'industrialisation du développement via la génération automatique des rapports ou les systèmes d'intégration continue.


2. Organisation des fichiers

Maven propose une structure de fichier complète. Il s'agit de la configuration par défaut mais elle est surchargeable.

Structure des répertoires
src/main/java Contient les sources Java de l'application
src/main/resources Contient les resources de l'application
src/main/webapp Contient les fichiers de l'application Web
src/test/java Contient les sources Java pour les tests unitaires
src/site Contient les fichiers pour le site
target Répertoire de destination de tous les traitements Maven
info La structure des fichiers par défaut
Le tableau ci dessus de présente que les répertoire les plus courant. Aucun de ces répertoire n'est indispensable il est tout à fait possible de ne créer par exemple que le répertoire src/main/java pour commancer un projet.

Tout configurer ou laisser par défaut ?

Laisser la configuration par défaut apporte la standardisation des projets. Ce n'est pas une notion à négliger. Le passage d'une grande majorité des projets Java à Maven 2 apporte une grande lisibilité sur les projets. Cela permet de savoir que même si on ouvre les sources de Spring ou d'Hibernate, on saura tout de suite que les sources se trouve dans src/main/java, les tests unitaires dans src/test/java etc..

idea En apportant une première classe Java au projet définit avec le pom.xml créé précédemment, la structure du projet ressemble alors à ceci :

	+- cours-maven-example/
	   +- src
	      +- main
	         +- java
	            +- Test.java
	   +- pom.xml
			
idea Il est alors déjà possible d'utiliser Maven pour compiler les sources du projet. Il faut pour cela utiliser la commande mvn compile (en se positionnant dans le répertoire du projet). Le résultat sera le suivant :

	~/cours-maven-example$ mvn compile
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [compile]
	[INFO] ------------------------------------------------------------------------
	[INFO] [resources:resources]
	[INFO] Using default encoding to copy filtered resources.
	[INFO] [compiler:compile]
	[INFO] Compiling 1 source file to ~\cours-maven-example\target\classes
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 3 seconds
	[INFO] Finished at: Tue Aug 12 11:38:35 CEST 2008
	[INFO] Final Memory: 2M/9M
	[INFO] ------------------------------------------------------------------------
			

	+- cours-maven-example/
	   +- src
	      +- main
	         +- java
	            +- Test.java
	   +- target
	      +- classes
	         +- Test.class
	   +- pom.xml
			

3. Cycle de vie et goal Maven

Maven a pour but de gérer tout le cycle de vie de l'application. Il définit pour cela une liste d'étape ordonnées qui sont pour lui le cycle de vie par défaut d'un projet. Comme il définit aussi le concept de type de projet (jar, war...) un cycle de vie plus précis est définit pour chaque type de projet.

Le cycle de vie par défaut définit les étapes suivantes :

On remarquera que Maven gère des concepts qui ne le limite pas à la manipulations de projets Java. Il est tout de même extremmement peut utiliser en dehors du monde Java.


3.1. Goals Maven


3.1.1. Définition

Maven s'execute sous forme de goal. Un goal est une tâche précise que Maven est capable de réaliser à partir des informatios qu'il pourra trouver dans le fichier pom.xml.

A partir de la comprehension qu'il a du projet, il est capable d'executer énormément d'opération dessus, chaque opération correspond à un goal.

Pour lancer un goal Maven sur un projet, il faut se placer à la racine du projet et executer la commande :

	mvn <nom du goal>
					
Il est possible d'enchainer deux ou plusieurs goal avec la commande :

	mvn <nom du goal 1> <nom du goal 2> <nom du goal 3>
					

3.1.2. Localisation des goals

Tous les goals se trouvent dans des plugins Maven. Pour executer un goal, Maven va donc commencer par résoudre le nom du goal pour en déduire le plugin dans lequel il se trouve et le télécharger.

Tous les goals maven s'ecrivent de la facon suivante :

	<nom du plugin>:<nom du goal>
					
idea Dans notre projet précédemment créer, on peut lancer le goal compile du plugin compiler :

	~/cours-maven-example$ mvn compiler:compile
	[INFO] Scanning for projects...
	[INFO] Searching repository for plugin with prefix: 'compiler'.
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [compiler:compile]
	[INFO] ------------------------------------------------------------------------
	[INFO] [compiler:compile]
	[INFO] Compiling 1 source file to ~\cours-maven-example\target\classes
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 2 seconds
	[INFO] Finished at: Tue Aug 12 14:33:40 CEST 2008
	[INFO] Final Memory: 2M/5M
	[INFO] ------------------------------------------------------------------------
				

3.2. Cycle de vie et goals

Chaque type de projet définit un ou plusieurs goal par défaut associés aux étapes du cycle de vie. Maven gère alors la progression dans le cycle de vie. Lorsque l'on traite un goal associé à une étape du cycle de vie, Maven lancera tous les goals associés aux étapes précédentes.

Il est possible de lancer la commande mvn avec comme paramètre une étape du cycle de vie.

	mvn <étape du cycle de vie>
				
Maven exécutera dans l'ordre tous les goals correspondants à chaque étape du cycle précédent celle qui a été demandée.

C'est ce mécanisme qui permet d'utiliser des commandes tu type :

	mvn compile
				
ou

	mvn install
				
Ce ne sont pas des noms de goal mais des nom d'étapes du cycle de vie auxquels sont associés des goals : compiler:compile pour le premier cas et war:war qui est executé pour un install dans un projet de type war (après avoir parcouru les étapes précédente dans le cycle de vie).

idea Si on utilise une partie importante du cycle de vie par défaut d'un projet Jar, on peut identifier la liste des goals que Maven utilise : [resources:resources], [compiler:compile], [compiler:testCompile], [surefire:test], [jar:jar], [install:install]

	~/cours-maven-example$ mvn install
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [install]
	[INFO] ------------------------------------------------------------------------
	[INFO] [resources:resources]
	[INFO] Using default encoding to copy filtered resources.
	[INFO] [compiler:compile]
	[INFO] Compiling 1 source file to ~\cours-maven-example\target\classes
	[INFO] [resources:testResources]
	[INFO] Using default encoding to copy filtered resources.
	[INFO] [compiler:testCompile]
	[INFO] No sources to compile
	[INFO] [surefire:test]
	[INFO] No tests to run.
	[INFO] [jar:jar]
	[INFO] Building jar: ~\cours-maven-example\target\cours-maven-example-1.0.jar
	[INFO] [install:install]
	[INFO] Installing ~\cours-maven-example\target\cours-maven-example-1.0.jar to
		~\.m2\repository\com\developpez\cours-maven-example\1.0\cours-maven-example-1.0.jar
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 9 seconds
	[INFO] Finished at: Tue Aug 12 14:36:05 CEST 2008
	[INFO] Final Memory: 8M/14M
	[INFO] ------------------------------------------------------------------------
				
Le cycle clean est une exception. il ne fait pas parti directement du cycle de vie mais il peut toujours être utilisé. Il permet de nettoyer (supprimer) le repertoire de travail de Maven. Il fait reference au goal clean du plugin clean.

ideaSur notre projet :

	~/cours-maven-example$ mvn clean
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [clean]
	[INFO] ------------------------------------------------------------------------
	[INFO] [clean:clean]
	[INFO] Deleting directory ~\cours-maven-example\target
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 2 seconds
	[INFO] Finished at: Tue Aug 12 14:51:24 CEST 2008
	[INFO] Final Memory: 3M/5M
	[INFO] ------------------------------------------------------------------------
				

4. Gestion des plugins Maven


4.1. Dans Maven, tout est plugin

Quand on télécharge Maven la première fois, on ne télécharge pratiquement que le moteur qui sert à télécharger des plugins. Tous les goals Maven sont dans des plugins même les plus indispensables comme le plugin compiler.

Il faut donc s'attendre à voir Maven télécharger énormémement de plugins lors de la première execution d'un goal.


4.2. Cartographie


4.2.1. Core


4.2.2. Packaging


4.2.3. Outils


4.2.4. Reporting


4.2.5. IDE


4.2.6. Tous les plugins


4.3. Configurer les plugins

Il est possible de configurer les plugins utilisés dans le pom.xml :

	<build>
		<plugins>
			...
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
			...
		</plugins>
	</build>
				
En rappelant le groupId et l'artifactId du plugin, on identifie de façon certaine le plugin. Il est alors possible de spécifier des paramètres génériques ou des paramètres spécifiques au plugin.

Spécifier la version peut être important. Tous les plugins peuvent avoir des mises à jour et par défaut Maven vérifiera une fois par jour si une nouvelle version est disponible. Il arrive que les meilleurs plugins sortent des versions buggé, et sans fixer la version, le projet peut poser des problèmes à la compilation d'un jour sur l'autre parce que la nouvelle version a été téléchargée.

Dans le meilleur des scénaris, grâce à la dépendance entre pom étudié ci dessous, un projet héritera d'un pom générique qui sélectionne au mieux les versions de chaque plugin.

Pour les configurations spécifiques au plugin, elles se positionnent dans la balise <configuration>. Chaque paramètre peut alors être définit de la façon suivante : <nom du paramètre>valeur</nom du paramètre>

Le plus judicieux est de toujours se référer à la page de rapport du plugin pour savoir quels paramètres peuvent lui être précisés. Pour trouver un plugin maven, la recherche Google "maven <nom du plugin> plugin" répondra pratiquement toujours.

Vous trouverez ensuite toujours sur le site du plugin la page : "Project Reports/Plugin documentation" . Il s'agit d'un rapport automatique de Maven.

info La page d'accueil listera toujours les goal du plugin.
Cliquer sur un goal proposera la liste des paramètres qui peuvent lui être passés.
idea Pour s'assurer de compiler notre projet avec Java 5, il faut donc enrichir le fichier pom.xml de cette façon :

	<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>
		<groupId>com.developpez</groupId>
		<artifactId>cours-maven-example</artifactId>
		<packaging>jar</packaging>
		<name>Projet d'exemple pour le cours Maven</name>
		<version>1.0</version>
		
		<build>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.0.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
			</plugins>
		</build>
		
	</project>
				

5. Repository Maven


5.1. Définition d'un artifact

Tous les artifacts gérés par Maven sont identifié par 4 informations :


5.2. Repository Maven 2

Maven 2 définit une structure de fichiers qui permet de publier les artifacts. Cette structure de fichiers est souvent publier sur le Web. En connaissant simplement la racine, Maven peut alors chercher sur le site tout ce dont il a besoin. Tous les repository Maven ne contiennent pas forcement tous les artifacts.

Que ce soit pour les plugins Maven que l'on a vu précédemment ou pour les dépendances ci desous, Maven gère un localrepository là ou il s'execute. Il y recopie tout ce qu'il télécharge.

Le localrepository se trouve toujours par défaut dans le répertoire ~/.m2/repository (Sous windows, cela donne : C:\Document And Settings\<User>\.m2\repository). Aller parcourir ce repertoire permet de se faire une idée de la façon dont Maven gère ses fichiers. Il n'y par contre normalement jamais besoin d'aller modifier directement les fichiers dans ce répertoire.

Le principe de Maven est de commencer à vérifier dans son localrepository la disponibilité d'un projet avant de le chercher sur Internet. Ainsi il n'y a que la première execution d'un nouveau goal ou d'une nouvelle résolution de dépendance qui prends du temps. La seconde fois, les packets seront déjà disponibles en local.


5.3. Configurer des repositories

Maven utilise toujours par défaut un serveur central qui contient énormément de jar et la pratiquement tous les plugins Maven.

Pour ajouter des repository, il faut ajouter dans le pom.xml :

	<repositories>
		<repository>
			<id>repo</id>
			<name>repo name</name>
			<url>url</url>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>plugin repo</id>
			<name>plugin repo name</name>
			<url>url</url>
		</pluginRepository>
	</pluginRepositories>
				
Comme on peut le voir, Maven differencie les repository qui contiennent les plugins et ceux qui contiennent les dépendances.

idea Le cycle install déploie le projet dans le repository local. Après avoir lancer mvn install , on peut aller vérifier que notre projet à été copié dans le repository local :

	+- ~
	   +- .m2
	      +- repository
	         +- com
	            +- developpez
	               +- cours-maven-example
	                  +- 1.0
	                     +- cours-maven-example-1.0.jar
	                     +- cours-maven-example-1.0.pom
			

6. Gestion des dépendances du projet

Plutôt que de copier explicitement tous les jar nécessaires pour un projet, Maven propose de le définir par configuration dans le pom.xml. C'est ensuite le plugin Maven de gestion de dépendances qui ira sur internet télécharger les jar indiqués.


6.1. Dépendances du projet

La configuration à rajouter dans le fichier pom.xml est la suivante :

	<dependencies>
		...
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>2.0.5</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		...
	</dependencies>
					
Une très bonne proportions des jars sont aujourd'hui disponible sur les repository Maven. Pour les trouver, le plus simple est d'utiliser le Google des packets Maven : http://www.mvnrepository.com/

Les seuls paramètres obligatoirs sont le groupId et l'artifactId.

Il est extremmement recommandé de toujours spécifier la version. Sans cela Maven utilisera toujours la dernière version en date. Il est alors tout à fait possible que lors d'une mise à jour d'une dépendance qui publierait une nouvelle version alpha, elle soit automatiquement utilisée et empeche le projet de tourner alors qu'aucune modification n'ait été aportée.

Le type n'est pratiquement jamais nécessaire sauf dans des cas particuliers.

Le paramètre scope est par contre à prendre en compte. Les différentes valeurs à prendre en compte sont les suivantes :

On utilisera souvent le scope provided lorsqu'on code avec les servlet. Effectivement, les jars sont fournis automatiquement par Tomcat mais il est nécessaire de les avoirs pour la compilation.

info Gestion des dépendances
idea Par exemple, si on veut utiliser log4j dans notre projet, il faut enrichir le pom.xml avec la dépendance :

	<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>
		<groupId>com.developpez</groupId>
		<artifactId>cours-maven-example</artifactId>
		<packaging>jar</packaging>
		<name>Projet d'exemple pour le cours Maven</name>
		<version>1.0</version>
		
		<dependencies>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>1.2.13</version>
			</dependency>
		</dependencies>
		
		<build>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.0.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
			</plugins>
		</build>
		
	</project>
				
idea On peut alors rajouter dans le code Java l'utilisation de la dépendance.

	package com.developpez;
	
	import org.apache.log4j.Logger;
	
	public class Test {
	    Logger logger = Logger.getLogger(this.getClass());
	    
	    public void main(String[] args) {
	        logger.debug("Hello, World");
	    }
	}
				
idea Enfin, lors de la compilation, la dépendance sera automatiquement résolue :

	~/cours-maven-example$ mvn compile
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [compile]
	[INFO] ------------------------------------------------------------------------
	[INFO] [resources:resources]
	[INFO] Using default encoding to copy filtered resources.
	Downloading: http://repo1.maven.org/maven2/log4j/log4j/1.2.13/log4j-1.2.13.pom
	389b downloaded
	Downloading: http://repo1.maven.org/maven2/log4j/log4j/1.2.13/log4j-1.2.13.jar
	349K downloaded
	[INFO] [compiler:compile]
	[INFO] Compiling 1 source file to ~\cours-maven-example\target\classes
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 6 seconds
	[INFO] Finished at: Tue Aug 12 15:38:23 CEST 2008
	[INFO] Final Memory: 3M/8M
	[INFO] ------------------------------------------------------------------------
				

6.2. Installation du projet

Tous les projets sont définits comme des paquets Maven. Il est donc possible de publier ces paquets.

Tout d'abord pour publier dans le localrepository, il suffit d'utiliser le goal install :

	mvn install
				
Pour l'installer sur un repository externe, il faut lui configurer dans le pom.xml la gestion de la distribution :

	<distributionManagement>
		<repository>
			<id>ganesh3-repo</id>
			<name>Ganesh Repository for Maven2</name>
			<url>file://${deploy.repository}</url>
		</repository>
	</distributionManagement>
				
L'URL peut être exprimé sur beaucoup de protocoles, ici on voit file, mais cela peut être également scp, http (à condition qu'il y ait un webdav) etc...


7. Resources et filtrage


7.1. Resources

Dans un projet Maven, src/main/java correspond au répertoire principal dans lequel doit se trouver toutes les sources applicatives du projet. Néammoins il est très courant d'avoir des fichiers de configuration à positionner dans le classpath.

Le répertoire src/main/resources répond à cette attente. Il s'agit d'un autre répertoire qui sera compilé et ajouté au classpath. Son rôle est de contenir l'ensemble des fichiers de configuration du projet.

Pour modifier le répertoire de resources ou pour en ajouter d'autres, il faut rajouter dans le pom :

	<build>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
			</resource>
		</resources>
	</build>
				

7.2. Filtrage

Mais les resources n'ont pas pour seul objectif de séparer les fichiers de conf pour amméliorer la visibilité. Même si ce n'est activé par défaut, le principal atout est de pouvoir réaliser du filtrage sur ces fichiers.

Filtrer les fichiers correspond à remplacer à l'intérieur de tous les fichiers et à chaque compilation tous les ${properties} par leur valeur. Pour activer le filtrage sur un répertoire de resources, il faut ajouter le code suivant :

	<build>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>
	</build>
				
Par défaut, les properties qui seront utilisés pour le filtrage sont les properties actifs dans Maven, il y en a plusieurs positionnées par défaut tel que pom.name, pom.version...

Il est possible d'ajouter un fichier de properties qui sera utilisé pour le filtrage. Ils sont alors positionné par convention dans le répertoire src/main/filters et se configure avec le code suivant :

	<build>
		<filters>
			<filter>src/main/filters/filter.properties</filter>
		</filters>
	</build>
				
info Gestion des resources

7.3. Stratégies et risques du filtrage

Le filtrage a été fait pour gérer les configuration par environnements pour les projets. Il y a plusieurs stratégies possible pour gérer les environnements :

Quelque soit la solution utilisée, cela permet de sélectionner l'environnement pour lequel on veut configurer l'application et les fichiers de configuration seront automatiquement positionnés avec les bonnes valeurs.

Le risque de cette méthode réside dans la phase de développement. Si dans la phase de développement, la gestion de la compilation n'est pas gérée par Maven, le filtrage ne sera pas effectué. Comme les fichiers du répertoire resources seront remplis de ${bdd.url} (par exemple) ils ne pourront être utilisés directement.

L'utilisation des filtres lie donc le développeur avec le mécanisme de compilation de Maven.


7.4. Stratégie de selection des ressources

Il peut être interessant de choisir un répertoire de ressources avec un nom dépendant de l'environnement :

	<build>
		<resources>
			<resource>
				<directory>src/main/resources-${env}</directory>
			</resource>
		</resources>
	</build>
				
L'avantage est que si l'IDE ne gère pas le filtrage, il est possible de lui donner le répertoire de ressources à utiliser en local, il ne connaitra pas les ressources pour les autres environnements mais cela ne l'empechera pas de fonctionner correctement.

Cela nécessite par contre de dupliquer tous les fichiers de configuration présent dans ces répertoires pour en avoir une version dans chaque répertoire.

idea Dans notre projet, nous allons rajouter en ressource le fichier de configuration log4j.properties pour qu'il soit filtré en fonction de l'environnement.
Pour cela, on précise que le répertoire resources doit être filtré, que le fichier de filtrage est ${env}.properties.
Afin de donner une valeur par défaut à la variable env, on rajoute la balise properties au bas du pom. Si une valeur est donné à la variable env par la commande "-Denv=xxx" elle sera prioritaire.

	<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>
		<groupId>com.developpez</groupId>
		<artifactId>cours-maven-example</artifactId>
		<packaging>jar</packaging>
		<name>Projet d'exemple pour le cours Maven</name>
		<version>1.0</version>
		
		<dependencies>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>1.2.13</version>
			</dependency>
		</dependencies>
		
		<build>
			<resources>
				<resource>
					<directory>src/main/resources</directory>
					<filtering>true</filtering>
				</resource>
			</resources>
			<filters>
				<filter>src/main/filters/${env}.properties</filter>
			</filters>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.0.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
			</plugins>
		</build>
		
		<properties>
			<env>LOCAL</env>
		</properties>
		
	</project>
			
idea Dans les fichiers, on rajoute le fichier src/main/resources/log4j.properties ainsi :

log4j.rootLogger=${log.level}, CONSOLE_APP

log4j.appender.CONSOLE_APP=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE_APP.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE_APP.layout.ConversionPattern= %d{dd-MM-yyyy HH:mm:ss:SSS} %-4r %-5p %c %x - %m%n
			
idea On crée les fichiers src/main/filters/LOCAL.properties et src/main/filters/PROD.properties dans lesquels ont définit la clé log.level dans le premier à DEBUG , dans le second à WARN .
Après compilation par mvn compile , on trouvera le fichier target/classes/log4.properties

log4j.rootLogger=DEBUG, CONSOLE_APP

log4j.appender.CONSOLE_APP=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE_APP.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE_APP.layout.ConversionPattern= %d{dd-MM-yyyy HH:mm:ss:SSS} %-4r %-5p %c %x - %m%n
			
idea Après compilation par mvn compile -Denv=PROD , on trouvera le fichier target/classes/log4.properties

log4j.rootLogger=WARN, CONSOLE_APP

log4j.appender.CONSOLE_APP=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE_APP.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE_APP.layout.ConversionPattern= %d{dd-MM-yyyy HH:mm:ss:SSS} %-4r %-5p %c %x - %m%n
			

8. Packaging

Le packaging fait partie intégrante du cycle de vie d'un projet Maven. Il est toujours nécessaire de transformer un projet en une archives uniques afin de pouvoir le publier dans un repository.

Maven est construit à partir de tous les standards de SUN, le packaging de maven en revient donc toujours à construire l'archives suivant ces standards.

La commande pour avoir le packaging de son projet est :

	mvn package
			
Bien évidemment, Maven prends en compte le type du projet et fera un .jar pour une librairie, un .war pour une application Web etc...

idea Dans notre projet Jar, le cycle package est implémenté par le goal jar:jar. On peut voir dans l'execution de la commande que Maven prépare automatiquement un jar respectant les normes sur l'appel du goal jar:jar.

	~/cours-maven-example$ mvn package
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [package]
	[INFO] ------------------------------------------------------------------------
	[INFO] [resources:resources]
	[INFO] Using default encoding to copy filtered resources.
	[INFO] [compiler:compile]
	[INFO] Compiling 1 source file to d:\workspace\IL\cours-maven-example\target\classes
	[INFO] [resources:testResources]
	[INFO] Using default encoding to copy filtered resources.
	[INFO] [compiler:testCompile]
	[INFO] No sources to compile
	[INFO] [surefire:test]
	[INFO] No tests to run.
	[INFO] [jar:jar]
	[INFO] Building jar: ~\cours-maven-example\target\cours-maven-example-1.0.jar
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 6 seconds
	[INFO] Finished at: Tue Aug 12 16:14:29 CEST 2008
	[INFO] Final Memory: 7M/12M
	[INFO] ------------------------------------------------------------------------
			

9. Integration avec Eclipse

Maven a pour but de gérer le projet pendant tout son cycle de vie. Depuis le poste de développement jusqu'a la livraison en production (du moins sur le papier).

Eclipse permet à l'utilisateur d'agir efficacement sur le projet, pour cela il a besoin de le comprendre en détail.

Conclusion, les deux outils utilisent une configuration complète et indépendante du projet.

"Intégrer" des deux outils correspond alors à faire communiquer les configurations de Maven et d'Eclipse. La partie critique correspond souvent à fournir à Eclipse le classpath qui correspond à la gestion des dépendances de Maven.

Plusieurs stratégies qui peuvent être mise en place pour cela. Les 3 qui sont présentées ici sont viables, elles présentent chacun leurs avantages et inconvénient.


9.1. External builder

Maven propose son plugin d'intégration pour Eclipse. Sa principale compétence est d'être capable d'écrire la configuration Eclipse à partir de son pom.xml.

	mvn eclipse:eclipse
			
Ce mécanisme est sur et abouti. La configuration Eclipse générée par Maven est toujours valide et lorsque la configuration existe déjà, Maven se contente de la compléter pour la bonne marche du projet. Noter que l'utilisation du plugin peut être afinée notamment pour activer la prise en charge de WTP.

	mvn eclipse:eclipse -Dwtpversion=1.5
			
Pour avoir tous les détails, se référer au site du plugin : maven-eclipse-plugin

Pour automatiser les développement, il faut alors configurer le lancement des commandes Maven dans les "builders" Eclipse. Pour cela, il faut aller dans les propriété du projet, puis builders. Ajouter un nouveau builder externe avec la configuration suivante :

On associera le plus souvent le déclenchement du builder uniquement sur les builds manuel afin de ne pas avoir Maven qui se déclenche dès qu'on sauvegarde un fichier.

Avec ce mécanisme, le plus pratique est de créer le builder suivant :

Avec ce builder, les dépendances du projets seront toujours à jour sous réserve d'avoir demandé explicitement un build.

info Maven Eclipse Plugin
idea Pour notre projet, utiliser le maven plugin eclipse donner cela :

	~/cours-maven-example$ mvn eclipse:eclipse
	[INFO] Scanning for projects...
	[INFO] Searching repository for plugin with prefix: 'eclipse'.
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [eclipse:eclipse]
	[INFO] ------------------------------------------------------------------------
	[INFO] Preparing eclipse:eclipse
	[INFO] No goals needed for project - skipping
	[INFO] [eclipse:eclipse]
	[INFO] Using source status cache: d:\workspace\IL\cours-maven-example\target\mvn-eclipse-cache.properties
	[INFO] Wrote settings to D:\workspace\IL\cours-maven-example\.settings\org.eclipse.jdt.core.prefs
	[INFO] Wrote Eclipse project for "cours-maven-example" to d:\workspace\IL\cours-maven-example.
	[INFO] 
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 3 seconds
	[INFO] Finished at: Tue Aug 12 16:18:08 CEST 2008
	[INFO] Final Memory: 4M/8M
	[INFO] ------------------------------------------------------------------------
				

9.1.1. Avantages

Cette méthode permet de gérer précisément les directives Maven à utiliser et leur déclenchement.


9.1.2. Inconvénients

A force d'édition des fichiers de configuration d'Eclipse par Maven, l'interface a tendance à perdre les pédales. Les fichiers de configuration ne sont jamais altéré mais Eclipse a parfois besoin de plusieurs "F5" pour retrouver sa configuration.


9.2. m2Eclipse plugin

Le plugin m2Eclipse est le plus aboutis des plugins Maven pour Eclipse à l'heure actuelle (juillet 2008). Ses principales fonctionnalités sont de gérer une librairie dynamique représentant les dépendances de Maven et de fournir un builder Maven simplifié.

A noter qu'il est également intégré dans le plugin eclipse de Maven, aussi vous pouvez utiliser

	mvn eclipse:m2eclipse
				
Pour pousser l'intégration jusqu'au projet web lançable avec Eclipse WTP, vous pouvez utiliser

	mvn eclipse:m2eclipse -Dwtpversion=1.5
				
m2eclipse propose maintenant une interface complète pour importer un projet Maven dans Eclipse. Soit à partir d'un système de gestion de ressource :

Soit à partir du projet sur le disque dur :

info m2Eclipse
idea Pour notre projet, le projet avec m2eclipse se présentera ainsi :

9.2.1. Avantages

Permet de s'abstraire du builder eclipse:eclipse et des problématiques de rechargement de la configuration Eclipse.


9.2.2. Inconvénient

m2eclipse a récemment essuyer ses principales faiblesses et se positionne comme le projet qui fera un jour partie intégrante d'Eclipse.

Il n'a de faiblesse qu'en cherchant les fonctionnalités avancées de Maven tel que les filtrages même s'il propose maintenant des solutions ou la gestion des projets multi-modules.


9.3. q4e

q4e est le principal concurent de m2eclipse. La version 0.7 actuellement disponible est déjà très stable. Projet q4e

En terme de service, il propose la gestion dynamique des dépendances Maven tout comme m2Eclipse. Il propose également plusieurs interfaces dont une pour lancer des directives.

info q4e

9.3.1. Avantages

Il est déjà opérationnel et se montre très prometteur.


9.3.2. Inconvénient

Le fonctionnel semble encore trop limité pour les projets utilisant des fonctionnalités avancées de Maven.


10. Integration avec Tomcat

Par défaut Maven gère les fichiers sources dans le répertoire src et les fichiers compilé dans le répertoire target. Et ce, même si la compilation ne fournis pas d'autre valeur ajoutée que la recopie du fichier.

La question du fonctionnement avec le développement sous Tomcat se pose alors. On a l'habitude de pouvoir modifier directement les fichiers utilisés par Tomcat ce qui permet de ne pas le redémarrer pour tester les modifications (du moins pour les fichiers statiques).

On démarre toujours Tomcat dans un répertoire webapp racine. La question est alors de savoir si on démarre tomcat dans le répertoire src/main/webapp ou target/<final-name>.


10.1. Dans src/main/webapp : war:inplace

Cela va un peu à l'encontre des grands principes de Maven. Si on démarre Tomcat dans le répertoire src, cela veut dire qu'il faudra ajouter dans src/main/webapp/WEB-INF/classes les fichiers compilés et dans src/main/webapp/WEB-INF/lib les dépendances.

La commande war:inplace réalisera cette opération automatiquement. En configurant Eclipse pour positionner sa sortie de compilatation dans le répertoire src/main/webapp/WEB-INF/classes, tout fonctionnera correctement.

Cette solution est à privilégier dès qu'elle est possible car elle apporte les meilleurs possibilité aux developpeurs. Malheureusement certaines limitations la rende innutilisable dans certains cas.


10.1. Avantages

C'est une solution très pratique car après une initialisation par la commande war:inplace, il est possible de développer avec Tomcat sans utiliser Maven et en profitant de toutes les modifications dans Tomcat intantanément.


10.1.1. Inconvénients


10.2. Dans target/<final-name> : war:exploded

La propriété final name dans maven correspond au nom du package à utiliser. Il se configure comme ceci :

	<build>
		<final-name>package-name</final-name>
		...
	</build>
				
La commande war:exploded va créer un répertoire target/<final-name> qui contiendra le war de l'application sans réaliser l'archive.

En configurant Tomcat pour démarrer dans ce répertoire, il utilisera les fichiers compilés par Maven. L'avantage est que l'on reste entièrement dans le cadre de Maven, pas d'entorses au concept : src d'un côté, fichiers compilés de l'autre. On profite de tous les mécanismes de Maven : filtrage, projets modulaire, dépendances des fichiers de la webapp...

L'inconvénient est qu'il faut passer par Maven pour toutes modification des fichiers. Cette opération peut être fastidieuse.


11. Configuration du site

Maven propose de générer un site présentant le projet. Toujours fidèle à ses principes, Maven pourra générer un site minimal même sans disposer de configuration spécifique. Le commande à utiliser est la suivante :

mvn site
			
(ou)

mvn site:site
			
Le site est alors générer dans le respertoire target/site. Une fois habituer à ce genre de site, vous reconnaitrait plusieurs sites officiels de grands frameworks générer par ce moyen : Tapestry , Struts , EhCache ou bien sur Maven lui même.

Un des gros atouts de cette fonctionnalité est de permettre la regénération automatique et fréquente du site présentant la documentation ainsi que les rapports du type JavaDoc ou tests unitaires. Le plus souvent, avec l'utilisation de systèmes d'intégration continue, la génération du site est configuré pour être lancé à chaque build afin de pouvoir suivre les rapports au fur et à mesure.


11.1. Structure

info Les bases de la gestion du site Maven sont décrit ici.
Par défaut, Maven va créer quelques pages présentant les informations présente dans le pom (si elles y sont) comme la description générale, la gestion des sources ou l'outil de ticketing...

Les fichiers pour le site seront à déposer dans le répertoire src/site prévu à cet effet. On l'organisera alors ainsi :

	+- src/
	   +- site/
	      +- apt/
	      |  +- index.apt
	      |
	      +- xdoc/
	      |  +- other.xml
	      |
	      +- fml/
	      |  +- general.fml
	      |  +- faq.fml
	      |
	      +- site.xml
				
Le fichier site.xml permet de gerer la structure du site et principalement le menu, se référer à la documentation pour la syntaxe.

Il y a ensuite deux fonctionnalités principales pour enrichir le contenu du site : rajouter du contenu, et rajouter des rapports.


11.2. Contenu

Il est possible de rajouter des pages de contenu dans plusieurs format différents :

Les fichiers pour chaque format doivent être positionner dans le répertoire correspondant. Dans le site généré, une page ecrite au format apt dans le fichier src/site/apt/toto/toto.apt sera généré dans target/site/toto/toto.html et c'est ainsi pour tous les types de fichiers.


11.3. Rapports

Certains plugins Maven proposent des rapport en plus de goals. Certains plugins ne proposent d'ailleur que des rapports. A la génération du site, Maven executera tous les rapports configurés pour les calculer.

Pour ajouter un rapport dans le site Maven, il faut rajouter dans le pom une configuration de ce type :

	<reporting>
		<plugins>
			...
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-project-info-reports-plugin</artifactId>
				<version>2.0.1</version>
			</plugin>
			...
		</plugins>
	</reporting>
				
En fait, le site par défaut contient justement le rapport du plugin maven-project-info-reports-plugin

Les plugins les plus courant proposant des rapports sont les suivants :

idea Pour générer un site qui propose quelques informations, nous allons enrichir le pom.xml avec une petite description et l'activation du rapport Javadoc.
Après la commande mvn site , le site sera disponible dans target/site/index.html

	<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>
		<groupId>com.developpez</groupId>
		<artifactId>cours-maven-example</artifactId>
		<packaging>jar</packaging>
		<name>Projet d'exemple pour le cours Maven</name>
		<description>Projet de démonstration des fonctionnalités de Maven</description>
		<version>1.0</version>
		
		<dependencies>
			<dependency>
				<groupId>log4j</groupId>
				<artifactId>log4j</artifactId>
				<version>1.2.13</version>
			</dependency>
		</dependencies>
		
		<build>
			<resources>
				<resource>
					<directory>src/main/resources</directory>
					<filtering>true</filtering>
				</resource>
			</resources>
			<filters>
				<filter>src/main/filters/${env}.properties</filter>
			</filters>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.0.2</version>
					<configuration>
						<source>1.5</source>
						<target>1.5</target>
					</configuration>
				</plugin>
			</plugins>
		</build>
		
		<reporting>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-javadoc-plugin</artifactId>
				</plugin>
			</plugins>
		</reporting>
		
		<properties>
			<env>LOCAL</env>
		</properties>
		
	</project>
			

	~/cours-maven-example$ mvn site
	[INFO] Scanning for projects...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO]    task-segment: [site]
	[INFO] ------------------------------------------------------------------------
	...
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO] ------------------------------------------------------------------------
	[INFO] No goals needed for project - skipping
	[INFO] Preparing javadoc:test-javadoc
	[INFO] ------------------------------------------------------------------------
	[INFO] Building Projet d'exemple pour le cours Maven
	[INFO] ------------------------------------------------------------------------
	[INFO] No goals needed for project - skipping
	[INFO] [site:site]
	[WARNING] No URL defined for the project - decoration links will not be resolved
	[INFO] Generating "JavaDocs" report.
	...
	[INFO] Generating "Continuous Integration" report.
	[INFO] Generating "Dependencies" report.
	[INFO] Generating "Issue Tracking" report.
	[INFO] Generating "Project License" report.
	[INFO] Generating "Mailing Lists" report.
	[INFO] Generating "About" report.
	[INFO] Generating "Project Summary" report.
	[INFO] Generating "Source Repository" report.
	[INFO] Generating "Project Team" report.
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 19 seconds
	[INFO] Finished at: Tue Aug 12 16:45:38 CEST 2008
	[INFO] Final Memory: 18M/35M
	[INFO] ------------------------------------------------------------------------
			

12. Heritage de pom

Un pom très complet peut devenir très conséquent. De plus, une partie importante de son contenu sera souvent partagé entre plusieurs projets (mêmes rapports, mêmes repository...)

Un mécanisme d'héritage permet d'organiser et de factoriser le contenu des pom.xml

Le code à utiliser est le suivant :

	<project ...>
		<parent>
			<groupId>...</groupId>
			<artifactId>...</artifactId>
			<version>...</version>
		</parent>
		...
	</project>
				
Via ce code, toutes les informations contenu dans le pom.xml du paquet ciblé sera ajouté au pom.xml courant. Les informations du pom courant sont forcément prioritaire en cas de doublons.

Attention : On a vite tendance à mettre les repository dans un pom hérité pour alléger le pom sur lequel on travail mais il faut toujours bien penser que le pom hérité sera recherché sur les repository connu, il faut donc que le pom sur lequel on travail connaisse au moins le repository où chercher son parent.

Cette solution est très intéressante pour éviter de rendre les pom illisible parce que trop long et encore plus intéressante lorsque l'on travail sur plusieurs projets. Il faut donc rapidement utiliser ce mécanisme et ne pas repousser sa mise en place trop longtemps.


13. Intégration continue


13.1. Principes

Chaque développeur commit son travail sur le système de gestion de sources. Le système d'intégration continue est connecté au système de gestion de sources va lancer une intégration à chaque commit.

L'intégration consite alors en l'enchainement de la compilation, de l'execution des tests unitaires, du déploiement de l'application et la génération du site de rapports.


13.2. Bénéfices

Le mécanisme réduit les problèmes d'intégration :

Permet de s'apercevoir au plus tôt des problèmes

Souligne les éventuelles régressions

Permet une application "Snapshot" disponible en permanence


13.3. Intégration continue avec Maven

L'architecture et les principes de maven favorisent cette pratique. Le processus de build maven est le même quel que soit l'environnement. L'utilisation des goals Maven peut être facilement automatisées.

Plusieurs produits Open Source permettent de mettre en oeuvre une intégration continue avec Maven :

Le système d'intégration contninue surveille le système de gestion des sources et lance un cycle maven complet : compilation, install, tests, déploiement, génération du site, etc...

C'est le POM du projet qui est utilisé pour paramétrer ce cycle, la configuration est donc la même que ce soit en local ou sur la plateforme d'intégration.

Maven gérant également les déploiement sur des applications tel que le déploiement d'un War dans Tomcat, avec un goal Maven supplémentaire dans l'intégration continue, l'application peut être redéployée à chaque build.


14. Archetypes

Un Archetype est un outil pour faire des templates de projet Maven. Avec des Archetypes existant déjà pour des grands projets tel que Tapestry , il est possible de créer un projet initialisé pret à compiler et déployer.

info Introduction aux Archetypes Maven

14.1. Utiliser un Archetype Maven

La commande à lancer pour créer un projet à partir d'un Archetype est presque toujours décrite avec l'Archetype. Néammoins, la commande est la suivante :

	mvn archetype:create -DarchetypeGroupId=org.apache.tapestry -DarchetypeArtifactId=quickstart
		-DgroupId=org.example -DartifactId=myapp
		-DpackageName=org.example.myapp -Dversion=1.0.0-SNAPSHOT
				
L'Archetype est un projet Maven identifié avec un groupId et artifactId comme les autres. Les paramètres à renseigner correspondent donc à la localisation du packet de l'Archetype auxquels on ajoute les paramètres du projet que l'on va créer : son nom, les package des sources et sa version.

Cette commande va générer tout le nécessaire pour lancer un projet démo avec Tapestry.


14.2. Créer un Archetype Maven

Un Archetype Maven est un projet Maven avec des particularités qui lui permettront ensuite de remplacer avec les valeurs paramètrés lors du mvn archetype:create.

Pour les détails concernant la création d'un Archetype Maven, il y a deux sources principales : Créer son propre Archetype Maven sur le site Maven et le site du plugin Archetype


15. Projets modulaires

Dans les projets Web, il est très souvent interessant de séparer le code middle du projet de la couche de présentation. Cela permet notamment de localiser le middle dans un jar que l'on pourra réutiliser dans le site Web mais aussi dans les batchs, les Web Services etc...

Les projets modulaires dans Maven permettent de mettre de déclarer des métas-projets qui sont le regroupement de plusieurs projets Maven.


15.1. Définition

Pour créer un projet multimodule, le principe est de créer plusieurs projets Maven dans un même sous répertoire. A la racine de ce répertoire, il faut ajouter un fichier pom.xml qui va réferencer les sous projets.

	+- project/
	   +- pom.xml
	   +- sub-project1/
	   |  +-pom.xml
	   +- sub-project2/
	   |  +-pom.xml
	   +- sub-project3/
	      +-pom.xml
				
Le méta projet n'est pas obligatoirement placé à la racine des sous projets. C'est tout de même préférable notamment pour la gestion des release comme on le vera plus bas.

Pour référence les sous projet, le méta projet devra ressembler à ça :

	<project ...>
		<modelVersion>4.0.0</modelVersion>
		<groupId>...</groupId>
		<artifactId>...</artifactId>
		<packaging>pom</packaging>
	
		<modules>
			<module>sub-project1</module>
			<module>sub-project2</module>
		</modules>
	</project>
				
Attention pour travailler ensemble, les sous modules doivent générer leur dépendances eux même. Par exemple, si les deux sous projets sont monProjetMiddle et monProjetFront, il sera toujours necessaire de définir monProjetMiddle comme dépendance de monProjetFront.

Ce n'est pas parce que plusieurs projets sont référencés dans le même méta-projet qu'ils se connaissent les un les autres.


15.2. Utilisation

Maven propose étonnament peu de fonctionnalité qui se basent directement sur le mécanisme des modules. La seule fonctionnalité directe est le "reactor". Le "reactor" est le mecanisme qui fait que lorsqu'on lance un goal sur un méta-projet, ce goal va d'abord être lancé successivement sur tous les sous-projets.

	...
	[INFO] ------------------------------------------------------------------------
	[INFO] Reactor Summary:
	[INFO] ------------------------------------------------------------------------
	[INFO] sub project 1 .......................................... SUCCESS [12.892s]
	[INFO] sub project 2 .......................................... SUCCESS [15.000s]
	[INFO] sub project 3 .......................................... SUCCESS [0.313s]
	...
	[INFO] ------------------------------------------------------------------------
	[INFO] BUILD SUCCESSFUL
	[INFO] ------------------------------------------------------------------------
	[INFO] Total time: 1 minute 32 seconds
	[INFO] Finished at: Tue Jul 08 17:19:38 CEST 2008
	[INFO] Final Memory: 15M/33M
	[INFO] ------------------------------------------------------------------------
				
Dans la définition des goals Maven, il est possible de traiter le fait de s'executer ou non dans le cadre d'un projet multi-module. Il est donc possible de trouver des plugin Maven qui ont un comportement particulier pour les projets multi-modules, c'est le cas notamment pour le plugin Maven pour Lutèce.


15.3. Intérêts et développements

On l'a vu, Maven propose peu de fonctionnalités directement liées aux modules, pourtant l'utilisation en est de plus en plus importante.

En effet un des intétrêts majeur de Maven est sa gestion fine des dépendances. Il est de plus en plus souvent interessant de profiter de cette gestion au sein même d'un projet.

Comme on l'a vu, dans un projet Web, on va rapidement extraire le middle dans un projet à part afin de pouvoir en dépendre depuis plusieurs projet differents.

Dans les grands framework, ce besoin est encore plus évident : pour les projets volumineux comme Spring, de ne pas avoir tout en dépendance. Par exemple, si on utilise pas la fonctionnalité de connexion au LDAP de Spring, il n'est pas nécessaire de dépendandre de l'artefact spring-ldap ni des dépendances nécessaire à la connexion LDAP etc...

Spring est aujourd'hui découpé en plus de 40 modules, Hibernate, Tapestry, Struts sont déjà tous des projets Maven modulaires...



               Version PDF   Version hors-ligne

Valid XHTML 1.1!Valid CSS!

Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -