diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/method/HandlerMethodArgumentResolverComposite.java b/spring-graphql/src/main/java/org/springframework/graphql/data/method/HandlerMethodArgumentResolverComposite.java index b6b7c7f5..dd7fd899 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/method/HandlerMethodArgumentResolverComposite.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/method/HandlerMethodArgumentResolverComposite.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,9 +27,8 @@ import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; /** - * Resolves method parameters by delegating to a list of registered - * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolver}'s. - * Previously resolved method parameters are cached for faster lookups. + * Container for a list of resolvers that looks for one that supports a given + * method parameter type, and delegates to it. * * @author Rossen Stoyanchev * @since 1.0.0 @@ -63,7 +62,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu */ @Override public boolean supportsParameter(MethodParameter parameter) { - return getArgumentResolver(parameter) != null; + return (getArgumentResolver(parameter) != null); } /** @@ -77,8 +76,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { - throw new IllegalArgumentException("Unsupported parameter type [" + - parameter.getParameterType().getName() + "]. supportsParameter should be called first."); + throw new IllegalArgumentException("Unsupported parameter [" + parameter + "]."); } return resolver.resolveArgument(parameter, environment); } @@ -89,17 +87,14 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu */ @Nullable public HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { - HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); - if (result == null) { + return this.argumentResolverCache.computeIfAbsent(parameter, p -> { for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) { if (resolver.supportsParameter(parameter)) { - result = resolver; - this.argumentResolverCache.put(parameter, result); - break; + return resolver; } } - } - return result; + return null; + }); } } \ No newline at end of file diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java index 21814613..53e807de 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java @@ -121,12 +121,6 @@ public class AnnotatedControllerConfigurer private final FormattingConversionService conversionService = new DefaultFormattingConversionService(); - @Nullable - private Executor executor; - - @Nullable - private ApplicationContext applicationContext; - @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @@ -136,6 +130,12 @@ public class AnnotatedControllerConfigurer @Nullable private AnnotatedControllerExceptionResolver exceptionResolver; + @Nullable + private Executor executor; + + @Nullable + private ApplicationContext applicationContext; + /** * Add a {@code FormatterRegistrar} to customize the {@link ConversionService} @@ -147,31 +147,10 @@ public class AnnotatedControllerConfigurer registrar.registerFormatters(this.conversionService); } - /** - * Configure an {@link Executor} to use for asynchronous handling of - * {@link Callable} return values from controller methods. - *
By default, this is not set in which case controller methods with a
- * {@code Callable} return value cannot be registered.
- * @param executor the executor to use
- */
- public void setExecutor(Executor executor) {
- this.executor = executor;
- }
-
- /**
- * Configure an initializer that configures the {@link DataBinder} before the binding process.
- * @param consumer the data binder initializer
- * @since 1.0.1
- * @deprecated this property is deprecated, ignored, and should not be
- * necessary as a {@link DataBinder} is no longer used to bind arguments
- */
- @Deprecated(since = "1.1.0", forRemoval = true)
- public void setDataBinderInitializer(@Nullable Consumer By default, this is not set in which case controller methods with a
+ * {@code Callable} return value cannot be registered.
+ * @param executor the executor to use
+ */
+ public void setExecutor(Executor executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+
@Override
public void afterPropertiesSet() {
diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingBeanFactoryInitializationAotProcessor.java b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingBeanFactoryInitializationAotProcessor.java
index 8e18ccba..68e330c6 100644
--- a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingBeanFactoryInitializationAotProcessor.java
+++ b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/SchemaMappingBeanFactoryInitializationAotProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2020-2022 the original author or authors.
+ * Copyright 2020-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,6 @@ import org.springframework.graphql.data.method.HandlerMethodArgumentResolverComp
import org.springframework.graphql.data.method.annotation.BatchMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
-import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -57,17 +56,21 @@ import static org.springframework.core.annotation.MergedAnnotations.SearchStrate
* {@link BeanFactoryInitializationAotProcessor} implementation for registering
* runtime hints discoverable through GraphQL controllers, such as:
* This processor is using a {@link HandlerMethodArgumentResolver} resolution mechanism similar
- * to the one used in {@link AnnotatedControllerConfigurer}. The type of runtime hints registered
- * for each method argument depends on the {@link HandlerMethodArgumentResolver} resolved.
- * Manual registration of {@link graphql.schema.DataFetcher} cannot be detected by this
- * processor; developers will need to declare bound types with {@link RegisterReflectionForBinding}
- * annotations on their configuration class.
+ * This processor is using a {@link HandlerMethodArgumentResolver} resolution
+ * mechanism similar to the one used in {@link AnnotatedControllerConfigurer}.
+ * The type of runtime hints registered for each method argument depends on the
+ * {@link HandlerMethodArgumentResolver} resolved.
+ * Manual registration of {@link graphql.schema.DataFetcher} cannot be detected
+ * by this processor; developers will need to declare bound types with
+ * {@link RegisterReflectionForBinding} annotations on their configuration class.
*
* @author Brian Clozel
* @see org.springframework.graphql.data.method.HandlerMethodArgumentResolver
@@ -93,7 +96,9 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
return MergedAnnotations.from(element, TYPE_HIERARCHY).isPresent(Controller.class);
}
- private static class SchemaMappingBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution {
+
+ private static class SchemaMappingBeanFactoryInitializationAotContribution
+ implements BeanFactoryInitializationAotContribution {
private final Class>[] controllers;
@@ -105,21 +110,21 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
private HandlerMethodArgumentResolverComposite createArgumentResolvers() {
- AnnotatedControllerConfigurer controllerConfigurer = new AnnotatedControllerConfigurer();
- controllerConfigurer.setApplicationContext(new StaticApplicationContext());
- controllerConfigurer.afterPropertiesSet();
- HandlerMethodArgumentResolverComposite argumentResolverComposite = controllerConfigurer.getArgumentResolvers();
- Assert.notNull(argumentResolverComposite, "argument resolvers should not be null");
- return argumentResolverComposite;
+ AnnotatedControllerConfigurer configurer = new AnnotatedControllerConfigurer();
+ configurer.setApplicationContext(new StaticApplicationContext());
+ configurer.afterPropertiesSet();
+ return configurer.getArgumentResolvers();
}
@Override
- public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) {
- RuntimeHints runtimeHints = generationContext.getRuntimeHints();
+ public void applyTo(GenerationContext context, BeanFactoryInitializationCode initializationCode) {
+ RuntimeHints runtimeHints = context.getRuntimeHints();
registerSpringDataSpelSupport(runtimeHints);
Arrays.stream(this.controllers).forEach(controller -> {
runtimeHints.reflection().registerType(controller);
- ReflectionUtils.doWithMethods(controller, method -> processSchemaMappingMethod(runtimeHints, method), this::isGraphQlHandlerMethod);
+ ReflectionUtils.doWithMethods(controller,
+ method -> processSchemaMappingMethod(runtimeHints, method),
+ this::isGraphQlHandlerMethod);
});
}
@@ -134,9 +139,8 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
private boolean isGraphQlHandlerMethod(AnnotatedElement element) {
- MergedAnnotations mergedAnnotations = MergedAnnotations.from(element, TYPE_HIERARCHY);
- return mergedAnnotations.isPresent(SchemaMapping.class)
- || mergedAnnotations.isPresent(BatchMapping.class);
+ MergedAnnotations annotations = MergedAnnotations.from(element, TYPE_HIERARCHY);
+ return annotations.isPresent(SchemaMapping.class) || annotations.isPresent(BatchMapping.class);
}
private void processSchemaMappingMethod(RuntimeHints runtimeHints, Method method) {
@@ -147,17 +151,17 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
processReturnType(runtimeHints, MethodParameter.forExecutable(method, -1));
}
- private void processMethodParameter(RuntimeHints runtimeHints, MethodParameter methodParameter) {
- MethodParameterRuntimeHintsRegistrar.fromMethodParameter(this.argumentResolvers, methodParameter)
- .apply(runtimeHints);
+ private void processMethodParameter(RuntimeHints hints, MethodParameter parameter) {
+ MethodParameterRuntimeHintsRegistrar.fromMethodParameter(this.argumentResolvers, parameter).apply(hints);
}
- private void processReturnType(RuntimeHints runtimeHints, MethodParameter methodParameter) {
- new ArgumentBindingHints(methodParameter).apply(runtimeHints);
+ private void processReturnType(RuntimeHints hints, MethodParameter parameter) {
+ new ArgumentBindingHints(parameter).apply(hints);
}
}
+
@FunctionalInterface
private interface MethodParameterRuntimeHintsRegistrar {
@@ -165,18 +169,20 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
void apply(RuntimeHints runtimeHints);
- static MethodParameterRuntimeHintsRegistrar fromMethodParameter(HandlerMethodArgumentResolverComposite argumentResolvers, MethodParameter methodParameter) {
- HandlerMethodArgumentResolver argumentResolver = argumentResolvers.getArgumentResolver(methodParameter);
- if (argumentResolver instanceof ArgumentMethodArgumentResolver
- || argumentResolver instanceof ArgumentsMethodArgumentResolver) {
- return new ArgumentBindingHints(methodParameter);
+ static MethodParameterRuntimeHintsRegistrar fromMethodParameter(
+ HandlerMethodArgumentResolverComposite resolvers, MethodParameter parameter) {
+
+ HandlerMethodArgumentResolver resolver = resolvers.getArgumentResolver(parameter);
+ if (resolver instanceof ArgumentMethodArgumentResolver
+ || resolver instanceof ArgumentsMethodArgumentResolver) {
+ return new ArgumentBindingHints(parameter);
}
- if (argumentResolver instanceof DataLoaderMethodArgumentResolver) {
- return new DataLoaderHints(methodParameter);
+ if (resolver instanceof DataLoaderMethodArgumentResolver) {
+ return new DataLoaderHints(parameter);
}
if (springDataPresent) {
- if (argumentResolver instanceof ProjectedPayloadMethodArgumentResolver) {
- return new ProjectedPayloadHints(methodParameter);
+ if (resolver instanceof ProjectedPayloadMethodArgumentResolver) {
+ return new ProjectedPayloadHints(parameter);
}
}
return new NoHintsRequired();
@@ -184,6 +190,7 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
+
private static class NoHintsRequired implements MethodParameterRuntimeHintsRegistrar {
@Override
@@ -192,6 +199,7 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
}
+
private static class ArgumentBindingHints implements MethodParameterRuntimeHintsRegistrar {
private final MethodParameter methodParameter;
@@ -210,6 +218,7 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
}
+
private static class DataLoaderHints implements MethodParameterRuntimeHintsRegistrar {
private final MethodParameter methodParameter;
@@ -219,12 +228,13 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
@Override
- public void apply(RuntimeHints runtimeHints) {
- bindingRegistrar.registerReflectionHints(runtimeHints.reflection(),
- this.methodParameter.nested().getNestedGenericParameterType());
+ public void apply(RuntimeHints hints) {
+ bindingRegistrar.registerReflectionHints(
+ hints.reflection(), this.methodParameter.nested().getNestedGenericParameterType());
}
}
+
private static class ProjectedPayloadHints implements MethodParameterRuntimeHintsRegistrar {
private final MethodParameter methodParameter;
@@ -234,10 +244,10 @@ class SchemaMappingBeanFactoryInitializationAotProcessor implements BeanFactoryI
}
@Override
- public void apply(RuntimeHints runtimeHints) {
+ public void apply(RuntimeHints hints) {
Class> parameterType = this.methodParameter.nestedIfOptional().getNestedParameterType();
- runtimeHints.reflection().registerType(parameterType);
- runtimeHints.proxies().registerJdkProxy(parameterType, TargetAware.class, SpringProxy.class, DecoratingProxy.class);
+ hints.reflection().registerType(parameterType);
+ hints.proxies().registerJdkProxy(parameterType, TargetAware.class, SpringProxy.class, DecoratingProxy.class);
}
}
diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java
index eeed59c9..910858e6 100644
--- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java
+++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerExceptionResolverTests.java
@@ -148,8 +148,8 @@ public class AnnotatedControllerExceptionResolverTests {
configurer.setApplicationContext(applicationContext);
configurer.afterPropertiesSet();
- HandlerMethodArgumentResolverComposite argumentResolvers = configurer.getArgumentResolvers();
- AnnotatedControllerExceptionResolver resolver = new AnnotatedControllerExceptionResolver(argumentResolvers);
+ HandlerMethodArgumentResolverComposite resolvers = configurer.getArgumentResolvers();
+ AnnotatedControllerExceptionResolver resolver = new AnnotatedControllerExceptionResolver(resolvers);
resolver.registerControllerAdvice(applicationContext);
return resolver;
}
- *
- *