You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ma...@apache.org on 2026/06/08 13:40:03 UTC
(grails-core) 01/01: refactor: replace usages of deprecated external APIs
This is an automated email from the ASF dual-hosted git repository.
matrei pushed a commit to branch remove-depr-warnings
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 504105fbbfbaf8c6ea327355b8b121984ad7cf9a
Author: Mattias Reichel <ma...@gmail.com>
AuthorDate: Mon Jun 8 15:39:14 2026 +0200
refactor: replace usages of deprecated external APIs
---
.../internal/DelegateAsyncTransformation.java | 30 ++----
.../groovy/grails/async/DelegateAsyncSpec.groovy | 105 +++++++++++++++++++++
.../transform/DelegateAsyncTransformation.java | 27 ------
.../datastore/mapping/reflect/NameUtils.java | 4 +-
.../org/grails/buffer/GrailsPrintWriter.java | 3 +-
.../Sitemesh3EnvironmentPostProcessor.java | 2 +-
.../java/grails/gsp/boot/GspAutoConfiguration.java | 2 +-
.../org/grails/support/MockApplicationContext.java | 3 +-
.../grails/web/databinding/DataBindingUtils.java | 12 ++-
.../org/grails/web/mapping/RegexUrlMapping.java | 4 +-
.../src/main/java/grails/init/GrailsUpdater.java | 9 +-
11 files changed, 141 insertions(+), 60 deletions(-)
diff --git a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java
index a776e0644d..7ba30826f6 100644
--- a/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java
+++ b/grails-async/core/src/main/groovy/org/grails/async/transform/internal/DelegateAsyncTransformation.java
@@ -20,9 +20,7 @@ package org.grails.async.transform.internal;
import java.beans.Introspector;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import groovy.lang.Closure;
@@ -173,28 +171,14 @@ public class DelegateAsyncTransformation implements ASTTransformation, Transform
}
private static ClassNode alignReturnType(final ClassNode receiver, final ClassNode originalReturnType) {
- ClassNode copiedReturnType = originalReturnType.getPlainNodeReference();
-
- List<GenericsType> redirectTypes = new ArrayList<>();
- if (receiver.redirect().getGenericsTypes() != null) {
- Collections.addAll(redirectTypes, receiver.redirect().getGenericsTypes());
+ if (!originalReturnType.isUsingGenerics()) {
+ return originalReturnType.getPlainNodeReference();
}
- if (!redirectTypes.isEmpty()) {
- GenericsType[] redirectReceiverTypes = redirectTypes.toArray(new GenericsType[0]);
-
- GenericsType[] receiverParameterizedTypes = receiver.getGenericsTypes();
- if (receiverParameterizedTypes == null) {
- receiverParameterizedTypes = redirectReceiverTypes;
- }
-
- if (originalReturnType.isUsingGenerics()) {
- GenericsType[] alignmentTypes = originalReturnType.getGenericsTypes();
- GenericsType[] genericsTypes = GenericsUtils.alignGenericTypes(redirectReceiverTypes, receiverParameterizedTypes, alignmentTypes);
- copiedReturnType.setGenericsTypes(genericsTypes);
- }
- }
-
- return copiedReturnType;
+ var genericsSpec = GenericsUtils.createGenericsSpec(receiver);
+ var correctedReturnType = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, originalReturnType);
+ return correctedReturnType == null
+ ? originalReturnType.getPlainNodeReference()
+ : correctedReturnType;
}
protected DelegateAsyncTransactionalMethodTransformer lookupAsyncTransactionalMethodTransformer() {
diff --git a/grails-async/core/src/test/groovy/grails/async/DelegateAsyncSpec.groovy b/grails-async/core/src/test/groovy/grails/async/DelegateAsyncSpec.groovy
index 6ed9ea4d54..2504e74835 100644
--- a/grails-async/core/src/test/groovy/grails/async/DelegateAsyncSpec.groovy
+++ b/grails-async/core/src/test/groovy/grails/async/DelegateAsyncSpec.groovy
@@ -75,6 +75,92 @@ class DelegateAsyncSpec extends Specification {
then: 'the decorator is applied to the value'
val == 6
}
+
+ void 'Delegate async transform preserves generic return type for static compilation'() {
+ when:
+ def result = new GroovyShell().evaluate('''
+ import grails.async.*
+ import groovy.transform.CompileStatic
+
+ class GenericService<T> {
+ T echo(T value) { value }
+ }
+
+ class AsyncStringService {
+ @DelegateAsync
+ GenericService<String> service = new GenericService<String>()
+ }
+
+ @CompileStatic
+ String test() {
+ Promise<String> p = new AsyncStringService().echo('hello')
+ p.get()
+ }
+
+ test()
+ ''')
+
+ then:
+ result == 'hello'
+ }
+
+ void 'Delegate async transform aligns generic return type from inherited interface method'() {
+ when:
+ def service = new AsyncStringHolderService()
+ def p = service.get()
+
+ then:
+ p instanceof Promise
+
+ and:
+ p.get() == 'hello'
+ }
+
+ void 'Delegate async transform preserves generic return type from inherited interface method for static compilation'() {
+ when:
+ def result = new GroovyShell().evaluate('''
+ import grails.async.*
+ import groovy.transform.CompileStatic
+
+ interface Holder<T> {
+ T get()
+ }
+
+ class StringHolder implements Holder<String> {
+ @Override
+ String get() {
+ 'hello'
+ }
+ }
+
+ @DelegateAsync(StringHolder)
+ class AsyncStringHolderService {
+ }
+
+ @CompileStatic
+ String test() {
+ Promise<String> p = new AsyncStringHolderService().get()
+ p.get()
+ }
+
+ test()
+ ''')
+
+ then:
+ result == 'hello'
+ }
+
+ void 'Delegate async transform aligns generic return type from parameterized interface field'() {
+ when:
+ def service = new AsyncParameterizedHolderService()
+ def p = service.get()
+
+ then:
+ p instanceof Promise
+
+ and:
+ p.get() == 'hello'
+ }
}
class MathService {
@@ -103,3 +189,22 @@ class AsyncMathService3 implements PromiseDecoratorProvider {
]
}
+interface Holder<T> {
+ T get()
+}
+
+class StringHolder implements Holder<String> {
+ @Override
+ String get() {
+ 'hello'
+ }
+}
+
+@DelegateAsync(StringHolder)
+class AsyncStringHolderService {
+}
+
+class AsyncParameterizedHolderService {
+ @DelegateAsync
+ Holder<String> holder = new StringHolder()
+}
\ No newline at end of file
diff --git a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java
index 11e20dbad3..f7042f25e2 100644
--- a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java
+++ b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java
@@ -23,7 +23,6 @@ import java.beans.Introspector;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -182,32 +181,6 @@ public class DelegateAsyncTransformation implements ASTTransformation, Transform
return names;
}
- private static ClassNode alignReturnType(final ClassNode receiver, final ClassNode originalReturnType) {
- ClassNode copiedReturnType = originalReturnType.getPlainNodeReference();
-
- ClassNode actualReceiver = receiver;
- List<GenericsType> redirectTypes = new ArrayList<>();
- if (actualReceiver.redirect().getGenericsTypes() != null) {
- Collections.addAll(redirectTypes, actualReceiver.redirect().getGenericsTypes());
- }
- if (!redirectTypes.isEmpty()) {
- GenericsType[] redirectReceiverTypes = redirectTypes.toArray(new GenericsType[redirectTypes.size()]);
-
- GenericsType[] receiverParameterizedTypes = actualReceiver.getGenericsTypes();
- if (receiverParameterizedTypes == null) {
- receiverParameterizedTypes = redirectReceiverTypes;
- }
-
- if (originalReturnType.isUsingGenerics()) {
- GenericsType[] alignmentTypes = originalReturnType.getGenericsTypes();
- GenericsType[] genericsTypes = GenericsUtils.alignGenericTypes(redirectReceiverTypes, receiverParameterizedTypes, alignmentTypes);
- copiedReturnType.setGenericsTypes(genericsTypes);
- }
- }
-
- return copiedReturnType;
- }
-
private static boolean isCandidateMethod(MethodNode declaredMethod) {
ClassNode groovyMethods = GROOVY_OBJECT_CLASS_NODE;
String methodName = declaredMethod.getName();
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java
index c831c62f4f..d3a988c731 100644
--- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java
+++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/reflect/NameUtils.java
@@ -20,7 +20,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-import org.codehaus.groovy.runtime.MetaClassHelper;
+import org.apache.groovy.util.BeanUtils;
import org.grails.datastore.mapping.model.config.GormProperties;
@@ -158,6 +158,6 @@ public class NameUtils {
* @return The class name
*/
public static String capitalize(String name) {
- return MetaClassHelper.capitalize(name);
+ return BeanUtils.capitalize(name);
}
}
diff --git a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java
index 08fac4e59c..a387f9ac9a 100644
--- a/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java
+++ b/grails-encoder/src/main/groovy/org/grails/buffer/GrailsPrintWriter.java
@@ -25,6 +25,7 @@ import java.io.Writer;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.lang.Writable;
+import org.codehaus.groovy.runtime.FormatHelper;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
@@ -133,7 +134,7 @@ public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, En
}
}
else {
- InvokerHelper.write(this, obj);
+ FormatHelper.write(this, obj);
}
return this;
}
diff --git a/grails-gsp/grails-sitemesh3/src/main/java/org/grails/plugins/sitemesh3/Sitemesh3EnvironmentPostProcessor.java b/grails-gsp/grails-sitemesh3/src/main/java/org/grails/plugins/sitemesh3/Sitemesh3EnvironmentPostProcessor.java
index b43dfa88dc..becc35034f 100644
--- a/grails-gsp/grails-sitemesh3/src/main/java/org/grails/plugins/sitemesh3/Sitemesh3EnvironmentPostProcessor.java
+++ b/grails-gsp/grails-sitemesh3/src/main/java/org/grails/plugins/sitemesh3/Sitemesh3EnvironmentPostProcessor.java
@@ -21,8 +21,8 @@ package org.grails.plugins.sitemesh3;
import java.util.HashMap;
import java.util.Map;
+import org.springframework.boot.EnvironmentPostProcessor;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
diff --git a/grails-gsp/spring-boot/src/main/java/grails/gsp/boot/GspAutoConfiguration.java b/grails-gsp/spring-boot/src/main/java/grails/gsp/boot/GspAutoConfiguration.java
index 79ec59002f..d32d50f72c 100644
--- a/grails-gsp/spring-boot/src/main/java/grails/gsp/boot/GspAutoConfiguration.java
+++ b/grails-gsp/spring-boot/src/main/java/grails/gsp/boot/GspAutoConfiguration.java
@@ -157,7 +157,7 @@ public class GspAutoConfiguration {
if (rootPath.endsWith("/")) {
rootPath = rootPath.substring(0, rootPath.length() - 1);
}
- if (!StringUtils.isEmpty(rootPath)) {
+ if (StringUtils.hasLength(rootPath)) {
rootPaths.add(rootPath);
}
}
diff --git a/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java b/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java
index 2e0efbad08..d0e7ce29df 100644
--- a/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java
+++ b/grails-test-suite-base/src/main/groovy/org/grails/support/MockApplicationContext.java
@@ -36,6 +36,8 @@ import groovy.lang.GroovyObjectSupport;
import jakarta.servlet.ServletContext;
+import org.jspecify.annotations.NonNull;
+
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactory;
@@ -53,7 +55,6 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
-import org.springframework.lang.NonNull;
import org.springframework.mock.web.MockServletContext;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
diff --git a/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java b/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java
index 55d23ed67f..4290f85550 100644
--- a/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java
+++ b/grails-web-databinding/src/main/groovy/grails/web/databinding/DataBindingUtils.java
@@ -19,6 +19,7 @@
package grails.web.databinding;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
@@ -179,7 +180,16 @@ public class DataBindingUtils {
}
final List<DataBindingSource> dataBindingSources = collectionBindingSource.getDataBindingSources();
for (final DataBindingSource dataBindingSource : dataBindingSources) {
- final T newObject = targetType.newInstance();
+ T newObject;
+ try {
+ newObject = targetType.getDeclaredConstructor().newInstance();
+ } catch(NoSuchMethodException | InvocationTargetException ex) {
+ throw new IllegalStateException(
+ "Could not instantiate class [" + targetType.getName() + "]",
+ ex
+ );
+ }
+
bindObjectToDomainInstance(entity, newObject, dataBindingSource, getBindingIncludeList(newObject), Collections.emptyList(), null);
collectionToPopulate.add(newObject);
}
diff --git a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java
index 5069852412..8aa4143d78 100644
--- a/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java
+++ b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/RegexUrlMapping.java
@@ -656,7 +656,7 @@ public class RegexUrlMapping extends AbstractUrlMapping {
}
}
// if the format is specified but the value is empty, ignore it
- if (!(FORMAT_PARAMETER.equals(propertyName) && GrailsStringUtils.isEmpty(lastGroup))) {
+ if (!(FORMAT_PARAMETER.equals(propertyName) && !GrailsStringUtils.hasLength(lastGroup))) {
params.put(propertyName, lastGroup);
}
break;
@@ -680,7 +680,7 @@ public class RegexUrlMapping extends AbstractUrlMapping {
lastGroup = lastGroup.substring(1);
}
// if the format is specified but the value is empty, ignore it
- if (!(FORMAT_PARAMETER.equals(propertyName) && GrailsStringUtils.isEmpty(lastGroup))) {
+ if (!(FORMAT_PARAMETER.equals(propertyName) && !GrailsStringUtils.hasLength(lastGroup))) {
params.put(propertyName, lastGroup);
}
}
diff --git a/grails-wrapper/src/main/java/grails/init/GrailsUpdater.java b/grails-wrapper/src/main/java/grails/init/GrailsUpdater.java
index d1c7e84c0b..073901a04f 100644
--- a/grails-wrapper/src/main/java/grails/init/GrailsUpdater.java
+++ b/grails-wrapper/src/main/java/grails/init/GrailsUpdater.java
@@ -21,6 +21,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -328,7 +330,12 @@ public class GrailsUpdater {
}
private static HttpURLConnection createHttpURLConnection(String mavenMetadataFileUrl) throws IOException {
- final URL url = new URL(mavenMetadataFileUrl);
+ final URL url;
+ try {
+ url = new URI(mavenMetadataFileUrl).toURL();
+ } catch (URISyntaxException | IllegalArgumentException e) {
+ throw new IOException("Invalid Maven metadata URL: " + mavenMetadataFileUrl, e);
+ }
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("User-Agent", "Apache-Maven/3.9.6");
conn.setInstanceFollowRedirects(true);