8

I have these classes:

public class EntityDataModel<T extends AbstractEntity>
{
    ...
}

public abstract class BarChartBean<E extends ChartEntry, T>
{
    protected EntityDataModel<? extends T> currentModel;

    ...
}

I can compile and run this code on eclipse without problem, but when I invoke mvn compile, this error is thrown:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project edea2: Compilation failure: Compilation failure:
[ERROR] C:\Develop\...\BarChartBean.java:[53,30] error: type argument ? extends T#1 is not within bounds of type-variable T#2
[ERROR] where T#1,T#2 are type-variables:
[ERROR] T#1 extends Object declared in class BarChartBean
[ERROR] T#2 extends AbstractEntity declared in class EntityDataModel

The error is pretty self-explanatory, and theoretically speaking, javac is right and eclipse compiler is wrong.

Why there's such a difference?

Here you are the details of the environment:

  • Eclipse

    • Mars.2 Release (4.5.2)
    • jdk 1.8.0_71
    • Compiler compliance level: 1.8
    • Errors/Warnings
  • Maven

    • Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T13:57:37+02:00)
    • Maven home: C:\Develop\tools\apache-maven-3.3.3
    • Java version: 1.8.0_71, vendor: Oracle Corporation
    • Java home: C:\Program Files\Java\jdk1.8.0_71\jre
    • Default locale: it_IT, platform encoding: Cp1252
    • OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
    • maven-compiler-plugin:

      <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.5.1</version>
          <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <encoding>UTF-8</encoding>
              <showDeprecation>true</showDeprecation>
              <showWarnings>true</showWarnings>
          </configuration>
      </plugin>
      

Question: How can I align the eclipse compiler behavior to javac (but I don't want to use javac in eclipse)?

A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73

1 Answers1

6

That's yet another mismatch between the Eclipse Java compiler and the official JDK compiler (because these are different indeed). And javac is not always the right actor in this game, you can indeed hit a javac bug not occurring in the Eclipse compiler.

A similar issue has already been reported: Bug 456459: Discrepancy between Eclipse compiler and javac - Enums, interfaces, and generics.

To align Maven with Eclipse, you can configure the maven-compiler-plugin as following:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.5.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerId>eclipse</compilerId>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
            <version>2.7</version>
        </dependency>
    </dependencies>
</plugin>

Basically, you are telling Maven to use the Eclipse Java compiler. I was able to reproduce your issue and applying this configuration the Maven build was then fine. However, I would not recommend this approach.

On the other hand, to configure Eclipse to use the JDK compiler is a bit more difficult, basically because the Eclipse compiler is part of the IDE features. A procedure is explained in the Stack Overflow q/a: How to run Javac from Eclipse.

Community
  • 1
  • 1
A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
  • 1
    Thanks, just knowing it's a ECJ bug is enough. I opened a [bug report](https://bugs.eclipse.org/bugs/show_bug.cgi?id=496911). – Michele Mariotti Jun 28 '16 at 11:11
  • @MicheleMariotti, thanks for the bug report. As argued there, I'm not convinced that ecj is wrong. JLS 4.5 defines well-formedness of a parameterized type via capturing the type arguments. Such capture by definition conforms to the upper bounds of the corresponding type variable. So, how can `cap#1 extends glb(AbstractEntity,T)` violate the bound `extends AbstractEntity`? This type could be ill-formed by contradictory bounds (i.e., undefined glb), but I don't see any such contradiction. So, why should a compiler reject this? – Stephan Herrmann Jun 28 '16 at 13:42
  • Regarding `plexus-compiler-eclipse`: I'm not sure how this plugin is maintained and what versions of ecj it would pull in. More hints on using ecj outside Eclipse are collected at https://wiki.eclipse.org/JDT/FAQ#Can_I_use_JDT_outside_Eclipse_to_compile_Java_code.3F which includes the option to use tycho, which updates the ecj-dependency quite regularly. – Stephan Herrmann Jun 28 '16 at 13:50
  • @StephanHerrmann I'll take a look, definitely. Thank you, again :) – Michele Mariotti Jun 28 '16 at 14:13