Ecriture d'un plugin maven en groovy

J'ai eu la chance d'avoir il y a peu une formation à la création de plugin maven par arnaud grand gourou maven. Cependant, je n'avais pas encore eu l'occasion de mettre vraiment la main à la pâte. Je dois bosser la semaine prochaine sur un plugin maven codé en groovy et j'ai besoin de passer par la case départ pour bien comprendre comment cela fonctionne. Cet article est ma case départ...
Codes et explications
Je suis parti from scratch et j'ai suivi les indications sur la page suivante http://docs.codehaus.org/display/GROOVY/GMaven+-+Implementing+Maven+Plugins
J'ai tout d'abord créé l'arborescence suivante :
src/it : contiendra les tests d'intégration ( convention chez maven) src/main src/main/groovy (contiendra le code source groovy src/main/groovy/com src/main/groovy/com/cestpasdur src/main/groovy/com/cestpasdur/maven src/main/groovy/com/cestpasdur/maven/samples/ src/main/groovy/com/cestpasdur/maven/samples/HelloworldMojo.groovy (Notre premier mojo) src/test/groovy (les tests unitaires )
Contenu de pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<!-- Description de l'artifact -->
<groupId>com.cestpasdur.maven</groupId>
<artifactId>maven-helloworld-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Exemple Groovy Mojo - maven-helloworld-plugin</name>
<!-- Les plugins maven ont leur packaging propre-->
<packaging>maven-plugin</packaging>
<properties>
<gmaven.version>1.0-rc-5</gmaven.version>
</properties>
<!-- Dépendances -->
<dependencies>
<dependency>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-mojo</artifactId>
<version>${gmaven.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Permet de générer les descripteurs de mojo présents dans le code source-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>${gmaven.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<!-- Génère les stubs java à partir de mojo groovy -->
<goal>generateStubs</goal>
<!-- Compile le code source groovy-->
<goal>compile</goal>
<!-- Génère les stubs java à partir de mojo groovy pour les Tests unitaires (TU)-->
<goal>generateTestStubs</goal>
<!-- Compile le code source des TU groovy-->
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Contenu du HelloworldMojo
package com.cestpasdur.maven.samples
import org.codehaus.groovy.maven.mojo.GroovyMojo
/**
* description
*
*@goal hello
*/
class HelloworldMojo extends GroovyMojo{
/**
* Dit bonjour à l'utilisateur
*
*/
void execute(){
log.info("hello world")
}
}
Maintenant que le code est terminé, il serait intéressant de vérifier que ce que fait ce plugin (pas grand chose) et que cela correspond à ce l'on attend de lui.
mvn clean install
Sortie console :
NetBeans: Executing '/developpement/apache-maven-2.1.0/bin/mvn -Dnetbeans.execution=true clean install'
NetBeans: JAVA_HOME =/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Home
Scanning for projects...
------------------------------------------------------------------------
Building Exemple Groovy Mojo - maven-helloworld-plugin
task-segment: [clean, install]
------------------------------------------------------------------------
[clean:clean]
Deleting directory /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/target
[groovy:generateStubs {execution: default}]
Generated 1 Java stub
[plugin:descriptor]
[WARNING] Using platform encoding (MacRoman actually) to read mojo metadata, i.e. build is platform dependent!
Applying mojo extractor for language: java
Mojo extractor for language: java found 1 mojo descriptors.
Applying mojo extractor for language: bsh
Mojo extractor for language: bsh found 0 mojo descriptors.
[resources:resources]
[WARNING] Using platform encoding (MacRoman actually) to copy filtered resources, i.e. build is platform dependent!
skip non existing resourceDirectory /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/src/main/resources
[compiler:compile]
Compiling 1 source file to /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/target/classes
[groovy:compile {execution: default}]
Compiled 1 Groovy class
[groovy:generateTestStubs {execution: default}]
No sources found for Java stub generation
[resources:testResources]
[WARNING] Using platform encoding (MacRoman actually) to copy filtered resources, i.e. build is platform dependent!
skip non existing resourceDirectory /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/src/test/resources
[compiler:testCompile]
Nothing to compile - all classes are up to date
[groovy:testCompile {execution: default}]
No sources found to compile
[surefire:test]
No tests to run.
[jar:jar]
Building jar: /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/target/maven-helloworld-plugin-1.0-SNAPSHOT.jar
[plugin:addPluginArtifactMetadata]
[install:install]
Installing /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/target/maven-helloworld-plugin-1.0-SNAPSHOT.jar to /Users/damiengouyette/.m2/repository/com/cestpasdur/maven/maven-helloworld-plugin/1.0-SNAPSHOT/maven-helloworld-plugin-1.0-SNAPSHOT.jar
[plugin:updateRegistry]
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
Total time: 8 seconds
Finished at: Sun Jun 28 09:24:25 CEST 2009
Final Memory: 21M/38M
------------------------------------------------------------------------
Comme vous pouvez le voir j'utilise Netbeans pour coder ce magnifique plugin en groovy car le support est pour le moment meilleur que dans Eclipse (espérons que le rachat de g2one par springsource arrange les choses de ce côté là)
On voit tout d'abord qu'un stub java est généré dont voici le code ci-dessous
//
// Generated stub from file:/developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/src/main/groovy/com/cestpasdur/maven/samples/HelloworldMojo.groovy
//
package com.cestpasdur.maven.samples;
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.*;
import groovy.lang.*;
import groovy.util.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.codehaus.groovy.maven.mojo.GroovyMojo;
/**
* description
*
* @goal hello
*/
public class HelloworldMojo
extends GroovyMojo
implements groovy.lang.GroovyObject
{
/**
* Dit bonjour l'utilisateur
*/
public void execute() {
throw new InternalError("Stubbed method");
}
public groovy.lang.MetaClass getMetaClass() {
throw new InternalError("Stubbed method");
}
public void setMetaClass(groovy.lang.MetaClass metaClass) {
throw new InternalError("Stubbed method");
}
public java.lang.Object invokeMethod(java.lang.String name, java.lang.Object args) {
throw new InternalError("Stubbed method");
}
public java.lang.Object getProperty(java.lang.String name) {
throw new InternalError("Stubbed method");
}
public void setProperty(java.lang.String name, java.lang.Object value) {
throw new InternalError("Stubbed method");
}
}
On peut également voir un warning dans la console :
[WARNING] Using platform encoding (MacRoman actually) to copy filtered resources, i.e. build is platform dependent! skip non existing resourceDirectory /developpement/workspaces/WS-ganymede/maven/maven-helloworld-plugin/src/test/resources
Je suis un mac user, et sur Mac nous avons la change/malchance (choisissez) d'avoir notre propre encodage par défaut. Afin de corriger çà il suffit d'ajouter dans le pom.xml :
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
<configuration>
<!-- Permet de spécifier l'encoding en UTF8 lors du traitement des ressources-->
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Permet de générer les descripteurs de mojo présents dans le code source-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.5</version>
<configuration>
<!-- Permet de spécifier l'encoding en UTF8 lors du traitement des descripteurs de mojo-->
<encoding>UTF-8</encoding>
</configuration>
</plugin>
...
Désormais, plus de warning dans la console :
... [plugin:descriptor] Using 'UTF-8' encoding to read mojo metadata. ... resources:testResources] Using 'UTF-8' encoding to copy filtered resources. ...
Tester son plugin
Pour tester mon plugin, je lance la commande suivante à la racine de mon projet :
mvn com.cestpasdur.maven:maven-helloworld-plugin:1.0-SNAPSHOT:hello
Résultat :
... INFO] ------------------------------------------------------------------------ [ERROR] BUILD ERROR [INFO] ------------------------------------------------------------------------ [INFO] Internal error in the plugin manager executing goal 'com.cestpasdur.maven:maven-helloworld-plugin:1.0-SNAPSHOT:hello': Unable to load the mojo 'com.cestpasdur.maven:maven-helloworld-plugin:1.0-SNAPSHOT:hello' in the plugin 'com.cestpasdur.maven:maven-helloworld-plugin'. A required class is missing: [Lorg/codehaus/groovy/runtime/callsite/CallSite; org.codehaus.groovy.runtime.callsite.CallSite ...
Je n'ai pas trouvé d'autre moyen que de changer la version en rc4, ce qui a corrigé le bug (j'en ai profité pour ouvrir un bug : http://jira.codehaus.org/browse/MGROOVY-206)
Re clean install
mvn clean install
Je relance le plugin et cette fois, cela fonctionne. Mission accomplie :
macbook-pro-de-damien-gouyette:maven-helloworld-plugin damiengouyette$ mvn com.cestpasdur.maven:maven-helloworld-plugin:1.0-SNAPSHOT:hello [INFO] Scanning for projects... [INFO] ------------------------------------------------------------------------ [INFO] Building Exemple Groovy Mojo - maven-helloworld-plugin [INFO] task-segment: [com.cestpasdur.maven:maven-helloworld-plugin:1.0-SNAPSHOT:hello] [INFO] ------------------------------------------------------------------------ [INFO] [helloworld:hello] [INFO] hello world [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3 seconds [INFO] Finished at: Sun Jun 28 11:04:27 CEST 2009 [INFO] Final Memory: 11M/80M [INFO] ------------------------------------------------------------------------
...
Code source
source maven-helloworld-plugin
En savoir +
http://groovy.codehaus.org/GMaven+-+Implementing+Maven+Plugins
http://www.sonatype.com/books/maven-book/reference/writing-plugins-alternative-sect-writing-groovy.html
Je vous invite à télécharger le code source de gmaven ici : https://svn.codehaus.org/groovy/gmaven/trunk
Le trunk contient actuellement des exemples de mojo qui existent déjà en java (cleanMojo, installMojo), mais cette fois, ils sont codés en groovy.
Aucun trackbacks pour l'instant