Skip to content

Commit d3ea23e

Browse files
committed
Add hook for the inspection of schema mappings
Closes gh-672
1 parent 7db96fd commit d3ea23e

File tree

3 files changed

+44
-11
lines changed

3 files changed

+44
-11
lines changed

spring-graphql-docs/src/docs/asciidoc/index.adoc

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,18 +417,30 @@ implement this interface. That includes those for <<controllers>>, and those for
417417
controllers, the return type is derived from the declared return type on a
418418
`@SchemaMapping` method.
419419

420-
On startup, Spring for GraphQL inspects all schema fields, `DataFetcher` registrations,
420+
On startup, Spring for GraphQL can inspect schema fields, `DataFetcher` registrations,
421421
and the properties of Java objects returned from `DataFetcher` implementations to check
422422
if all schema fields are covered either by an explicitly registered `DataFetcher`, or
423423
a matching Java object property. The inspection also performs a reverse check looking for
424-
`DataFetcher` registrations against schema fields that don't exist. This inspection is
425-
performed automatically, and results in a report that is logged at INFO level on startup.
426-
For example:
424+
`DataFetcher` registrations against schema fields that don't exist.
425+
426+
To enable inspection of schema mappings:
427+
428+
[source,java,indent=0,subs="verbatim,quotes"]
429+
----
430+
GraphQlSource.Builder builder = ...
431+
432+
builder.schemaResources(..)
433+
.inspectSchemaMappings(report -> {
434+
logger.debug(report);
435+
})
436+
----
437+
438+
Below is an example report:
427439

428440
----
429441
GraphQL schema inspection:
430442
Unmapped fields: {Book=[title], Author[firstName, lastName]} // <1>
431-
Unmapped DataFetcher registrations: {Book.reviews=BookController#reviews[1 args]} <2>
443+
Unmapped registrations: {Book.reviews=BookController#reviews[1 args]} <2>
432444
Skipped types: [BookOrAuthor] // <3>
433445
----
434446

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.List;
2525
import java.util.Set;
2626
import java.util.function.BiFunction;
27+
import java.util.function.Consumer;
2728
import java.util.stream.Collectors;
2829

2930
import graphql.language.InterfaceTypeDefinition;
@@ -71,6 +72,9 @@ final class DefaultSchemaResourceGraphQlSourceBuilder
7172
@Nullable
7273
private BiFunction<TypeDefinitionRegistry, RuntimeWiring, GraphQLSchema> schemaFactory;
7374

75+
@Nullable
76+
private Consumer<SchemaReport> schemaReportConsumer;
77+
7478

7579
@Override
7680
public DefaultSchemaResourceGraphQlSourceBuilder schemaResources(Resource... resources) {
@@ -96,6 +100,12 @@ public DefaultSchemaResourceGraphQlSourceBuilder defaultTypeResolver(TypeResolve
96100
return this;
97101
}
98102

103+
@Override
104+
public GraphQlSource.SchemaResourceBuilder inspectSchemaMappings(Consumer<SchemaReport> consumer) {
105+
this.schemaReportConsumer = consumer;
106+
return this;
107+
}
108+
99109
@Override
100110
public DefaultSchemaResourceGraphQlSourceBuilder schemaFactory(
101111
BiFunction<TypeDefinitionRegistry, RuntimeWiring, GraphQLSchema> schemaFactory) {
@@ -136,11 +146,13 @@ protected GraphQLSchema initGraphQlSchema() {
136146
// SchemaMappingInspector needs RuntimeWiring, but cannot run here since type
137147
// visitors may transform the schema, for example to add Connection types.
138148

139-
configureGraphQl(builder -> {
140-
GraphQLSchema schema = builder.build().getGraphQLSchema();
141-
SchemaReport report = SchemaMappingInspector.inspect(schema, runtimeWiring);
142-
logger.info(report);
143-
});
149+
if (this.schemaReportConsumer != null) {
150+
configureGraphQl(builder -> {
151+
GraphQLSchema schema = builder.build().getGraphQLSchema();
152+
SchemaReport report = SchemaMappingInspector.inspect(schema, runtimeWiring);
153+
this.schemaReportConsumer.accept(report);
154+
});
155+
}
144156

145157
return (this.schemaFactory != null ?
146158
this.schemaFactory.apply(registry, runtimeWiring) :

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.List;
2020
import java.util.function.BiFunction;
2121
import java.util.function.Consumer;
22-
import java.util.function.Function;
2322

2423
import graphql.GraphQL;
2524
import graphql.execution.instrumentation.Instrumentation;
@@ -201,6 +200,16 @@ interface SchemaResourceBuilder extends Builder<SchemaResourceBuilder> {
201200
*/
202201
SchemaResourceBuilder defaultTypeResolver(TypeResolver typeResolver);
203202

203+
/**
204+
* Enable inspection of schema mappings to find unmapped fields and
205+
* unmapped {@code DataFetcher} registrations. For more details, see
206+
* {@link SchemaReport} and the reference documentation.
207+
* @param reportConsumer a hook to inspect the report
208+
* @return the current builder
209+
* @since 1.2.0
210+
*/
211+
SchemaResourceBuilder inspectSchemaMappings(Consumer<SchemaReport> reportConsumer);
212+
204213
/**
205214
* Configure a function to create the {@link GraphQLSchema} from the
206215
* given {@link TypeDefinitionRegistry} and {@link RuntimeWiring}.

0 commit comments

Comments
 (0)