Vaadin-gradle-plugin does not support Gradle Toolchains
Description of the bug
UI project utilizing vaadin-gradle-plugin fails to build on vaadinBuildFrontend task, when Gradle toolchains configured to higher version of java. e.g JAVA_HOME is java 11, toolchain version is java 17.
Failure happens since gradle compiles java using java 17, but vaadin-gradle-plugin uses java 11 to process classes.
Expected behavior
vaadin-gradle-plugin must respect gradle java toolchain configured in project and use appropriate tools for underlying steps of the build.
Minimal reproducible example
Add toolchain configuration DSL into build.gradle of UI project utilizing vaadin-gradle-plugin e.g.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
CLI actions:
export JAVA_HOME=<jdk11> ./gradlew build -s BUILD FAILED ... vaadinBuildFrontend failed with exception...
Versions
- Vaadin / Flow version: 23.+, 24.+
- Java version: 11+
- OS version: any
- Browser version (if applicable): n/a
- Application Server (if applicable): n/a
- IDE (if applicable): n/a
We are not currently sure if the fact that Vaadin Gradle plugin doesn't respect it / support it is a bug or feature. Let us investigate more about Gradle Toolchain and how common it is for Gradle projects.
@mvysny do you have an idea/suggestion how to treat this issue?
I do not know much about toolchains, but from what I read at https://docs.gradle.org/current/userguide/toolchains.html , it's a way to compile your project using a different JVM than the one running Gradle itself. In such case vaadin-gradle-plugin should then honor toolchain setting. However, that means that the class processing code (which means Flow plugin code) must run on the toolchain java rather than Gradle java, and I have no idea how that works. Needs investigating how this could be achieved, hopefully using support from Gradle itself.
@mvysny @mshabarov @mcollovati
I forked the flow-gradle-plugin and rewrote it to support Gradle's Java toolchains. The code is just a proof of concept and is unsuitable for a PR. I wanted to run some ideas by you about my POC to see if you are interested in me creating a PR for this feature or alternatively you can use the ideas below as part of your own investigation.
Details of the POC
Convert VaadinBuildFrontendTask to the Worker API
Gradle's Worker API allows us to configure a desired level of isolation such that work can be executed in an isolated process.
-
Moved the code from the
@TaskActioninVaadinBuildFrontendTaskinto an implementation of WorkAction -
Expressed all the parameters required by the
VaadinBuildFrontendTaskas an extension of the WorkParameters interface. Note, the current design of theVaadinBuildFrontendTaskessentially adapts a GradleProjectinstance to aPluginAdapterBaseto execute the frontend build. Using theProjectat Task execution time is deprecated and will break once the configuration cache is enabled by default (see here). Despite the deprecation ofProject, objects of this type are not serializable and therefore cannot be used as WorkParameters. To remove the use ofProjectfromTaskexecution I expressed everything needed byPluginAdapterBaseas File, Directory and Serializable properties using Gradle's various @Input/@Output annotations on theVaadinBuildFrontendTask. It then becomes the responsibility of theVaadinPluginthat registers the task to get the data from theProjectand provide it to theVaadinBuildFrontendTask -
Created a thin implementation of
PluginAdapterBase. With all inputs now available asWorkParameters, the action builds a POJO implementation ofPluginAdapterBase, which can be provided to the various methods onBuildFrontendUtil. -
Use the toolchain JDK (If one is configured) to execute the
WorkAction. With theVaadinBuildFrontendTasknow converted to theWorker API, we inject the Gradle JavaToolchainService and Gradle's WorkerExecutor into theVaadinBuildFrontendTask. Our action is then executed using WorkerExecutor#processIsolation with a JDK provided by ToolchainService#launcherFor
I have successfully tested my POC and built a Vaadin front end containing Java 21 code (with toolchains configured) with Gradle running on JDK 17.
I would appreciate any comments you may have on my proposed implementation and whether you feel that it would be worth me spending time to create a production-ready PR for you.
Simon
@sihutch thank you very much for taking the time to look into this issue. At a first glance, it seems a great improvement and a PR is definitely worth it. We would like to improve/fix Gradle support and contributions are more than welcome
Hi @mcollovati, @mvysny, @mshabarov I've prepared PR https://github.com/vaadin/flow/pull/19789 based on example that @sihutch demonstrated earlier in this conversation.