Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
013cb13
canary: test Groovy 6.0.0-SNAPSHOT
jamesfredley Apr 5, 2026
4463494
fix: Groovy 6 VerifyError in DefaultConstraintFactory default parameter
jamesfredley Apr 5, 2026
ba0df88
Merge branch 'grails8-groovy5-sb4' into grails8-groovy6-canary
jamesfredley Apr 6, 2026
c19037d
fix: Groovy 6 compile fixes - Spock version check and CycloneDX license
jamesfredley Apr 6, 2026
ddd7325
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 6, 2026
0dcb652
fix: Groovy 6 genericGetMethod regression breaks property access on G…
jamesfredley Apr 6, 2026
a6d06f5
fix: GormEntity.get(String) throws MissingPropertyException when GORM…
jamesfredley Apr 6, 2026
99bf0be
fix: centralize Spock version check and add jline 4.0.7 CycloneDX ove…
jamesfredley Apr 6, 2026
8e4fba5
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 6, 2026
cfd7605
fix: Groovy 6 remaining test fixes
jamesfredley Apr 6, 2026
b2bd213
fix: resolve all remaining test failures on Groovy 6
jamesfredley Apr 6, 2026
24eb53d
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 6, 2026
027c203
fix: CodeNarc UnnecessaryDotClass in DefaultConstraintFactory
jamesfredley Apr 6, 2026
b225663
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 6, 2026
b9ac44c
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 6, 2026
52aad53
fix: GormEntity.get(String) delegates to staticPropertyMissing for GO…
jamesfredley Apr 6, 2026
ea41a40
Merge branch 'grails8-groovy5-sb4' into grails8-groovy6-canary
jamesfredley Apr 25, 2026
678bdf1
fix: harden Groovy 6 canary against snapshot drift and add regression…
jamesfredley Apr 25, 2026
c2aa269
fix: Groovy 6 closure dispatch regression in ControllerActionTransformer
jamesfredley Apr 25, 2026
8e9cdbc
fix: move Groovy 6 generic-getter guard from GormEntity trait to AST
jamesfredley Apr 25, 2026
ddc7ea2
fix: serialise GSP compilation under Groovy 6 to dodge ListHashMap race
jamesfredley Apr 25, 2026
95e9212
style: drop a leftover consecutive blank line in GormEntity
jamesfredley Apr 25, 2026
54b718b
fix(sbom): revert LICENSE_GROUP_MAPPING per @jdaugherty review
jamesfredley Apr 25, 2026
2619635
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 25, 2026
48598b4
test(forge): capture both stdout and stderr from generated-app gradle…
jamesfredley Apr 25, 2026
5d71eb4
fix(forge): bypass Spock Groovy-version check in generated app build.…
jamesfredley Apr 25, 2026
18b9e52
fix: serialise GSON/views template compilation under Groovy 6
jamesfredley Apr 25, 2026
3e9f517
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 25, 2026
de1cf4a
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley Apr 25, 2026
8af3b23
docs: drop incorrect GROOVY-11829 citation from GormEntity workaround…
jamesfredley Apr 26, 2026
3f485f3
Merge grails8-groovy5-sb4 audit work into grails8-groovy6-canary
jamesfredley Apr 27, 2026
ee77652
Add standalone reproducer link to GormEntity get(String) AST shim
jamesfredley Apr 27, 2026
fb717d3
Validateable: link standalone reproducer for the TraitReceiverTransfo…
jamesfredley Apr 27, 2026
e7f2478
Merge grails8-groovy5-sb4: link reproducer + Validateable javadoc + r…
jamesfredley Apr 27, 2026
e6332ed
ContainerSupport: link upstream PR #2495 (GROOVY-11968) and standalon…
jamesfredley Apr 27, 2026
367dad7
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
May 2, 2026
2a5e983
drop Groovy 6 workarounds whose upstream fixes have merged
May 2, 2026
4a51898
fix: workaround Groovy 6 stub generator regression in HibernateSettings
May 2, 2026
449c766
Merge branch 'grails8-groovy5-sb4' into grails8-groovy6-canary
jamesfredley May 2, 2026
a69a157
Merge remote-tracking branch 'origin/grails8-groovy5-sb4' into grails…
jamesfredley May 3, 2026
bd7a30a
Drop two more Groovy 6 workarounds - upstream fixes merged 2026-05-02
jamesfredley May 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,34 +91,32 @@ class SbomPlugin implements Plugin<Project> {
'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', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jansi@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline@3.23.0?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-builtins@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-builtins@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-console@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-console@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-console-ui@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-native@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-native@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-reader@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-reader@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-shell@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-style@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-style@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal-jansi@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal-jna@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal-jni@3.30.9?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'pkg:maven/org.jline/jline-terminal-jni@4.0.7?type=jar' : 'BSD-3-Clause', // maps incorrectly because of https://github.com/CycloneDX/cyclonedx-core-java/issues/205
'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
]

