Gradle Java Plugin Issue - Gives compilation error but works fine in eclipse IDE

I’m facing weird issue with Gradle 4.1, JDK 1.8.291 and Eclipse IDE. I created demo class to explain my problem. Please note that i set the same JDK in eclipse build Path as well and also im not using any Gradle plugin in eclipse. Its just a simple java project.

Below code absolutely works fine in eclipse with same JDK:

package com.test;

import java.util.HashMap;
import java.util.Map;

public class Sample {
	public static void main(String[] args) {
		Map<String, Long> myMap=new HashMap<>();
		Long l=(myMap.get("abc")!=null)?myMap.get("abc"):0;
		System.out.println(l);
	}
}

But when i’m trying to build the same code with Gradle 4.1 and same JDK which i set in ENV variable, causes compilation error:

> Task :compileJava
Sample.java:9: error: incompatible types: bad type in conditional expression
                Long l=(myMap.get("abc")!=null)?myMap.get("abc"):0;
                                                                 ^
    int cannot be converted to Long
1 error


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

Below is my build.gradle file:

apply plugin: 'java'
sourceSets { 
  main { 
    java { srcDirs = [ 'src/main' ] } 
  }
  test { 
    java { srcDirs = [ 'test' ] } 
  }
}

Can anyone please explain why this is happening.

If i change below line like this:

Long l=(myMap.get("abc")!=null)?myMap.get("abc"):0L;

gradle build is fine. But i want to know why earlier code is failing with Gradle but success in eclipse.

Because we are migrating to Gradle 4.1 & JDK8 from older gradle version 1.9 and JDK7. I’ve found similar lines in various modules and all are failed due to this error. So i want to know the root cause for this issue.

This doesn’t have anything to do with Gradle. No matter what version of Gradle (or any other build tool for that matter), you absolutely should have a failure.

This line of code is simply not valid in Java 8:

Long l = (myMap.get("abc") != null) ? myMap.get("abc") : 0;

Eclipse is the issue here. Either Eclipse is not really using a Java 8 compatible compiler, or its Java 8 compiler is just broken as it uses its own built-in compiler, not the one from the JDK.

I can 100% sure that eclipse is using same JDK (JDK1.8_291 which i downloaded from oracle site) that i set in Installed JREs and the same being used even for Gradle… In fact, IntellijIDE also shows program is clean and no errors… Anyways, let me post the issue in eclipse forum as well.

It doesn’t really matter what JDK is shown in your Installed JREs. Eclipse uses its own compiler to incrementally compile the code and give faster feedback. It does not use the compiler included in your JDK. Sometimes this causes discrepancies between what the IDE shows as valid and what will actually compile with the JDK compiler.

When moving from Java 7 to Java 8, you should have to change 0 to 0L because Java 8 doesn’t support auto-boxing and widening in the same operation.

Thank you @jjustinic … But most of our dev uses eclipse to do code development… if eclipse shows clean without compilation errors but if gradle build fails in jenkins server, team again need to rework. Can you suggest any other way to get rid of this problem?

Not really. The Eclipse compiler and javac are different implementations with different objectives, and sometimes bugs cause them to differ in results, but I wouldn’t really expect it to be a problem for a non-junior developer. These should be extremely rare edge cases (but perhaps less rare if the same code has been copy/pasted across multiple locations).

As far as rework, the IDE is a tool and accurate most of the time, but I would expect an experienced developer to at least run a quick check with the real compiler before committing to the repository. The IDE gives good feedback while you type, but it’s not a replacement for running a quick check once a batch of work seems done.

In Java 8, you can’t auto-box and widen in the same assignment. So, Long l = 0; is not valid, but Long l = 0L; or long l = 0; are since each only does one or the other. The Eclipse compiler seems to be confused by the ternary and doesn’t quite pick up that the second part of the ternary isn’t the same type as the first part. I would expect a developer to notice that the types don’t seem quite right anyway, but even if they don’t, I’d expect the worst case would be they spend a couple extra minutes learning something about Java 8 vs. 7 and then it wouldn’t be an issue again.

This is a Gradle forum though, and from that perspective, the result from Gradle is the same result you’d get with another build tool or javac directly, so there’s not much else that can be done about the unrelated tool. However, I do recommend when you’re using a build tool like Gradle, the Jenkins server should NOT be the first time a Gradle task runs in your developers’ workflow.