I am getting a class version error when compiling my groovy test code. I am using Gradle 8.5 and Java 21 which I believe is a supported combination. Any tips why this still fails?
* What went wrong:
Execution failed for task ':compileTestGroovy'.
> BUG! exception in phase 'semantic analysis' in source unit '/gee/workspace/..../MyControllerSpec.groovy' Unsupported class file major version 65
$ ./gradlew -v
------------------------------------------------------------
Gradle 8.5
------------------------------------------------------------
Build time: 2023-11-29 14:08:57 UTC
Revision: 28aca86a7180baa17117e0e5ba01d8ea9feca598
Kotlin: 1.9.20
Groovy: 3.0.17
Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM: 21 (Oracle Corporation 21+35-LTS-2513)
OS: Linux 5.4.17-2136.325.5.1.el7uek.x86_64 amd64
Why should it?
Unless you tell it to.
The Groovy version you use to build production code (or in your case test code) has nothing to do with the Groovy version used for Groovy DSL build scripts or plugins written in Groovy.
Those are two totally separate things unless you configure it like that for example when building build logic by using localGroovy() instead of a normal Groovy dependency.
So I guess up to this point, my cucumberTest just used the groovy plugin. From what you are saying I need to setup a different groovy not that works with Java 21. I haven’t been able to find a reference yet for how to have compileTestGroovy to use a different groovy.
Just having the Groovy plugin will not bring you any Groovy version.
You might have an explicit dependency or you might have an implicit dependency, but it is coming from a dependency.
You can use the dependencies task, or the dependencyInsight task, or if you can a build --scan to see where it comes from and which version it is.
I am having the same issue on a bare new project created with gradle init. My build scan.
Any idea how to troubleshoot this issue?
Edit: I created another project but this time at the last question “Generate build using new APIs and behavior (some features may change in the next minor release)?” I answered “no” and this time I didn’t get any error when running the tests.
$ ./gradlew dependencies
> Task :dependencies
------------------------------------------------------------
Root project 'java'
------------------------------------------------------------
No configurations
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 713ms
1 actionable task: 1 executed
$ ./gradlew build --scan
> Task :app:compileTestGroovy FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileTestGroovy'.
> BUG! exception in phase 'semantic analysis' in source unit '/home/marco/src/java/app/src/test/groovy/org/example/AppTest.groovy' Unsupported class file major version 65
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Get more help at https://help.gradle.org.
BUILD FAILED in 5s
6 actionable tasks: 5 executed, 1 up-to-date
Well, it is exactly what I already assumed is OP’s problem.
It is not Gradle complaining, but Groovy.
You use Groovy 3.0.12 and that is not Java 21 compatible.
Use a newer Groovy version, an older Java version to run Gradle, or better use toolchains to decouple the Java version used to run Gradle from the Java version used for your code.
I don’t know where that Groovy 3.0.12 is coming from because it is not installed system wide. After running gradle init I selected Groovy when Gradle asked to “Select build script DSL”, so I suppose gradle installed it locally for the project? That question comes after I selected the Java version (21), so shouldn’t Gradle install a Groovy version compatible with the Java version I selected?
Do you know why this problem happens only when using gradle init and answering “yes” to the last question “Generate build using new APIs and behavior (some features may change in the next minor release)?” but when I answer “no” then the application runs just fine?
Gradle does not “install” any Groovy version.
And what DSL you select is irrelevant.
As you can easily see in your build scan, what fails is compiling your tests.
And as you can also easily see is, that you depend on org.spockframework:spock-core:2.2-groovy-3.0 for writing the tests which depends on org.codehaus.groovy:groovy:3.0.12 which is not compatible with Java 21.
The init task is basically just a basic project templating mechanism and does not a thorough Analysis like “what Java version was used to run and what dependencies might or might not be compatible with that version”.
Besides that, I highly recommend you use Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio.
I understand the init task does not a thorough analysis like “what Java version was used to run and what dependencies might or might not be compatible with that version”, but I am wondering why did it pick up among all versions available that specific version instead of simply using the latest stable of spock-core? Seems to me that would be the safest choice.