diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index 58841c0d..08225af5 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -417,18 +417,30 @@ implement this interface. That includes those for <>, and those for controllers, the return type is derived from the declared return type on a `@SchemaMapping` method. -On startup, Spring for GraphQL inspects all schema fields, `DataFetcher` registrations, +On startup, Spring for GraphQL can inspect schema fields, `DataFetcher` registrations, and the properties of Java objects returned from `DataFetcher` implementations to check if all schema fields are covered either by an explicitly registered `DataFetcher`, or a matching Java object property. The inspection also performs a reverse check looking for -`DataFetcher` registrations against schema fields that don't exist. This inspection is -performed automatically, and results in a report that is logged at INFO level on startup. -For example: +`DataFetcher` registrations against schema fields that don't exist. + +To enable inspection of schema mappings: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +GraphQlSource.Builder builder = ... + +builder.schemaResources(..) + .inspectSchemaMappings(report -> { + logger.debug(report); + }) +---- + +Below is an example report: ---- GraphQL schema inspection: Unmapped fields: {Book=[title], Author[firstName, lastName]} // <1> - Unmapped DataFetcher registrations: {Book.reviews=BookController#reviews[1 args]} <2> + Unmapped registrations: {Book.reviews=BookController#reviews[1 args]} <2> Skipped types: [BookOrAuthor] // <3> ---- diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/DefaultSchemaResourceGraphQlSourceBuilder.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/DefaultSchemaResourceGraphQlSourceBuilder.java index cd5b75a2..65bddfe2 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/DefaultSchemaResourceGraphQlSourceBuilder.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/DefaultSchemaResourceGraphQlSourceBuilder.java @@ -24,6 +24,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.stream.Collectors; import graphql.language.InterfaceTypeDefinition; @@ -71,6 +72,9 @@ final class DefaultSchemaResourceGraphQlSourceBuilder @Nullable private BiFunction schemaFactory; + @Nullable + private Consumer schemaReportConsumer; + @Override public DefaultSchemaResourceGraphQlSourceBuilder schemaResources(Resource... resources) { @@ -96,6 +100,12 @@ final class DefaultSchemaResourceGraphQlSourceBuilder return this; } + @Override + public GraphQlSource.SchemaResourceBuilder inspectSchemaMappings(Consumer consumer) { + this.schemaReportConsumer = consumer; + return this; + } + @Override public DefaultSchemaResourceGraphQlSourceBuilder schemaFactory( BiFunction schemaFactory) { @@ -136,11 +146,13 @@ final class DefaultSchemaResourceGraphQlSourceBuilder // SchemaMappingInspector needs RuntimeWiring, but cannot run here since type // visitors may transform the schema, for example to add Connection types. - configureGraphQl(builder -> { - GraphQLSchema schema = builder.build().getGraphQLSchema(); - SchemaReport report = SchemaMappingInspector.inspect(schema, runtimeWiring); - logger.info(report); - }); + if (this.schemaReportConsumer != null) { + configureGraphQl(builder -> { + GraphQLSchema schema = builder.build().getGraphQLSchema(); + SchemaReport report = SchemaMappingInspector.inspect(schema, runtimeWiring); + this.schemaReportConsumer.accept(report); + }); + } return (this.schemaFactory != null ? this.schemaFactory.apply(registry, runtimeWiring) : diff --git a/spring-graphql/src/main/java/org/springframework/graphql/execution/GraphQlSource.java b/spring-graphql/src/main/java/org/springframework/graphql/execution/GraphQlSource.java index fe283fdd..119893b0 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/execution/GraphQlSource.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/execution/GraphQlSource.java @@ -19,7 +19,6 @@ package org.springframework.graphql.execution; import java.util.List; import java.util.function.BiFunction; import java.util.function.Consumer; -import java.util.function.Function; import graphql.GraphQL; import graphql.execution.instrumentation.Instrumentation; @@ -201,6 +200,16 @@ public interface GraphQlSource { */ SchemaResourceBuilder defaultTypeResolver(TypeResolver typeResolver); + /** + * Enable inspection of schema mappings to find unmapped fields and + * unmapped {@code DataFetcher} registrations. For more details, see + * {@link SchemaReport} and the reference documentation. + * @param reportConsumer a hook to inspect the report + * @return the current builder + * @since 1.2.0 + */ + SchemaResourceBuilder inspectSchemaMappings(Consumer reportConsumer); + /** * Configure a function to create the {@link GraphQLSchema} from the * given {@link TypeDefinitionRegistry} and {@link RuntimeWiring}.