Skip to content

Commit 0f9581d

Browse files
committed
Support custom controller method argument resolvers
Closes gh-603
1 parent f237842 commit 0f9581d

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AnnotatedControllerConfigurer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.lang.annotation.Annotation;
1919
import java.lang.reflect.Method;
2020
import java.lang.reflect.Type;
21+
import java.util.ArrayList;
2122
import java.util.Arrays;
2223
import java.util.Collection;
2324
import java.util.Collections;
@@ -121,6 +122,8 @@ public class AnnotatedControllerConfigurer
121122

122123
private final FormattingConversionService conversionService = new DefaultFormattingConversionService();
123124

125+
private final List<HandlerMethodArgumentResolver> customArgumentResolvers = new ArrayList<>(8);
126+
124127
@Nullable
125128
private HandlerMethodArgumentResolverComposite argumentResolvers;
126129

@@ -147,6 +150,18 @@ public void addFormatterRegistrar(FormatterRegistrar registrar) {
147150
registrar.registerFormatters(this.conversionService);
148151
}
149152

153+
/**
154+
* Add {@link HandlerMethodArgumentResolver}'s for custom controller method
155+
* arguments. Such custom resolvers are ordered after built-in resolvers
156+
* except for {@link SourceMethodArgumentResolver}, which is always last.
157+
*
158+
* @param resolvers the resolvers to add.
159+
* @since 1.2
160+
*/
161+
public void setCustomArgumentResolver(List<HandlerMethodArgumentResolver> resolvers) {
162+
this.customArgumentResolvers.addAll(resolvers);
163+
}
164+
150165
HandlerMethodArgumentResolverComposite getArgumentResolvers() {
151166
Assert.notNull(this.argumentResolvers,
152167
"HandlerMethodArgumentResolverComposite is not yet initialized, was afterPropertiesSet called?");
@@ -243,6 +258,8 @@ private HandlerMethodArgumentResolverComposite initArgumentResolvers() {
243258
resolvers.addResolver(new ContinuationHandlerMethodArgumentResolver());
244259
}
245260

261+
this.customArgumentResolvers.forEach(resolvers::addResolver);
262+
246263
// This works as a fallback, after all other resolvers
247264
resolvers.addResolver(new SourceMethodArgumentResolver());
248265

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.graphql.data.method.annotation.support;
17+
18+
import java.util.Collections;
19+
import java.util.List;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
import org.springframework.context.support.StaticApplicationContext;
24+
import org.springframework.graphql.data.method.HandlerMethodArgumentResolver;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.mockito.Mockito.mock;
28+
29+
/**
30+
* Unit tests for {@link AnnotatedControllerConfigurer}.
31+
*
32+
* @author Rossen Stoyanchev
33+
* @since 1.2
34+
*/
35+
public class AnnotatedControllerConfigurerTests {
36+
37+
38+
@Test
39+
void customArgumentResolvers() {
40+
HandlerMethodArgumentResolver customResolver1 = mock(HandlerMethodArgumentResolver.class);
41+
HandlerMethodArgumentResolver customResolver2 = mock(HandlerMethodArgumentResolver.class);
42+
43+
AnnotatedControllerConfigurer configurer = new AnnotatedControllerConfigurer();
44+
configurer.setCustomArgumentResolver(Collections.singletonList(customResolver1));
45+
configurer.setCustomArgumentResolver(Collections.singletonList(customResolver2));
46+
configurer.setApplicationContext(new StaticApplicationContext());
47+
configurer.afterPropertiesSet();
48+
49+
List<HandlerMethodArgumentResolver> resolvers = configurer.getArgumentResolvers().getResolvers();
50+
int size = resolvers.size();
51+
assertThat(resolvers).element(size -1).isInstanceOf(SourceMethodArgumentResolver.class);
52+
assertThat(resolvers).element(size -2).isSameAs(customResolver2);
53+
assertThat(resolvers).element(size -3).isSameAs(customResolver1);
54+
}
55+
56+
}

0 commit comments

Comments
 (0)