Gradle/GitHub: Using .java-version Files to Define the Java Version
Effectively reducing the sources of truth about the used Java version to one
When setting up a Java (or Kotlin) build, we often specify the Java version in multiple places:
- The build.gradle(.kts),
- the pipeline(s),
- the IDE configuration.
I personally broke a number of builds simply by forgetting to update one of these accordingly, plus it is quite annoying to have so many places that basically redundantly state the same fact.
GitHub Pipeline
In the pipeline we usually use the GitHub action setup-java
to take care of the Java setup. E.g.
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
Luckily the action allows to be configure a java-version-file
. So we can remove all the 17
s (or 11
s, 21
s, …) from our GitHub pipelines:
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version-file: .java-version
Plus a very simple .java-version
file:
17
Local Setup
According to the documentation, the file format is basically the one of the jEnv tool, which we can also use to automatically configure our local environment.
Gradle Build File
The remaining problem now is the build.gradle.kts, which still contains something like
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
vendor.set(JvmVendorSpec.ADOPTIUM)
}
}
According to my research there’s no direct support to use jEnv’s .java-version
file here. But Gradle allows us to simply read the content of files and the syntax of .java-version
simply contains the used Java version. So we can easily replace the above code with
java {
toolchain {
languageVersion.set(
JavaLanguageVersion.of(file(".java-version").readText(Charsets.UTF_8).trim())
)
vendor.set(JvmVendorSpec.ADOPTIUM)
}
}
Conclusion
The .java-version
file allows us to reduce the number of places stating the Java version from thee to only. In my humble opinion, the code in the build.gradle(.kts)
is straight forward enough. I especially like that there are explicit links to the .java-version
file in the build file and the pipeline. If the file has a corrupted content or is missing, the error messages in GitHub and Gradle are pretty easy to understand.