1

I'm having trouble getting either of the two Cloud Native Buildpacks builders I've tried (gcr.io/buildpacks/builder:v1 and paketobuildpacks/builder:base) to fully detect my desired Java version so that the right JVM is used to build my project and to run it. It seems to successfully detect my desired version as it completes the build step, but I notice in the logs during the build that it ends up downloading a version 11 JDK and I get an error when trying to run a container from the built image:

Error: LinkageError occurred while loading main class com.mattwelke.javatests.JavalinPostgresJdbc
java.lang.UnsupportedClassVersionError: com/mattwelke/javatests/JavalinPostgresJdbc has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0

This error infers that it chose to use JDK 17 to build the class files but then JDK 11 to run them.

My project structure is the one produced by running gradle init and choosing "application" as the type of project to be created, except I moved the contents of app up into the root and deleted settings.gradle. I found that I had to do that in order for the first builder I tried to be able to detect it as a Gradle project in the first place. I also had to add id 'com.github.johnrengelman.shadow' version '7.1.2' to the plugins section of build.gradle, otherwise the builder failed to build, with an error about not being able to find a main class.

I added the following to build.gradle to indicate my preferred Java version for the project:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

I thought that this might be something I'm doing wrong, therefore being a good reason to post to Stack Overflow, instead of raising a GitHub issue in either of the repos for the two builders I tried, because I got the exact same error with both builders (the one from Google and the one from Paketo).

Matt Welke
  • 1,441
  • 1
  • 15
  • 40

1 Answers1

1

I can't speak to the first builder, but for Paketo Buildpacks, you just need to set BP_JVM_VERSION and that'll tell the builder what version to use. It'll use Java 11 by default, so I think that's why you're getting Java 11.

Ex: pack build cool-app -e BP_JVM_VERSION=17

https://paketo.io/docs/howto/java/#install-a-specific-jvm-version

There is a Gradle Sample App available here.


I don't know why some things have been built with Java 17, but for the Paketo Java buildpack, you cannot build with one version and run with another version, the same version is always used for both build and run.

The only time I've seen this happen is when I build locally on Java 17 and pack build -p build/libs/app.jar, forgetting to set BP_JVM_VERSION to 17. In that case, it'll build from my locally compiled code which is from a newer Java version.

If you leave off the -p argument or have -p point to your Java source code, then you should always get a consistent build with the same version of Java at build and runtime.

Daniel Mikusa
  • 13,716
  • 1
  • 22
  • 28
  • Thanks, that did the trick. I actually already read the documentation on the website and the readme for the Paketo Gradle builder on GitHub, but I misunderstood what the documentation meant when it said there was a `BP_JVM_VERSION` environment variable. It didn't have examples of using it, so I thought I was supposed to set an environment variable with that name as I invoke `pack`, like `BP_JVM_VERSION=17 pack build cool-app`. I didn't realize by "environment variable" by they meant a type of command line parameter. I think better docs would help, so I'll raise the issue in the Paketo project. – Matt Welke Apr 05 '22 at 04:58
  • As for why I was seeing it use Java 17 to build my code and then Java 11 to run it, I think that it's working as designed. Its readme (https://github.com/paketo-buildpacks/gradle) says it will first "Requests that a JDK be installed" and then "If /gradlew exists, Runs /gradlew --no-daemon assemble to build the application". The builder delegated to Gradle to do the build, and in my case, I configured Gradle to build with a particular version of Java, JDK 17. Since the builder controls what version of Java is used to run the code, my code ran under JDK 11. – Matt Welke Apr 05 '22 at 05:04