Skip to content

Commit 763877b

Browse files
committed
Improves generic type support in schema inspection
The fix targets cases when a method's return type has a generic type, and the generic type is declared inline on the return type. We need to pass containing class information as a ResolvableType in order to be able to resolve generic types. Closes gh-1037
1 parent 579bb64 commit 763877b

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public final class SchemaMappingInspector {
9393
(!method.getDeclaringClass().equals(Object.class) && !method.getReturnType().equals(Void.class) &&
9494
method.getParameterCount() == 0 && Modifier.isPublic(method.getModifiers()));
9595

96-
9796
private final GraphQLSchema schema;
9897

9998
private final Map<String, Map<String, DataFetcher>> dataFetchers;
@@ -182,13 +181,15 @@ private void checkFieldsContainer(
182181
if (resolvableType != null) {
183182
PropertyDescriptor descriptor = getProperty(resolvableType, fieldName);
184183
if (descriptor != null) {
185-
checkField(fieldContainer, field, ResolvableType.forMethodReturnType(descriptor.getReadMethod()));
184+
MethodParameter returnType = new MethodParameter(descriptor.getReadMethod(), -1);
185+
checkField(fieldContainer, field, ResolvableType.forMethodParameter(returnType, resolvableType));
186186
continue;
187187
}
188188
// Kotlin function?
189189
Method method = getRecordLikeMethod(resolvableType, fieldName);
190190
if (method != null) {
191-
checkField(fieldContainer, field, ResolvableType.forMethodReturnType(method));
191+
MethodParameter returnType = new MethodParameter(method, -1);
192+
checkField(fieldContainer, field, ResolvableType.forMethodParameter(returnType, resolvableType));
192193
continue;
193194
}
194195
}

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void mappedSubscriptionWithUnmappedArgument() {
310310

311311

312312
@Nested
313-
class TypesInspectionTests {
313+
class SchemaTypeInspectionTests {
314314

315315
@Test
316316
void reportIsEmptyWhenFieldHasMatchingObjectProperty() {
@@ -434,6 +434,25 @@ void reportHasUnmappedFieldOnEagerlyFetchedNestedType() {
434434
assertThatReport(report).hasUnmappedFieldCount(1).containsUnmappedFields("Author", "missing");
435435
}
436436

437+
@Test // gh-1037
438+
void reportHasUnmappedFieldOnGenericType() {
439+
String schema = """
440+
type Query {
441+
teamContainer: TeamContainer
442+
}
443+
type TeamContainer {
444+
items: [Team]
445+
}
446+
type Team {
447+
name: String
448+
missing: String
449+
}
450+
""";
451+
452+
SchemaReport report = inspectSchema(schema, TeamController.class);
453+
assertThatReport(report).hasUnmappedFieldCount(1).containsUnmappedFields("Team", "missing");
454+
}
455+
437456
@Test
438457
void reportWorksWithCyclicRelations() {
439458
String schema = """
@@ -680,6 +699,10 @@ public Team team(TeamMember teamMember) {
680699
return null;
681700
}
682701

702+
@QueryMapping
703+
public ListContainer<Team> teamContainer() {
704+
return new ListContainer<>(Collections.emptyList());
705+
}
683706
}
684707

685708

@@ -692,4 +715,9 @@ record TeamMember(String name, Team team) {
692715

693716
}
694717

718+
719+
record ListContainer<T>(List<T> items) {
720+
721+
}
722+
695723
}

0 commit comments

Comments
 (0)