Add resolver for @Argument Map<String, Object>

Closes gh-113
This commit is contained in:
Rossen Stoyanchev
2021-08-31 14:44:47 +01:00
parent 60e65078c2
commit a98ca42981
5 changed files with 66 additions and 10 deletions

View File

@@ -566,6 +566,9 @@ it not specified, it defaults to the method parameter name, but this requires th
By default, an `@Argument` is required, but you can make it optional by setting the
`required` flag to false or by declaring the argument with `java.util.Optional`.
You can use `@Argument` on a `Map<String, Object>` argument, to obtain all argument
values. The name attribute on `@Argument` must not be set.
[[controllers-source]]
==== Source

View File

@@ -45,8 +45,9 @@ import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.graphql.data.method.annotation.SubscriptionMapping;
import org.springframework.graphql.data.method.annotation.support.ArgumentMapMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.support.DataFetchingEnvironmentMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.support.InputArgumentMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.support.ArgumentMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.support.SourceMethodArgumentResolver;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import org.springframework.http.MediaType;
@@ -159,17 +160,18 @@ public class AnnotatedDataFetcherConfigurer
public void afterPropertiesSet() {
this.argumentResolvers = new HandlerMethodArgumentResolverComposite();
this.argumentResolvers.addResolver(initInputArgumentMethodArgumentResolver());
this.argumentResolvers.addResolver(new ArgumentMapMethodArgumentResolver());
this.argumentResolvers.addResolver(new DataFetchingEnvironmentMethodArgumentResolver());
this.argumentResolvers.addResolver(new SourceMethodArgumentResolver());
}
private InputArgumentMethodArgumentResolver initInputArgumentMethodArgumentResolver() {
InputArgumentMethodArgumentResolver argumentResolver;
private ArgumentMethodArgumentResolver initInputArgumentMethodArgumentResolver() {
ArgumentMethodArgumentResolver argumentResolver;
if (this.jsonMessageConverter != null) {
argumentResolver = new InputArgumentMethodArgumentResolver(this.jsonMessageConverter);
argumentResolver = new ArgumentMethodArgumentResolver(this.jsonMessageConverter);
}
else if (this.jsonEncoder != null && this.jsonDecoder != null) {
argumentResolver = new InputArgumentMethodArgumentResolver(this.jsonDecoder, this.jsonEncoder);
argumentResolver = new ArgumentMethodArgumentResolver(this.jsonDecoder, this.jsonEncoder);
}
else {
throw new IllegalArgumentException(

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.graphql.data.method.annotation.support;
import java.util.Map;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.core.MethodParameter;
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.util.StringUtils;
/**
* Resolves {@link Map} method arguments annotated with an @{@link Argument}
* where the annotation does not specify an argument name.
*
* @author Rossen Stoyanchev
* @since 1.0.0
*/
public class ArgumentMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
Argument argument = parameter.getParameterAnnotation(Argument.class);
return (argument != null &&
Map.class.isAssignableFrom(parameter.getParameterType()) &&
!StringUtils.hasText(argument.name()));
}
@Override
public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) {
return environment.getArguments();
}
}

View File

@@ -53,7 +53,7 @@ import org.springframework.util.StringUtils;
* @author Rossen Stoyanchev
* @since 1.0.0
*/
public class InputArgumentMethodArgumentResolver implements HandlerMethodArgumentResolver {
public class ArgumentMethodArgumentResolver implements HandlerMethodArgumentResolver {
private final ArgumentConverter argumentConverter;
@@ -62,16 +62,16 @@ public class InputArgumentMethodArgumentResolver implements HandlerMethodArgumen
* {@link org.springframework.http.converter.HttpMessageConverter} to convert
* Map-based input arguments to higher level Objects.
*/
public InputArgumentMethodArgumentResolver(GenericHttpMessageConverter<Object> converter) {
public ArgumentMethodArgumentResolver(GenericHttpMessageConverter<Object> converter) {
this.argumentConverter = new MessageConverterArgumentConverter(converter);
}
/**
* Variant of
* {@link #InputArgumentMethodArgumentResolver(GenericHttpMessageConverter)}
* {@link #ArgumentMethodArgumentResolver(GenericHttpMessageConverter)}
* to use an {@link Encoder} and {@link Decoder} to convert input arguments.
*/
public InputArgumentMethodArgumentResolver(Decoder<Object> decoder, Encoder<Object> encoder) {
public ArgumentMethodArgumentResolver(Decoder<Object> decoder, Encoder<Object> encoder) {
this.argumentConverter = new CodecArgumentConverter(decoder, encoder);
}

View File

@@ -37,7 +37,9 @@ import org.springframework.stereotype.Controller;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link AnnotatedDataFetcherConfigurer}.
* Unit tests for {@link AnnotatedDataFetcherConfigurer}, focusing on detection
* and mapping of handler methods to schema fields.
*
* @author Rossen Stoyanchev
*/
public class AnnotatedDataFetcherConfigurerTests {