Groovy 6 compatibility: changes required in Grails, and when each can be removed
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 28/100
- Tipo di issue
- Documentazione
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- groovy, java
- Ambito
- backend, build-system, testing
Direzione di ricerca
Inizia dalla tabella degli elementi rimanenti e dai file indicati, in particolare GrailsWebDataBinder.groovy, GormEntity.groovy, i file di configurazione di Gradle e le impostazioni di compatibilità di Spock. Esegui i test rilevanti del modulo e i controlli di build di Groovy 6 descritti nell’issue. Il lavoro è completato quando ogni workaround mantenuto include il commento richiesto, prove del fallimento, una condizione di eliminazione e una classe di impatto, e build e test hanno esito positivo.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Tracking issue for the changes Apache Grails needs in order to build, test, and ship against Apache Groovy 6. It documents what landed via #15558 on 9.0.x, why each item exists, how it affects applications upgrading from Grails 7/8, and the condition under which it can be deleted.
Current state: Groovy 6.0.0-beta-2, Grails 9 (9.0.x), JDK 21, Spring Boot 4.1, Spock 2.4-groovy-5.0 (no groovy-6.0 artifact published yet).
Every row was established empirically: a workaround was only kept when removing it produced an observed failure, and only removed when the build and tests stayed green without it.
Documentation standard (treat every workaround the same)
Each remaining workaround must have all five of:
- A source comment (or build-file comment) naming Groovy 6 / the specific trigger.
- A pointer to this issue (
#16157). - The observed failure without the change.
- The deletion condition ("remove when X").
- An end-user impact class from the table below.
Do not leave "framework-only" items uncommented while test-only or build-only items are documented, or the reverse.
Impact classes
| Class | Meaning |
|---|---|
| App source | An upgraded application can hit the same Groovy 6 behaviour in its own code and may need the same change |
| App runtime | Framework behaviour the app calls at runtime changed; no app source edit required if they stay on public APIs |
| App test build | The app's test compile/runtime needs a Gradle/Maven flag or extra dependency until an upstream artifact exists |
| Framework only | Confined to Grails internals / this repo's build. Apps do not copy it |
| Permanent | Not a workaround. Keep it |
1. Upstream Groovy 6 regression (not filed upstream)
Static type checking merges the flow state of a || inside a closure to void, so a variable guarded by x == null || ... becomes unusable in the branch body.
@groovy.transform.CompileStatic
class Repro {
void bind(Collection val, Class componentType) {
List boundItems = []
((Collection) val).each { item ->
if (item == null || componentType.isAssignableFrom(item.getClass())) {
boundItems << item // FAILS on 6.0.0-beta-2
}
}
}
}
[Static type checking] - Cannot find matching method java.util.ArrayList#leftShift(void)
The Map form fails equivalently with Cannot find matching method java.util.LinkedHashMap#putAt(java.lang.Object, void).
- Compiles cleanly on Groovy
5.0.8; fails on6.0.0-beta-2. &&in the same position compiles. Only||triggers it.- Workaround: hoist the disjunction into a
booleanlocal. Short-circuiting and null handling are unchanged.
Applied in grails-web-databinding/.../GrailsWebDataBinder.groovy (Collection and Map branches).
Upgrade impact: App source. Any @CompileStatic / @GrailsCompileStatic closure in an application that uses || as a type guard can fail to compile on Groovy 6 until hoisted the same way. The Grails framework change does not alter runtime bind behaviour.
2. Remaining items on 6.0.0-beta-2
| # | File | Groovy 6 behaviour | Observed failure without it | Removable when | End-user impact |
|---|---|---|---|---|---|
| 1 | grails-web-databinding/.../GrailsWebDataBinder.groovy |
|| flow state inside a closure infers as void |
ArrayList#leftShift(void) |
Section 1 is fixed upstream | App source if the app has the same @CompileStatic pattern. Framework bind behaviour unchanged |
| 2 | grails-core/.../config/external/WriterFilteringMap.groovy |
@Delegate now generates mutator methods that were previously excluded |
WriteFilteringMapSpec: getWrittenValues().size() == 0 |
Groovy restores the previous @Delegate mutator exclusion |
App source if the app uses @Delegate the same way. Grails config filtering stays correct because of this change |
| 3 | grails-datamapping-core/.../GormEntity.groovy |
Generic trait method signatures are specialized differently, so trait-injected merge(Object) is not found |
NoSuchMethodException: Book.merge(Object) |
Groovy restores prior generic trait-signature resolution | App runtime. Domain merge() is a public GORM API. Without this, upgraded apps can fail at runtime when calling merge |
| 4 | grails-datastore-core/.../reflect/ClassPropertyFetcher.java |
Interface methods surface differently during property introspection | MissingMethodException ... __transients$get |
Unknown - needs upstream confirmation | App runtime. Property / transients introspection is used by GORM and databinding. Apps should not call this class directly |
| 5 | grails-testing-support-http-client/.../utils/XmlUtils.groovy |
SAX/JAXP feature set recognised by the default parser changed | DOCTYPE is disallowed... |
Unknown. This is XXE-hardening; do not drop it for convenience | App test build if the app uses this testing helper. Not a production runtime change. Keep the hardening |
| 6 | grails-validation/.../ValidateableTraitSpec.groovy |
Static trait methods are emitted with a modifier combination the verifier rejects | illegal combination of modifiers: abstract and static |
Groovy fixes static trait-method emission | App source. Validateable is a public trait. Command objects / domain-like types in the app can fail class verification on Groovy 6 |
| 7 | grails-data-hibernate7/.../HibernateGormInstanceApi.groovy |
Negated instanceof requires explicit parenthesization |
Compile failure | Groovy restores prior parsing precedence | App source if the app has !(x instanceof Foo) under static compile. Framework persistence behaviour unchanged |
| 8 | grails-fields/.../BeanPropertyAccessorImpl.groovy |
@Canonical no longer implies @MapConstructor |
Compile failure | Groovy reinstates implied @MapConstructor, or Grails keeps the explicit annotation permanently |
App source. Apps using @Canonical and expecting a map constructor must add @MapConstructor themselves on Groovy 6 |
| 9 | grails-views-gson/.../GrailsJsonViewHelper.groovy, .../internal/TemplateRenderer.groovy |
Closure/generic inference under @CompileStatic |
Compile failure | Unknown | Framework only unless the app copies these helpers. Gson views keep compiling because of this |
| 10 | grails-testing-support-http-client/.../HttpClientSupport.groovy |
A static final constant in a Spec collides with a trait instance getter |
cannot have both a static and an instance method |
Groovy restores prior static/instance resolution | App test build. Specs that mix a static FORM (or similar) with this trait will fail to compile. Rename the constant or drop the static |
| 11 | gradle/*-test-config.gradle, gradle.properties, CompilePlugin, forge template |
Spock 2.4 is built against Groovy 5 and refuses to run on Groovy 6 | IncompatibleGroovyVersionException / SpockTransform |
Spock ships 2.4-groovy-6.0 (not on Maven Central as of 2026-08-18; latest is 2.4-groovy-5.0. Spock master compiles against Groovy 6.0.0-alpha-2 only) |
App test build. Any app or plugin that compiles/tests with Spock on Groovy 6 must pass -Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true until Spock publishes a groovy-6 artifact. This is the largest end-user item |
| 12 | grails-common/build.gradle, dependencies.gradle |
groovy-callsite is a separate module in Groovy 6 |
Missing class at runtime when indy is off | Never | Permanent. Apps/plugins that compile with indy = false need groovy-callsite on the compile/runtime classpath |
| 13 | build-logic/.../SbomPlugin.groovy |
Groovy 6 pulls JLine 4, whose POM omits the licence SBOM validation expects | SBOM licence validation failure | JLine publishes complete licence metadata | Framework only (Grails repo / SBOM). Not an application concern |
| 14 | settings.gradle |
Micronaut island is pinned to Groovy 5 | Version conflict if included | The Micronaut island supports Groovy 6 (#16161) | App runtime / BOM. Groovy 6 snapshots omit grails-micronaut-*. Apps that depend on Micronaut integration cannot use those artifacts from this line yet |
| 15 | .github/workflows/groovy-joint-workflow.yml |
Groovy 6 development is still on master; GROOVY_6_0_X does not exist |
Joint validation checks out a missing branch | Apache Groovy cuts GROOVY_6_0_X |
Framework only (Grails CI) |
3. Upgrade checklist for application authors (7.x / 8.x -> 9 on Groovy 6)
These are the items an application actually has to do or know. Everything else in the table is absorbed inside Grails.
- Spock. Until
org.spockframework:spock-core:2.4-groovy-6.0exists, add the version-check opt-out on Groovy compile and test JVMs (-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true). Without it,grails-test-coreand any Spec will fail to compile. This is unsupported by Spock and may produce odd runtime errors. groovy-callsite. If the app keepsgrails { indy = false }(the current plugin default), addorg.apache.groovy:groovy-callsiteor inherit it from the Grails BOM.@CompileStatic||guards inside closures. Hoist to abooleanlocal. Same as item 1 in the table.Validateable/ static trait methods. If verification fails withabstract and static, that is Groovy 6 trait emission, not a Grails API break.@Canonicalmap constructors. Add@MapConstructorexplicitly.!(x instanceof T)under static compile: parenthesize!(x instanceof T).- Micronaut.
grails-micronaut-bomand the island are not in Groovy 6 snapshots (#16161). - Do not drop XmlUtils XXE hardening if you copied that helper.
GORM merge(), transients introspection, and config filtering are handled inside Grails. Upgraded apps that stay on public APIs should not need source edits for those.
4. Workarounds retired at 6.0.0-beta-2
| Workaround | Why it is gone |
|---|---|
Gradle 9.6.1 bump |
Never a Groovy 6 requirement |
CoreGrailsPlugin BeanConfiguration.addProperty |
Obsolete after the beanRegistrar rewrite |
GrailsApplicationLifeCycle rewritten as a Java interface |
Groovy 6 handles the default method again. Verified under -PgrailsIndy=false |
| ~30 further snapshot-era compile workarounds | No longer reproduce on 6.0.0-beta-2 |
5. Not Groovy 6
ConfigurationBuildernested-map handling is Spring 7 and lives on8.0.xvia #16160 / #16159. It is not a Groovy 6 workaround.- Embedded MongoDB / Testcontainers failures seen locally are environmental.
Verification
#15558 merged to 9.0.x on 2026-08-18. Snapshot publish is the 9.0.x push CI publish job.
- Lingua principale
- Groovy
- Stelle
- 2.9k
- Fork
- 976
- Merge medio
- 21h 14m
- PR unite (30g)
- 174
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/grails-core
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
apache/grails-core#16635 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
apache/grails-core#16289 · 5 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
apache/grails-core#15764 ·
I maintainer di solito rispondono entro 1 giorno
-
Update documentation for Java 25Forse già presa @ruthst00 l’ha presa 8 giorni fa. Apertarelates-to: documentation weekly-action-item
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
apache/grails-core#15725 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 18/100
apache/grails-core#16634 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di apache/grails-core
Issue simili
-
[BUG]: Prompt compressor crashes with TypeError when a past chat has a non-string response.textForse già presa @ManojDevarajulu l’ha presa oggi. Apertapossible bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
Mintplex-Labs/anything-llm#6737 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 Mezza giornata Idoneità per principianti 62/100
ibm-granite/granite.build#504 ·
I maintainer di solito rispondono entro 2 giorni
-
area/plugin good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
kestra-io/plugin-kestra#200 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
api-platform/core#8690 ·
I maintainer di solito rispondono entro 1 giorno