Ce soir j’ai participé à la deuxième réunion du ChtiJUG, le club des Javaistes du Nord.
Thème de la soirée : Maven2, la présentation était effectuée par Arnaud Héritier, commiter et membre du comité du projet.
Cela fait maintenant 6 ans que je pratique Maven et je venais surtout pour profiter de l’expérience d’Arnaud que l’on imagine avoir participé à de multiples mises en places.
J’ai trouvé la présentation intéressante, Arnaud ne manie pas la langue de bois et n’est pas avar en anecdotes et conseils.
Voici les points que j’ai retenu de sa présentation :
- Maven ne convient pas à tous les projets, notamment quand il n’y a pas de besoin de standardisation ou de réutilisation
- Dans un premier temps, se contenter d’une mise en place simpliste, en évitant de sur utiliser les capacités avancées de l’outil : héritages à n niveaux, trop de modules, profils, …
- De concentrer ensuite sur la sécurisation du build : utiliser un proxy maven pour pallier à une défaillance des serveurs centraux, préciser la version de tous les plugins.
- Enfin : industrialiser le build : mettre en place une intégration continue, mettre en place les outils et rapports qualité, automatiser la release.
Arnaud a également pas mal partagé sur sa vision des outils de l’écosystème Maven et se montre très enthousiaste quand il parle de Nexus (proxy et référentiel maven) ou de Hudson (intégration continue)
Autre remarque d’Arnaud : configurez Maven pour qu’il s’adapte à votre IDE et pas l’inverse : il faut passer le moins de temps possible dans la console.
Je pense que la fin de la présentation ainsi que certaines questions ont du plonger une bonne partie de la salle dans de profonds doutes quand au coté simple de l’outil, le niveau était assez relevé
Coup de chapeau à mon ami et collègue Jérémy qui a brillamment gagné une licence IntelliJ IDEA en répondant à une question difficile : de quel projet est issu Maven : vous le saviez vous ?
Charlie Collins annonce qu’il va rejoindre le projet Mojo afin de fusionner le plugin GWT-Maven qu’il a réalisé avec celui du projet Mojo : gwt-maven-plugin.
Je pense que c’est une très bonne nouvelle pour l’industrialisation des projets GWT, tous les efforts d’outillage autour de maven porteront sur le même produit.
Maven 2 propose d’origine les types de packaging des différents composants java / j2ee : jar, war, ejb et ear.
Cependant, il faut parfois utiliser des types de packaging moins conventionnels qui nécessitent la création d’un packaging maven dédié.
Pour exemple, je vais créer un packaging nommé “custom”, qui va créer des archives avec l’extension .cust et qui contient les classes et ressources du projet dans un répertoire “classes” et les dépendances du projet dans un répertoire lib.
- Première étape : créer le plugin maven2 à l’aide de l’archetype plugin :
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-plugin -DgroupId=org.tartachuc.m2 -DartifactId=my-custom-packaging
- Ajouter dans le descripteur de projet pom.xml le projet maven-archiver :
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
<version>2.2</version>
</dependency>
- Modifier le MOJO généré par l’archetype pour qu’il prenne en charge le packaging.
- Renommer la classe MyMojo en CustomPackageMojo
- Changer le commentaire en entête de la classe pour préciser le goal : custom et la phase : package
/**
* Goal which creates a custom package
* @goal custom
* @phase package
*/
- Ajouter au Mojo les attributs et leur documentation qui vont permettre de récupérer des informations sur le projet qui utilise le plugin :
private MavenProject project;
private File classesDirectory;
private File buildDirectory;
- Ajouter au Mojo les attributs qui vont permettre de créer l’archive :
private JarArchiver jarArchiver;
protected MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
- Ce packaging maison nécessite d’archiver les dépendances du projet, dans un premier temps les dépendances vont être copiées dans un répertoire de travail. Pour pouvoir configurer ce répertoire de travail, ajouter un attribut au Mojo
private File libDirectory;
- Il faut maintenant implémenter la méthode “execute” qui est le point d’entrée du Mojo.
public void execute() throws MojoExecutionException {
String archiveName = project.getBuild().getFinalName() + ".cust";
File custFile = new File(buildDirectory, archiveName);
MavenArchiver archiver = new MavenArchiver();
archiver.setArchiver(jarArchiver);
archiver.setOutputFile(custFile);
copyLibs();
try {
archiver.getArchiver().addDirectory(classesDirectory, "classes/");
archiver.getArchiver().addDirectory(libDirectory, "lib/");
archiver.createArchive(project, archive);
project.getArtifact().setFile(custFile);
} catch (ArchiverException e) {
throw new MojoExecutionException("Exception while packaging", e);
} catch (ManifestException e) {
throw new MojoExecutionException("Exception while packaging", e);
} catch (IOException e) {
throw new MojoExecutionException("Exception while packaging", e);
} catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException("Exception while packaging", e);
}
}
protected void copyLibs() throws MojoExecutionException {
try {
Set artifacts = project.getArtifacts();
for (Iterator iter = artifacts.iterator(); iter.hasNext();) {
Artifact artifact = (Artifact) iter.next();
ScopeArtifactFilter filter = new ScopeArtifactFilter(
Artifact.SCOPE_RUNTIME);
if (!artifact.isOptional() && filter.include(artifact)
&& "jar".equals(artifact.getType())) {
FileUtils.copyFileToDirectory(artifact.getFile(),
libDirectory);
}
}
} catch (IOException e) {
throw new MojoExecutionException("Error copying libs", e);
}
}
- Il faut maintenant indiquer à maven quel MOJO exécuter lors du cycle de vie de notre nouveau packaging. Pour cela, le plugin doit inclure un descripteur plexus nommé components.xml à placer dans répertoire src/main/resources/META-INF/plexus.
<?xml version="1.0" encoding="UTF-8"?>
<component-set>
<components>
<component>
<role>org.apache.maven.artifact.handler.ArtifactHandler</role>
<role-hint>cust</role-hint>
<implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
<configuration>
<type>cust</type>
<extension>cust</extension>
<language>java</language>
</configuration>
</component>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>cust</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<phases>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
<process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
<test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
<test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
<package>org.tartachuc.m2:my-custom-packaging:custom</package>
<install>org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</phases>
</configuration>
</component>
</components>
</component-set>
Nous avons inséré notre MOJO (org.tartachuc.m2:my-custom-packaging:custom) lors de la phase de packaging. les autres MOJO sont repris des plugins standards de maven.
- Pour installer le plugin dans votre référentiel local, exécuter la commande
mvn install
- Pour utiliser le packaging nouvellement créé, il faut créer un nouveau projet et déclarer le packaging cust et le plugin créé ci-dessus comme extension du build.
<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>org.tartachuc.m2</groupId>
<artifactId>my-custom-project</artifactId>
<packaging>cust</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-custom-project uses a custom packaging</name>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>2.5.3</version>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>org.tartachuc.m2</groupId>
<artifactId>my-custom-packaging</artifactId>
<version>1.0-SNAPSHOT</version>
</extension>
</extensions>
</build>
</project>
- Here it is