Un vrai build incremental dans Maven

Maven contient une bizarrerie, que certains qualifieront à juste titre de bug. Sans le plugin maven-incremental-plugin, le build dans Maven ne peut pas être executé de manière incrementale car le résultat peut dans certaines situations se reveler incorrect.

Description du problème

Considerons le projet suivant :

module-parent |--- module-api |--- module-impl

Le module module-parent contient 2 sous-modules : module-api et module-impl.

Le module module-impl contient une classe ProcessImpl qui implemente l’interface *Process *définie dans module-api.

Nous lancons la commande "mvn install" sur le projet parent. Tout marche parfaitement. Nous modifions la signature de l’interface *Process *dans module-api sans répercuter les changements sur ProcessImpl de module-impl.

Nous re-lançons une installation du projet sur module-parent avec la commande "mvn install".

... [INFO] ------------------------------------------------------------------------ [INFO] Building module-api [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ ... [INFO] [compiler:compile] [INFO] Compiling 1 source file to C:\devs\poc-inc\module-parent\module-api\target\classes ... [INFO] [jar:jar] [INFO] Building jar: C:\devs\poc-inc\module-parent\module-api\target\module-api-1.0_SNAPSHOT.jar [INFO] [install:install] ... [INFO] ------------------------------------------------------------------------ [INFO] Building module-impl [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ ... [INFO] [compiler:compile] [INFO] Nothing to compile - all classes are up to date ... [INFO] [jar:jar] [INFO] [install:install] ... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] module-parent ......................................... SUCCESS [3.828s] [INFO] module-api ............................................ SUCCESS [2.875s] [INFO] module-impl ........................................... SUCCESS [0.047s] [INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------

Le build se déroule correctement et les livrables module-api.jar et module-impl.jar sont installés dans le repository Maven. Comme les sources de module-impl n’ont pas été éditées, Maven ne le recompile pas, bien qu’il dépende d’un module modifié : module-api. L’état du projet est donc invalide dans le repository maven car au runtime, le problème d’implémentation de *Process *par ProcessImpl lèvera une exception.

Ce problème peut être résolu en forçant le "clean" avant chaque "install". Le build n’est alors plus incremental et pour la modification d’une simple classe, le rebuild est total. Dans de gros projets utilisant l’intégration continue, le coût d’un rebuild total est trop élevé.

Utilisation de maven-incremental-build

Le plugin maven-incremental-build permet d’obtenir un vrai build incremental en ne recompilant que les projets qui doivent l’être.

Il s’exécute automatiquement lors de la toute première phase (validate) du cycle de build Maven et vérifie que ni les sources ni les dépendances n’ont été modifiées depuis le dernier build. Dans le cas contraire, il force la recompilation en effectuant un clean du projet.

Pour l’activer, il suffit d’éditer le pom parent pour ajouter :

... maven2-repository.dev.java.net Java.net Repository for Maven http://download.java.net/maven/2/ default ... ... org.jvnet.maven.incrementalbuild incremental-build-plugin incremental-build ...

Avec le plugin activé, si *ProcessImpl *n’est pas modifié en accord avec Process, le build sera en échec.

[INFO] ------------------------------------------------------------------------ [INFO] Building module-api [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ [INFO] [incremental-build:incremental-build {execution: default}] [INFO] Verifying module descriptor ... [INFO] Pom descriptor modification detected. [INFO] C:\devs\poc-inc\module-parent\module-api\target deleted [INFO] [compiler:compile] [INFO] Compiling 1 source file to C:\devs\poc-inc\module-parent\module-api\target\classes ... [INFO] [jar:jar] [INFO] Building jar: C:\devs\poc-inc\module-parent\module-api\target\module-api-1.0_SNAPSHOT.jar [INFO] [install:install] ... [INFO] ------------------------------------------------------------------------ [INFO] Building module-impl [INFO] task-segment: [install] [INFO] ------------------------------------------------------------------------ [INFO] [incremental-build:incremental-build {execution: default}] [INFO] Verifying module descriptor ... [INFO] Pom descriptor modification detected. [INFO] C:\devs\poc-inc\module-parent\module-impl\target deleted [INFO] [resources:resources] [INFO] Using default encoding to copy filtered resources. [INFO] [compiler:compile] [INFO] Compiling 1 source file to C:\devs\poc-inc\module-parent\module-impl\target\classes [INFO] ------------------------------------------------------------------------ [ERROR] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Compilation failure C:\devs\poc-inc\module-parent\module-impl\src\main\java\fr\ippon\vbe\ProcessImpl.java:[3,7] fr.ippon.vbe.ProcessImpl is not abstract and does not override abstract method method(java.lang.String,int,boolean) in fr.ippon.vbe.Process

Grâce au plugin maven-incremental-build, le projet est forcément dans un état valide en n’effectuant des cleans que lorsque cela s’avère nécessaire.

Liens :

Site du plugin : http://maven-incremental-build.dev.java.net/

Discussion sur le build incremental dans Maven : http://markmail.org/message/kdij7s7jlm2crlip