Skip to content

Commit fb6a225

Browse files
committed
Polishing in SchemaMappingInspector
1 parent d933828 commit fb6a225

File tree

3 files changed

+51
-39
lines changed

3 files changed

+51
-39
lines changed

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

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -414,8 +414,8 @@ Spring for GraphQL defines the `SelfDescribingDataFetcher` interface to allow a
414414
`DataFetcher` to expose return type information. All Spring `DataFetcher` implementations
415415
implement this interface. That includes those for <<controllers>>, and those for
416416
<<data.querydsl>> and <<data.querybyexample>> Spring Data repositories. For annotated
417-
controllers, the return type is derived from the declared return type on `@SchemaMapping`
418-
methods.
417+
controllers, the return type is derived from the declared return type on a
418+
`@SchemaMapping` method.
419419

420420
On startup, Spring for GraphQL inspects all schema fields, `DataFetcher` registrations,
421421
and the properties of Java objects returned from `DataFetcher` implementations in order
@@ -432,18 +432,23 @@ GraphQL schema inspection:
432432
<1> List of schema fields and their source types that are not mapped
433433
<2> List of schema types that are skipped, as explained next
434434

435-
There are limits to what schema mappings inspection can do, in particular when there is insufficient Java
436-
type information. This is the case if an annotated controller method returns
437-
`java.lang.Object` such as for a `union` type, or if a `DataFetcher` does not implement
438-
`SelfDescribingDataFetcher`. If a schema type is skipped, its name is listed as such in
439-
the report, and a DEBUG message is logged to provide a reason for why it was skipped.
440-
441-
For schema `interface` types, the inspection currently checks only fields declared
442-
directly on the interface against properties of the Java return type declared by the
443-
`DataFetcher`. Additional fields on concrete implementations are not inspected, as there
444-
is insufficient information about what Java types may be returned at runtime. This could
445-
be improved in a future release to extend inspection to schema `interface` implementing
446-
types to look for a match among subtypes of the declared Java return type.
435+
There are limits to what schema mappings inspection can do, in particular when there is
436+
insufficient Java type information. This is the case if an annotated controller method is
437+
declared to return `java.lang.Object`, or if the return type has an unspecified generic
438+
parameter such as `List<?>`, or if the `DataFetcher` does not implement
439+
`SelfDescribingDataFetcher` and the return type is not even known. In such cases, the
440+
Java object type structure remains unknown, and the schema type is listed as skipped in
441+
the resulting report. For every skipped type, a DEBUG message is logged to indicate why
442+
it was skipped.
443+
444+
Schema union types are always skipped because there is no way for a controller method to
445+
declare such a return type in Java, and the Java type structure is unknown.
446+
447+
Schema interface types are supported only as far as fields declared directly, which are
448+
compared against properties on the Java type declared by a `SelfDescribingDataFetcher`.
449+
Additional fields on concrete implementations are not inspected. This could be improved
450+
in a future release to also inspect scheam `interface` implementation types and to try
451+
to find a match among subtypes of the declared Java return type.
447452

448453

449454
[[execution.graphqlsource.operation-caching]]

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

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,30 @@
4848
import org.springframework.util.MultiValueMap;
4949

5050
/**
51-
* Provide {@link #inspect(GraphQLSchema, RuntimeWiring)} method that checks if
52-
* schema fields are covered by either a {@link DataFetcher} registration, or a
53-
* Java object property. Fields that have neither are reported as unmapped in
54-
* the output {@link Report}.
51+
* Declares an {@link #inspect(GraphQLSchema, RuntimeWiring)} method that checks
52+
* if schema fields are covered either by a {@link DataFetcher} registration,
53+
* or match a Java object property. Fields that have neither are reported as
54+
* "unmapped" in the resulting {@link Report Resport}.
5555
*
56-
* <p>The inspection depends on {@code DataFetcher}s to expose return type
57-
* information by implementing {@link SelfDescribingDataFetcher}. This allows
58-
* checking if Java object types have properties that match schema fields.
59-
* If a {@code DataFetcher} does not implement this interface, then the Java
60-
* object type is not known, and the field type is reported as skipped.
56+
* <p>The inspection depends on {@code DataFetcher}s to be
57+
* {@link SelfDescribingDataFetcher} to be able to compare schema type and Java
58+
* object type structure. If a {@code DataFetcher} does not implement this
59+
* interface, then the Java type remains unknown, and the field type is reported
60+
* as "skipped".
6161
*
62-
* <p>The {@link SelfDescribingDataFetcher} for annotated controller methods
63-
* exposes the declared return type of the controller method. If the return type
64-
* is {@link Object} such as for a union, then the Java object structure is
65-
* not known, and the field output type is reported as skipped.
62+
* <p>The {@code SelfDescribingDataFetcher} for an annotated controller method
63+
* derives type information from the controller method signature. If the declared
64+
* return type is {@link Object}, or an unspecified generic parameter such as
65+
* {@code List<?>} then the Java type structure remains unknown, and the field
66+
* output type is reported as skipped.
6667
*
67-
* <p>Union types are automatically skipped because there is no way for an
68-
* annotated controller method to declare the actual Java types.
68+
* <p>Unions are always skipped because there is no way for an annotated
69+
* controller method to express that in a return type, and the Java type
70+
* structure remains unknown.
71+
*
72+
* <p>Interfaces are supported only as far as fields declared directly on the
73+
* interface, which are compared against properties of the Java type declared
74+
* by a {@code SelfDescribingDataFetcher}.
6975
*
7076
* @author Brian Clozel
7177
* @author Rossen Stoyanchev
@@ -242,9 +248,9 @@ public static Report inspect(GraphQLSchema schema, RuntimeWiring runtimeWiring)
242248

243249

244250
/**
245-
* Container of unmapped fields and skipped types.
246-
* @param unmappedFields fields with neither {@link DataFetcher} mapping nor Object property
247-
* @param skippedTypes types that could not be verified, e.g. union
251+
* The report produced as a result of schema mappings inspection.
252+
* @param unmappedFields a map with type names as keys, and unmapped field names as values
253+
* @param skippedTypes the names of types skipped by the inspection
248254
*/
249255
public record Report(MultiValueMap<String, String> unmappedFields, Set<String> skippedTypes) {
250256

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,20 @@
2121
import org.springframework.core.ResolvableType;
2222

2323
/**
24-
* Specialized {@link DataFetcher} that can provide information about itself.
24+
* Specialized {@link DataFetcher} that exposes additional details such as
25+
* return type information.
26+
*
2527
* @author Brian Clozel
28+
* @author Rossen Stoyanchev
2629
* @since 1.2.0
2730
*/
2831
public interface SelfDescribingDataFetcher<T> extends DataFetcher<T> {
2932

3033
/**
31-
* The type that the {@link DataFetcher} returns.
32-
* <p>This could be a type from a {@code @Controller} method declaration
33-
* or the type expected to be returned by the {@link DataFetcher}
34-
* possibly backed by a Spring Data repository.
35-
* The concrete type of the returned instance might be a subclass.
36-
* @return the type of the data returned by the data fetcher.
34+
* The return type of this {@link DataFetcher}.
35+
* <p>This could be derived from the method signature of an annotated
36+
* {@code @Controller} method, the domain type of a {@link DataFetcher}
37+
* backed by a Spring Data repository, or other.
3738
*/
3839
ResolvableType getReturnType();
3940

0 commit comments

Comments
 (0)