Skip to content

Commit 133b406

Browse files
committed
Schema inspection handles List with async wrapper
Fixes gh-674
1 parent 01bc66a commit 133b406

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

spring-graphql/src/main/java/org/springframework/graphql/execution/SchemaMappingInspector.java

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,14 @@ private void inspectSchemaType(GraphQLType type, @Nullable ResolvableType resolv
134134
type = unwrapNonNull(type);
135135
if (isConnectionType(type)) {
136136
type = getConnectionNodeType(type);
137-
resolvableType = nest(resolvableType, type);
137+
resolvableType = nestForConnection(resolvableType, type);
138138
}
139139
else if (type instanceof GraphQLList listType) {
140140
type = unwrapNonNull(listType.getWrappedType());
141-
resolvableType = nest(resolvableType, type);
141+
resolvableType = nestForList(resolvableType, type);
142+
}
143+
else {
144+
resolvableType = (resolvableType != null ? nestIfReactive(resolvableType) : null);
142145
}
143146

144147
if (type instanceof GraphQLNamedOutputType outputType) {
@@ -157,7 +160,7 @@ else if (type instanceof GraphQLList listType) {
157160
}
158161
return;
159162
}
160-
else if (resolvableType != null && resolveClassToCompare(resolvableType) == Object.class) {
163+
else if (resolvableType != null && resolvableType.resolve(Object.class) == Object.class) {
161164
if (logger.isDebugEnabled()) {
162165
logger.debug("Skipped '" + getTypeName(type) + "': " +
163166
"inspection could not determine the Java object return type.");
@@ -208,10 +211,35 @@ private GraphQLType getConnectionNodeType(GraphQLType type) {
208211
return type;
209212
}
210213

211-
private static ResolvableType nest(@Nullable ResolvableType resolvableType, GraphQLType type) {
212-
Assert.notNull(resolvableType, "No declaredType for " + getTypeName(type));
213-
resolvableType = resolvableType.getNested(2);
214-
return resolvableType;
214+
private ResolvableType nestForConnection(@Nullable ResolvableType type, GraphQLType graphQLType) {
215+
Assert.state(type != null, "No Java type for " + getTypeName(graphQLType));
216+
type = nestIfReactive(type);
217+
Assert.state(type.hasGenerics(), "Expected type with generics: " + type);
218+
return type.getNested(2);
219+
}
220+
221+
private ResolvableType nestIfReactive(ResolvableType type) {
222+
Class<?> clazz = type.resolve(Object.class);
223+
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(clazz);
224+
if (adapter != null) {
225+
Assert.state(!adapter.isNoValue(), "Expected value producing type: " + type);
226+
return type.getNested(2);
227+
}
228+
return type;
229+
}
230+
231+
private ResolvableType nestForList(@Nullable ResolvableType type, GraphQLType graphQlType) {
232+
Assert.state(type != null, "No Java type for " + getTypeName(graphQlType));
233+
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(type.resolve(Object.class));
234+
if (adapter != null) {
235+
if (adapter.isMultiValue()) {
236+
return type.getNested(2);
237+
}
238+
Assert.state(!adapter.isNoValue(), "Expected List compatible type: " + type);
239+
type = type.getNested(2);
240+
}
241+
Assert.state(type.isArray() || type.hasGenerics(), "Expected List compatible type: " + type);
242+
return type.getNested(2);
215243
}
216244

217245
private static String getTypeName(GraphQLType type) {
@@ -224,7 +252,7 @@ private static boolean isNotScalarOrEnumType(GraphQLType type) {
224252

225253
private boolean hasProperty(ResolvableType resolvableType, String fieldName) {
226254
try {
227-
Class<?> clazz = resolveClassToCompare(resolvableType);
255+
Class<?> clazz = resolvableType.resolve(Object.class);
228256
return (BeanUtils.getPropertyDescriptor(clazz, fieldName) != null);
229257
}
230258
catch (BeansException ex) {
@@ -233,12 +261,6 @@ private boolean hasProperty(ResolvableType resolvableType, String fieldName) {
233261
}
234262
}
235263

236-
private Class<?> resolveClassToCompare(ResolvableType resolvableType) {
237-
Class<?> clazz = resolvableType.resolve(Object.class);
238-
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(clazz);
239-
return (adapter != null ? resolvableType.getNested(2).resolve(Object.class) : clazz);
240-
}
241-
242264
@SuppressWarnings("rawtypes")
243265
private void inspectDataFetcherRegistrations() {
244266
this.runtimeWiring.getDataFetchers().forEach((typeName, registrations) ->

spring-graphql/src/test/java/org/springframework/graphql/execution/SchemaMappingInspectorTests.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Collections;
2121
import java.util.List;
2222
import java.util.Set;
23+
import java.util.concurrent.CompletableFuture;
2324

2425
import graphql.schema.FieldCoordinates;
2526
import graphql.schema.GraphQLSchema;
@@ -28,7 +29,7 @@
2829
import org.assertj.core.api.AbstractAssert;
2930
import org.junit.jupiter.api.Nested;
3031
import org.junit.jupiter.api.Test;
31-
import reactor.core.publisher.Mono;
32+
import reactor.core.publisher.Flux;
3233

3334
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3435
import org.springframework.data.domain.OffsetScrollPosition;
@@ -597,8 +598,8 @@ public Book createBook() {
597598
}
598599

599600
@SubscriptionMapping
600-
public Mono<Book> bookSearch(@Argument String author) {
601-
return Mono.empty();
601+
public Flux<Book> bookSearch(@Argument String author) {
602+
return Flux.empty();
602603
}
603604
}
604605

@@ -611,8 +612,8 @@ public Team teamById(@Argument Long id) {
611612
}
612613

613614
@SchemaMapping
614-
public List<TeamMember> members(Team team) {
615-
return List.of();
615+
public CompletableFuture<List<TeamMember>> members(Team team) {
616+
return CompletableFuture.completedFuture(List.of());
616617
}
617618

618619
@SchemaMapping

0 commit comments

Comments
 (0)