diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy index fa515941a69..fb0ac407f0e 100644 --- a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/CompilePlugin.groovy @@ -111,6 +111,7 @@ class CompilePlugin implements Plugin { it.options.encoding = StandardCharsets.UTF_8.name() it.options.fork = true it.options.forkOptions.jvmArgs = ['-Xms128M', '-Xmx2G'] + it.options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] if (System.getenv('SUPPRESS_DEPRECATION_WARNINGS') == 'true') { it.options.compilerArgs += ['-Xlint:-removal'] } diff --git a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/SbomPlugin.groovy b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/SbomPlugin.groovy index bbd16832938..f9462f6bb4e 100644 --- a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/SbomPlugin.groovy +++ b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/SbomPlugin.groovy @@ -91,20 +91,21 @@ class SbomPlugin implements Plugin { 'pkg:maven/com.oracle.coherence.ce/coherence-bom@25.03.1?type=pom': 'UPL-1.0', // does not have map based on license id 'pkg:maven/com.oracle.coherence.ce/coherence-bom@25.03.2?type=pom': 'UPL-1.0', // does not have map based on license id 'pkg:maven/com.oracle.coherence.ce/coherence-bom@22.06.2?type=pom': 'UPL-1.0', // does not have map based on license id - 'pkg:maven/jline/jline@2.14.6?type=jar' : 'BSD-2-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205 + 'pkg:maven/jline/jline@2.14.6?type=jar' : 'BSD-2-Clause', // legacy jline:jline group, BSD-2; maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205 'pkg:maven/opensymphony/sitemesh@2.6.0?type=jar' : 'OpenSymphony', // custom license approved by legal LEGAL-707 'pkg:maven/org.antlr/antlr4-runtime@4.7.2?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205 - 'pkg:maven/org.jline/jansi@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline@3.30.6?type=jar' : 'BSD-3-Clause', // direct dependency declared at jline.version in dependencies.gradle - 'pkg:maven/org.jline/jline-builtins@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-console@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-native@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-reader@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-style@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-terminal@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-terminal-jansi@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-terminal-jna@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly - 'pkg:maven/org.jline/jline-terminal-jni@3.30.9?type=jar' : 'BSD-3-Clause', // jline group resolved at 3.30.9 transitively via groovy-groovysh; main org.jline:jline pinned at 3.30.6 directly + 'pkg:maven/org.jline/jansi@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; cyclonedx misreports as BSD-4-Clause (cyclonedx-core-java#205); resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jansi@4.1.0?type=jar' : 'BSD-3-Clause', // jline 4.1.0 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.1.0/LICENSE.txt confirms BSD-3-Clause; cyclonedx misreports as BSD-4-Clause (cyclonedx-core-java#205); resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline@3.30.6?type=jar' : 'BSD-3-Clause', // jline 3.30.6 LICENSE at https://github.com/jline/jline3/blob/jline-parent-3.30.6/LICENSE.txt confirms BSD-3-Clause; direct dependency declared at jline.version in dependencies.gradle + 'pkg:maven/org.jline/jline-builtins@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-console@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-console-ui@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-native@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-reader@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-shell@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-style@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-terminal@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 + 'pkg:maven/org.jline/jline-terminal-jni@4.0.12?type=jar' : 'BSD-3-Clause', // jline 4.0.12 LICENSE.txt at https://github.com/jline/jline3/blob/jline-parent-4.0.12/LICENSE.txt confirms BSD-3-Clause; resolved transitively via groovy-groovysh on Groovy 6 'pkg:maven/org.jruby/jzlib@1.1.5?type=jar' : 'BSD-3-Clause', // https://web.archive.org/web/20240822213507/http://www.jcraft.com/jzlib/LICENSE.txt shows it's a 3 clause 'pkg:maven/org.liquibase.ext/liquibase-hibernate5@4.27.0?type=jar': 'Apache-2.0', // maps incorrectly because of https://github.com/liquibase/liquibase/issues/2445 & the base pom does not define a license ] diff --git a/dependencies.gradle b/dependencies.gradle index 04f629679ce..966a8225f27 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -80,7 +80,7 @@ ext { 'geb-spock.version' : '8.0.1', 'graphql-java.version' : '25.0', 'graphql-java-extended-scalars.version': '24.0', - 'groovy.version' : '5.0.7-SNAPSHOT', + 'groovy.version' : '6.0.0-SNAPSHOT', 'hibernate-groovy-proxy.version': '1.1', 'jakarta-servlet-api.version' : '6.1.0', 'jakarta-validation.version' : '3.1.1', @@ -223,9 +223,9 @@ ext { else if (project.name == 'grails-micronaut-bom') { customBomVersions = [ // Keep aligned with bomDependencyVersions['groovy.version']; the main bom now uses - // Groovy 5, so the micronaut bom must match to avoid validateDependencyVersions + // Groovy 6, so the micronaut bom must match to avoid validateDependencyVersions // failures from transitive dependencies upgrading groovy-bom past the pinned version. - 'groovy.version' : '5.0.7-SNAPSHOT', + 'groovy.version' : '6.0.0-SNAPSHOT', 'spock.version' : '2.4-groovy-5.0', 'protobuf.version': '4.30.2', ] diff --git a/gradle/functional-test-config.gradle b/gradle/functional-test-config.gradle index 062752e5631..9dc5ad98ff0 100644 --- a/gradle/functional-test-config.gradle +++ b/gradle/functional-test-config.gradle @@ -54,11 +54,7 @@ configurations.configureEach { } } -tasks.named('compileTestGroovy') { - options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] -} - -tasks.named('compileGroovy') { +tasks.withType(GroovyCompile).configureEach { options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] } diff --git a/gradle/hibernate5-test-config.gradle b/gradle/hibernate5-test-config.gradle index 667b9e61b8e..85fadc0a888 100644 --- a/gradle/hibernate5-test-config.gradle +++ b/gradle/hibernate5-test-config.gradle @@ -26,6 +26,10 @@ dependencies { add('testRuntimeOnly', 'org.objenesis:objenesis') } +tasks.withType(GroovyCompile).configureEach { + options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] +} + tasks.withType(Test).configureEach { // Honor DO_NOT_CACHE_TESTS=1 so developers can repeatedly invoke the same test command // without --rerun-tasks (and without recompiling everything else). diff --git a/gradle/mongodb-forked-test-config.gradle b/gradle/mongodb-forked-test-config.gradle index 7166c983239..032fadde7f4 100644 --- a/gradle/mongodb-forked-test-config.gradle +++ b/gradle/mongodb-forked-test-config.gradle @@ -26,6 +26,10 @@ dependencies { add('testRuntimeOnly', 'org.objenesis:objenesis') } +tasks.withType(GroovyCompile).configureEach { + options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] +} + tasks.named('compileTestGroovy', GroovyCompile) { groovyOptions.forkOptions.jvmArgs = ['-Xmx768m'] } diff --git a/gradle/mongodb-test-config.gradle b/gradle/mongodb-test-config.gradle index 7d140e899f3..65e5cf0c6b7 100644 --- a/gradle/mongodb-test-config.gradle +++ b/gradle/mongodb-test-config.gradle @@ -26,6 +26,10 @@ dependencies { add('testRuntimeOnly', 'org.objenesis:objenesis') } +tasks.withType(GroovyCompile).configureEach { + options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] +} + tasks.named('compileTestGroovy', GroovyCompile) { groovyOptions.forkOptions.jvmArgs = ['-Xmx768m'] } diff --git a/gradle/test-config.gradle b/gradle/test-config.gradle index ddc0163fa16..32344e61857 100644 --- a/gradle/test-config.gradle +++ b/gradle/test-config.gradle @@ -35,11 +35,12 @@ dependencies { add('testRuntimeOnly', 'org.objenesis:objenesis') } -tasks.named('compileTestGroovy') { - options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] -} - -tasks.named('compileGroovy') { +// Disable Spock's compile-time Groovy version check on ALL Groovy compile +// tasks. Spock's SpockTransform is registered via META-INF services and +// the Groovy compiler loads every AST transform on the classpath, so even +// main source sets trip the version check when Groovy is newer than the +// Spock artifact's groovy variant. +tasks.withType(GroovyCompile).configureEach { options.forkOptions.jvmArgs += ['-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true'] } diff --git a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java index 280249d6fed..8bd79d2fa33 100644 --- a/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java +++ b/grails-controllers/src/main/groovy/org/grails/compiler/web/ControllerActionTransformer.java @@ -73,7 +73,6 @@ import org.codehaus.groovy.classgen.GeneratorContext; import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.syntax.Token; import org.codehaus.groovy.syntax.Types; import org.codehaus.groovy.transform.trait.Traits; @@ -267,12 +266,12 @@ private void processMethods(ClassNode classNode, SourceUnit source, if (methodShouldBeConfiguredAsControllerAction(method)) { final List declaredMethodsWithThisName = classNode.getDeclaredMethods(method.getName()); if (declaredMethodsWithThisName != null) { - final int numberOfNonExceptionHandlerMethodsWithThisName = DefaultGroovyMethods.count((Iterable) declaredMethodsWithThisName, new Closure(this) { - @Override - public Object call(Object object) { - return !isExceptionHandlingMethod((MethodNode) object); + int numberOfNonExceptionHandlerMethodsWithThisName = 0; + for (MethodNode candidate : declaredMethodsWithThisName) { + if (!isExceptionHandlingMethod(candidate)) { + numberOfNonExceptionHandlerMethodsWithThisName++; } - }).intValue(); + } if (numberOfNonExceptionHandlerMethodsWithThisName > 1) { String message = "Controller actions may not be overloaded. The [" + method.getName() + diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy index dae59760d87..ca8b8b19d2c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy @@ -39,6 +39,7 @@ import org.grails.datastore.mapping.model.types.ToOne import org.grails.datastore.mapping.query.api.BuildableCriteria import org.grails.datastore.mapping.query.api.Criteria import org.grails.datastore.mapping.reflect.EntityReflector +import org.codehaus.groovy.runtime.InvokerHelper /** * @@ -590,7 +591,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi + apply plugin: 'org.apache.grails.gradle.grails-web' dependencies { diff --git a/grails-test-examples/micronaut-groovy-only/build.gradle b/grails-test-examples/micronaut-groovy-only/build.gradle index 62abb364315..32b731c1a40 100644 --- a/grails-test-examples/micronaut-groovy-only/build.gradle +++ b/grails-test-examples/micronaut-groovy-only/build.gradle @@ -25,6 +25,13 @@ plugins { version = '0.1' group = 'micronautgroovyonly' +// Groovy 6.0.0-SNAPSHOT requires asm 9.10 (for JDK 27 bytecode support), while +// the grails-micronaut-bom inherits asm 9.9.1 from Spring Boot 4 / Micronaut +// platform. The divergence is intentional on this canary; un-pin via the +// validator plugin's allowedBomOverrides mechanism (see GrailsDependencyValidatorPlugin +// `ALLOWED_OVERRIDES_EXT` for the contract). +ext.allowedBomOverrides = ['org.ow2.asm:asm', 'org.ow2.asm:asm-util'] as Set + apply plugin: 'org.apache.grails.gradle.grails-web' // This module intentionally has NO annotationProcessor dependencies. diff --git a/grails-test-examples/micronaut/build.gradle b/grails-test-examples/micronaut/build.gradle index 3a3c4e527b7..906e84f6d3e 100644 --- a/grails-test-examples/micronaut/build.gradle +++ b/grails-test-examples/micronaut/build.gradle @@ -27,6 +27,13 @@ plugins { version = '0.1' group = 'micronaut' +// Groovy 6.0.0-SNAPSHOT requires asm 9.10 (for JDK 27 bytecode support), while +// the grails-micronaut-bom inherits asm 9.9.1 from Spring Boot 4 / Micronaut +// platform. The divergence is intentional on this canary; un-pin via the +// validator plugin's allowedBomOverrides mechanism (see GrailsDependencyValidatorPlugin +// `ALLOWED_OVERRIDES_EXT` for the contract). +ext.allowedBomOverrides = ['org.ow2.asm:asm', 'org.ow2.asm:asm-util'] as Set + apply plugin: 'org.apache.grails.gradle.grails-web' apply plugin: 'cloud.wondrify.asset-pipeline' diff --git a/grails-test-examples/plugins/micronaut-singleton/build.gradle b/grails-test-examples/plugins/micronaut-singleton/build.gradle index 96d97930f73..d0154439656 100644 --- a/grails-test-examples/plugins/micronaut-singleton/build.gradle +++ b/grails-test-examples/plugins/micronaut-singleton/build.gradle @@ -25,6 +25,13 @@ plugins { version = '0.1-SNAPSHOT' group = 'com.example.grails.plugins' +// Groovy 6.0.0-SNAPSHOT requires asm 9.10 (for JDK 27 bytecode support), while +// the grails-micronaut-bom inherits asm 9.9.1 from Spring Boot 4 / Micronaut +// platform. The divergence is intentional on this canary; un-pin via the +// validator plugin's allowedBomOverrides mechanism (see GrailsDependencyValidatorPlugin +// `ALLOWED_OVERRIDES_EXT` for the contract). +ext.allowedBomOverrides = ['org.ow2.asm:asm', 'org.ow2.asm:asm-util'] as Set + apply plugin: 'org.apache.grails.gradle.grails-plugin' dependencies { diff --git a/grails-validation/src/main/groovy/grails/validation/Validateable.groovy b/grails-validation/src/main/groovy/grails/validation/Validateable.groovy index 827c851e8f4..bdcc1ec1977 100644 --- a/grails-validation/src/main/groovy/grails/validation/Validateable.groovy +++ b/grails-validation/src/main/groovy/grails/validation/Validateable.groovy @@ -286,9 +286,10 @@ trait Validateable { * override semantics. Starting in Groovy 5, {@code TraitReceiverTransformer} * rewrites {@code this.defaultNullable()} from another method inside the * trait body to a direct call into the trait helper's static method, - * silently losing any implementing-class override. - * {@link java.lang.reflect.Method#invoke} is opaque to the transform so it - * dispatches to the implementing-class bytecode directly. + * silently losing any implementing-class override. The same regression + * is present in Groovy 6.0.0-SNAPSHOT. {@link java.lang.reflect.Method#invoke} + * is opaque to the transform so it dispatches to the implementing-class + * bytecode directly. * * Standalone reproducer: * https://github.com/jamesfredley/groovy-trait-static-method-override-bug diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/view/api/internal/TemplateRenderer.groovy b/grails-views-gson/src/main/groovy/grails/plugin/json/view/api/internal/TemplateRenderer.groovy index 905a7ad385f..d079a46a8e4 100644 --- a/grails-views-gson/src/main/groovy/grails/plugin/json/view/api/internal/TemplateRenderer.groovy +++ b/grails-views-gson/src/main/groovy/grails/plugin/json/view/api/internal/TemplateRenderer.groovy @@ -19,8 +19,10 @@ package grails.plugin.json.view.api.internal +import groovy.json.StreamingJsonBuilder import groovy.transform.CompileStatic +import grails.plugin.json.builder.JsonOutput import grails.plugin.json.view.api.GrailsJsonViewHelper import grails.util.GrailsNameUtils @@ -39,6 +41,36 @@ class TemplateRenderer { this.jsonViewHelper = jsonViewHelper } + // Explicit forwarders for the 5 GrailsJsonViewHelper#render(...) overloads. + // Under Groovy 6.0.0-SNAPSHOT the @Delegate AST transform no longer satisfies + // the abstract-method-implementation check for interface methods whose return + // type is an inner class (here JsonOutput.JsonWritable): the @CompileStatic + // verifier runs before @Delegate generates the forwarders, so the compiler + // reports "Can't have an abstract method in a non-abstract class". + // The 5 inline(...) overloads return void and are unaffected, so @Delegate + // still handles them. Behaviour is identical to what @Delegate generates on + // Groovy 5. + + JsonOutput.JsonWritable render(Map arguments) { + jsonViewHelper.render(arguments) + } + + JsonOutput.JsonWritable render(Object object, Map arguments, @DelegatesTo(StreamingJsonBuilder.StreamingJsonDelegate) Closure customizer) { + jsonViewHelper.render(object, arguments, customizer) + } + + JsonOutput.JsonWritable render(Object object, Map arguments) { + jsonViewHelper.render(object, arguments) + } + + JsonOutput.JsonWritable render(Object object) { + jsonViewHelper.render(object) + } + + JsonOutput.JsonWritable render(Object object, @DelegatesTo(StreamingJsonBuilder.StreamingJsonDelegate) Closure customizer) { + jsonViewHelper.render(object, customizer) + } + @Override Object invokeMethod(String name, Object args) { Object[] argArray = (Object[]) args