/**
* Group-level license overrides applied AFTER {@link #LICENSE_MAPPING} fails to match.
* The key is a purl prefix (e.g. {@code 'pkg:maven/org.jline/'}) and the value is the
* SPDX license id to force for any artifact whose bomRef starts with that prefix.
*
* This exists for groups that:
* (a) have a stable license across all artifacts and versions, AND
* (b) suffer from cyclonedx-core-java#205 (license is misreported), AND
* (c) are pulled transitively by SNAPSHOT dependencies (e.g. groovy-groovysh ->
* org.jline:* drifts on every Groovy SNAPSHOT bump), making per-version entries
* unmaintainable.
*
* Only add a group entry when ALL three conditions hold. Per-version entries in
* {@link #LICENSE_MAPPING} should still be preferred for one-off overrides.
*/
private static Map<String, String> LICENSE_GROUP_MAPPING = [
'pkg:maven/org.jline/': 'BSD-3-Clause', // entire org.jline group is BSD-3-Clause; cyclonedx misreports it (cyclonedx-core-java#205) and versions drift via groovy-groovysh on every SNAPSHOT bump
Comment thread
jamesfredley marked this conversation as resolved.
Outdated
]

// we don't distribute these so these licenses are considered acceptable, but we still prefer ASF licenses.
// Require a whitelist of any case of category X licenses to prevent accidental inclusion in a distributed artifact
// this list will need to be updated anytime we change versions so we can revise the licenses
Expand Down Expand Up @@ -338,6 +336,21 @@ class SbomPlugin implements Plugin<Project> {
return licenseBlock
}

// Fallback: group-level override matched by purl prefix. See LICENSE_GROUP_MAPPING
// for criteria (stable license + cyclonedx misreport + SNAPSHOT version drift).
def groupOverride = LICENSE_GROUP_MAPPING.find { prefix, _ -> bomRef.startsWith(prefix) }
if (groupOverride) {
def licenseId = groupOverride.value
logger.lifecycle('Forcing license for {} to {} via group rule {}', bomRef, licenseId, groupOverride.key)

def licenseBlock = LICENSES[licenseId]
if (!licenseBlock) {
throw new GradleException("Cannot find license information for id ${licenseId} to use for bomRef ${bomRef} in project ${projectName}")
}

return licenseBlock
}

