Schema inspection handles List with async wrapper

Fixes gh-674
This commit is contained in:
rstoyanchev
2023-04-25 17:10:42 +01:00
parent 01bc66acb1
commit 133b4063e4
2 changed files with 42 additions and 19 deletions

View File

@@ -134,11 +134,14 @@ class SchemaMappingInspector {
type = unwrapNonNull(type);
if (isConnectionType(type)) {
type = getConnectionNodeType(type);
resolvableType = nest(resolvableType, type);
resolvableType = nestForConnection(resolvableType, type);
}
else if (type instanceof GraphQLList listType) {
type = unwrapNonNull(listType.getWrappedType());
resolvableType = nest(resolvableType, type);
resolvableType = nestForList(resolvableType, type);
}
else {
resolvableType = (resolvableType != null ? nestIfReactive(resolvableType) : null);
}
if (type instanceof GraphQLNamedOutputType outputType) {
@@ -157,7 +160,7 @@ class SchemaMappingInspector {
}
return;
}
else if (resolvableType != null && resolveClassToCompare(resolvableType) == Object.class) {
else if (resolvableType != null && resolvableType.resolve(Object.class) == Object.class) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped '" + getTypeName(type) + "': " +
"inspection could not determine the Java object return type.");
@@ -208,10 +211,35 @@ class SchemaMappingInspector {
return type;
}
private static ResolvableType nest(@Nullable ResolvableType resolvableType, GraphQLType type) {
Assert.notNull(resolvableType, "No declaredType for " + getTypeName(type));
resolvableType = resolvableType.getNested(2);
return resolvableType;
private ResolvableType nestForConnection(@Nullable ResolvableType type, GraphQLType graphQLType) {
Assert.state(type != null, "No Java type for " + getTypeName(graphQLType));
type = nestIfReactive(type);
Assert.state(type.hasGenerics(), "Expected type with generics: " + type);
return type.getNested(2);
}
private ResolvableType nestIfReactive(ResolvableType type) {
Class<?> clazz = type.resolve(Object.class);
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(clazz);
if (adapter != null) {
Assert.state(!adapter.isNoValue(), "Expected value producing type: " + type);
return type.getNested(2);
}
return type;
}
private ResolvableType nestForList(@Nullable ResolvableType type, GraphQLType graphQlType) {
Assert.state(type != null, "No Java type for " + getTypeName(graphQlType));
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(type.resolve(Object.class));
if (adapter != null) {
if (adapter.isMultiValue()) {
return type.getNested(2);
}
Assert.state(!adapter.isNoValue(), "Expected List compatible type: " + type);
type = type.getNested(2);
}
Assert.state(type.isArray() || type.hasGenerics(), "Expected List compatible type: " + type);
return type.getNested(2);
}
private static String getTypeName(GraphQLType type) {
@@ -224,7 +252,7 @@ class SchemaMappingInspector {
private boolean hasProperty(ResolvableType resolvableType, String fieldName) {
try {
Class<?> clazz = resolveClassToCompare(resolvableType);
Class<?> clazz = resolvableType.resolve(Object.class);
return (BeanUtils.getPropertyDescriptor(clazz, fieldName) != null);
}
catch (BeansException ex) {
@@ -233,12 +261,6 @@ class SchemaMappingInspector {
}
}
private Class<?> resolveClassToCompare(ResolvableType resolvableType) {
Class<?> clazz = resolvableType.resolve(Object.class);
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(clazz);
return (adapter != null ? resolvableType.getNested(2).resolve(Object.class) : clazz);
}
@SuppressWarnings("rawtypes")
private void inspectDataFetcherRegistrations() {
this.runtimeWiring.getDataFetchers().forEach((typeName, registrations) ->

View File

@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLSchema;
@@ -28,7 +29,7 @@ import graphql.schema.idl.SchemaGenerator;
import org.assertj.core.api.AbstractAssert;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.OffsetScrollPosition;
@@ -597,8 +598,8 @@ class SchemaMappingInspectorTests {
}
@SubscriptionMapping
public Mono<Book> bookSearch(@Argument String author) {
return Mono.empty();
public Flux<Book> bookSearch(@Argument String author) {
return Flux.empty();
}
}
@@ -611,8 +612,8 @@ class SchemaMappingInspectorTests {
}
@SchemaMapping
public List<TeamMember> members(Team team) {
return List.of();
public CompletableFuture<List<TeamMember>> members(Team team) {
return CompletableFuture.completedFuture(List.of());
}
@SchemaMapping