Eclipse compiler & m2e

By , 24/01/2012

Récemment, j’ai appris que l’IDE eclipse n’utilisait pas le compilateur de la JDK (javac) pour transformer les fichiers Java en Class. C’est d’ailleurs pour cela qu’il est possible de développer et compiler du code sans avoir installer la JDK sur son ordinateur.

Par défaut, Maven utilise javac pour compiler les sources Java. Or, dans certains cas, le compilateur eclipse (JDT) accepte de compiler des classes là où javac sort en erreur. Par exemple, voici un code qui compile avec le JDT et pas avec javac :

package com.test;

public class GenericMethod {

    private Object value;

    @SuppressWarnings("unchecked")
    public <X> X getValue() {
        return (X) value;
        // le cast n'est obligatoire que pour que javac compile
        // avec le compilateur eclipse, il n'est pas nécessaire
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

Voici la classe pour appeler la méthode :

package com.test;

public class GenericMethodTest {

    public static void main(String[] args) {
        GenericMethod method = new GenericMethod();
        method.setValue(3);

        int[] array = new int[] {1, 2};

        array[0] = method.getValue();
        System.out.println(array[0]);
    }
}

Avec javac, la ligne 11 de la classe GenericMethodTest provoque l’erreur suivante :

type parameters of <X>X cannot be determined;no unique maximal instance exists for type variable X with upper bounds int,java.lang.Object

Il peut donc être essentiel d’utiliser dans le processus de build un autre compilateur que javac. Il est possible de configurer le plugin maven-compiler-plugin afin d’utiliser un compilateur alternatif. Par exemple, pour utiliser le compilateur eclipse c’est très simple :

<project>
  [...]
  <build>
    [...]
    <plugins>
      [...]
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <compilerId>eclipse</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
          </dependency>
        </dependencies>
      </plugin>
  [...]
</project>

Le build maven fonctionne parfaitement, en revanche l’utilisation du compilateur alternatif a des effets secondaires lorsqu’il est utilisé par le plugin eclipse m2e. La modification des fichiers .classpath et .project ne fonctionne plus correctement et cela provoque :

  • La nature java du projet n’est pas détectée,
  • Les dépendances ne sont plus récupérées,
  • Les répertoires sources (src/main/java, src/main/resources, etc.) ne sont plus référencés

Le problème du nouveau plugin m2e c’est qu’il ne reconnaît les projets maven en tant que projets java que lorsque le compilateur utilisé est javac. Pour configurer un projet eclipse utilisant le compilateur eclipse, il est donc nécessaire d’indiquer à m2e qu’il s’agit bien d’un projet Java :

<pluginManagement>
  <plugins>
    <plugin>
      <groupId>org.eclipse.m2e</groupId>
      <artifactId>lifecycle-mapping</artifactId>
      <version>1.0.0</version>
      <configuration>
        <lifecycleMappingMetadata>
          <pluginExecutions>
            <pluginExecution>
              <pluginExecutionFilter>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <versionRange>[2.0,)</versionRange>
                <goals>
                  <goal>compile</goal>
                  <goal>testCompile</goal>
                </goals>
              <parameters>
                <compilerId>eclipse</compilerId>
              </parameters>
             </pluginExecutionFilter>
             <action>
               <configurator>
                 <id>org.eclipse.m2e.jdt.javaConfigurator</id>
               </configurator>
             </action>
           </pluginExecution>
          </pluginExecutions>
        </lifecycleMappingMetadata>
      </configuration>
    </plugin>
  </plugins>
</pluginManagement>

Dès que m2e reconnaît le projet en tant que projet java, la fonction Update project configuration, configurera les répertoires sources et mettra à jour le classpath du projet.

4 Responses to “Eclipse compiler & m2e”

  1. Fred Bricon says:

    Sinon il y’a ce connecteur m2e qui permet d’eviter de modifier le pom.xml : https://github.com/fbricon/m2e-jdt-compiler#readme

    Installable depuis http://download.jboss.org/jbosstools/builds/staging/m2e-jdt-compiler/all/repo/ en attendant de le rendre dispo sur le marketplace m2e.

    • Yan says:

      Merci pour ce commentaire, j’ai cherché un connecteur de ce type très longtemps avant de tomber sur cette astuce.

  2. Jérôme says:

    Excellent article !

    Chaque compilateur a donc son comportement propre, et il faut s’en méfier en passer de l’un à l’autre.

    Pour ma part, je suis partisant d’avoir javac comme référence, même s’il est plus restrictif, car c’est le standard de fait. (un IDE qui refuse de compiler du code validé par javac, ça n’existe pas… du moins je l’espère !)

Leave a Reply to Yan


+ three = 6

OfficeFolders theme by Themocracy