if (!(licenseChoices instanceof List) || licenseChoices.isEmpty()) {
throw new GradleException("No License was found for dependency: ${bomRef} in project ${projectName}")
}
Expand Down
1 change: 0 additions & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ ext {
'commons-lang3.version' : '3.20.0',
'geb-spock.version' : '8.0.1',
'groovy.version' : '6.0.0-SNAPSHOT',
'jackson.version' : '2.21.2',
'jquery.version' : '3.7.1',
'liquibase-hibernate5.version': '4.27.0',
'mongodb.version' : '5.6.4',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -267,12 +266,12 @@ private void processMethods(ClassNode classNode, SourceUnit source,
if (methodShouldBeConfiguredAsControllerAction(method)) {
final List<MethodNode> 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() +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,17 +593,27 @@ trait GormEntity<D> implements GormValidateable, DirtyCheckable, GormEntityApi<D
/**
* Retrieves an object from the datastore. eg. Book.get(1)
*
* Groovy 6 registers this as the genericGetMethod for dynamic property
* resolution (GROOVY-xxxxx). The String overload below intercepts property-
* style calls like {@code Entity.name} and delegates to Class.class when the
* property belongs to java.lang.Class, preventing false "GORM not initialized"
* errors.
* Groovy 6 (GROOVY-11829) relaxed {@code MetaClassImpl.isGenericGetMethod} to
* accept {@code get(Serializable)} as a generic property getter where Groovy 5
* required {@code get(String)}. Without the {@link #get(String)} overload below,
* every dynamic property access on a GORM entity (e.g. {@code Book.name},
* {@code Book.simpleName}) routes through this method instead of
* {@link Class#getName()}, breaking property resolution and triggering false
* "GORM not initialized" errors during class loading.
*/
@Generated
static D get(Serializable id) {
currentGormStaticApi().get(id)
}

/**
* Groovy 6 generic-property-getter overload (see GROOVY-11829). Resolves
* {@link Class} bean properties first, then falls back to GORM's
* {@code propertyMissing} (handles datasource qualifiers and dynamic GORM
* properties), and finally to {@link #get(Serializable)} for entity-by-ID
* lookups. Throws {@link MissingPropertyException} when nothing matches so
* Groovy's MOP can continue normal property resolution.
*/
@Generated
static Object get(String nameOrId) {
MetaProperty mp = InvokerHelper.getMetaClass(Class).hasProperty(this, nameOrId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ class MappingContextAwareConstraintFactory extends DefaultConstraintFactory {

final MappingContext mappingContext

MappingContextAwareConstraintFactory(Class<? extends Constraint> constraintClass, MessageSource messageSource, MappingContext mappingContext, List<Class> targetTypes = [Object]) {
MappingContextAwareConstraintFactory(Class<? extends Constraint> constraintClass, MessageSource messageSource, MappingContext mappingContext) {
this(constraintClass, messageSource, mappingContext, [Object] as List<Class>)
}

MappingContextAwareConstraintFactory(Class<? extends Constraint> constraintClass, MessageSource messageSource, MappingContext mappingContext, List<Class> targetTypes) {
super(constraintClass, messageSource, targetTypes)
this.mappingContext = mappingContext
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,38 @@ class GormEntityTransformSpec extends Specification{
thrown(MissingPropertyException)
}

void 'test Groovy 6 genericGetMethod regression workaround (GROOVY-11829)'() {
expect: 'Class bean properties remain accessible via dynamic property access (the workaround target)'
Book.simpleName == 'Book'
Book.name.endsWith('Book')

and: 'the get(String) Groovy-6 compatibility overload exists and is @Generated'
def getStringMethod = Book.getMethod('get', String)
getStringMethod != null
getStringMethod.isAnnotationPresent(Generated)

and: 'the original get(Serializable) overload still exists for entity-by-id lookups'
def getSerializableMethod = Book.getMethod('get', Serializable)
getSerializableMethod != null
getSerializableMethod.isAnnotationPresent(Generated)
}

void 'test get(String) throws MissingPropertyException when GORM not initialized and string is not a Class property'() {
when: 'a name that is neither a Class property nor a known qualifier is passed'
Book.get('definitelyNotAClassPropertyOrEntityIdABCXYZ')

then: 'we do NOT leak the IllegalStateException raised by uninitialized GORM'
thrown(MissingPropertyException)
}

void 'test get(String) returns Class bean property when name matches Class property and GORM not initialized'() {
expect: 'explicit get("simpleName") returns the Class.simpleName because the Groovy 6 generic-getter workaround intercepts Class properties before delegating to the GORM static API'
Book.get('simpleName') == 'Book'

and: 'this is a documented behavior change vs Grails on Groovy 5: prior to GROOVY-11829, Book.get("simpleName") would call get(Serializable) and attempt an entity-by-id lookup. See GormEntity.get(String) docstring.'
Book.get('canonicalName') == Book.canonicalName
}

void 'test that all GormEntity/GormValidateable trait methods are marked as Generated'() {

expect: 'all GormEntity methods are marked as Generated on implementation class'
Expand Down
Loading