From 310424e793f1def8db349e91f9a1b417c922796d Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Tue, 18 Feb 2025 16:52:58 +0000 Subject: [PATCH] SchemaMappingInspector checks public fields Closes gh-1101 --- .../execution/SchemaMappingInspector.java | 19 ++++++++++++++++++- .../org/springframework/graphql/Book.java | 2 ++ .../SchemaMappingInspectorTests.java | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/SchemaMappingInspector.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/SchemaMappingInspector.java index 1ac9f39f..e747aa37 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/SchemaMappingInspector.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/SchemaMappingInspector.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 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. @@ -17,6 +17,7 @@ package org.springframework.graphql.execution; import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -185,6 +186,11 @@ public final class SchemaMappingInspector { checkField(fieldContainer, field, ResolvableType.forMethodParameter(returnType, resolvableType)); continue; } + Field javaField = getField(resolvableType, fieldName); + if (javaField != null) { + checkField(fieldContainer, field, ResolvableType.forField(javaField)); + continue; + } // Kotlin function? Method method = getRecordLikeMethod(resolvableType, fieldName); if (method != null) { @@ -268,6 +274,17 @@ public final class SchemaMappingInspector { } } + @Nullable + private Field getField(ResolvableType resolvableType, String fieldName) { + try { + Class clazz = resolvableType.resolve(); + return (clazz != null) ? clazz.getField(fieldName) : null; + } + catch (NoSuchFieldException ex) { + return null; + } + } + @Nullable private static Method getRecordLikeMethod(ResolvableType resolvableType, String fieldName) { Class clazz = resolvableType.resolve(); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/Book.java b/spring-graphql/src/test/java/org/springframework/graphql/Book.java index b3f2a2ab..3b39e592 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/Book.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/Book.java @@ -26,6 +26,8 @@ public class Book { Author author; + public String publicField; + public Book() { } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/execution/SchemaMappingInspectorTests.java b/spring-graphql/src/test/java/org/springframework/graphql/execution/SchemaMappingInspectorTests.java index f3766d9c..33ebdd53 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/execution/SchemaMappingInspectorTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/execution/SchemaMappingInspectorTests.java @@ -327,6 +327,22 @@ class SchemaMappingInspectorTests extends SchemaMappingInspectorTestSupport { assertThatReport(report).hasUnmappedFieldCount(0).hasSkippedTypeCount(0); } + @Test + void reportIsEmptyWhenFieldHasMatchingObjectField() { + String schema = """ + type Query { + bookById(id: ID): Book + } + type Book { + id: ID + name: String + publicField: String + } + """; + SchemaReport report = inspectSchema(schema, BookController.class); + assertThatReport(report).hasUnmappedFieldCount(0).hasSkippedTypeCount(0); + } + @Test void reportIsEmptyWhenFieldHasDataFetcherMapping() { String schema = """