7878 * corresponding Class property.
7979 * <li>{@code DataFetcher} registrations refer to a schema field that exists.
8080 * <li>{@code DataFetcher} arguments have matching schema field arguments.
81- * <li>The nullness of schema fields matches the nullness of {@link DataFetcher}
82- * return types, class properties or class methods.
83- * <li>{@code DataFetcher} arguments match the nullness of schema argument types.
81+ * <li>The nullness of {@link DataFetcher} return types, class properties or class methods
82+ * match, or is more restrictive than, the nullness of schema fields.
83+ * <li>The nullness of {@code DataFetcher} arguments match, or is more restrictive than,
84+ * the nullness of schema argument types.
8485 * </ul>
8586 *
8687 * <p>Use methods of {@link GraphQlSource.SchemaResourceBuilder} to enable schema
@@ -223,11 +224,11 @@ private void checkFieldsContainer(
223224
224225 private void checkFieldNullNess (FieldCoordinates fieldCoordinates , Field javaField , Nullness schemaNullness ) {
225226 Nullness applicationNullness = Nullness .forField (javaField );
226- if (isMismatch (schemaNullness , applicationNullness )) {
227+ if (isNullnessError (schemaNullness , applicationNullness )) {
227228 DescribedAnnotatedElement annotatedElement = new DescribedAnnotatedElement (javaField ,
228229 javaField .getDeclaringClass ().getSimpleName () + "#" + javaField .getName ());
229- this .reportBuilder .fieldNullnessMismatch (fieldCoordinates ,
230- new DefaultNullnessMismatch (schemaNullness , applicationNullness , annotatedElement ));
230+ this .reportBuilder .fieldNullnessError (fieldCoordinates ,
231+ new DefaultNullnessError (schemaNullness , applicationNullness , annotatedElement ));
231232
232233 }
233234 }
@@ -246,10 +247,10 @@ else if (dataFetcher.usesDataLoader() && Map.class.isAssignableFrom(dataFetcherM
246247 // we cannot infer nullness if batch loader method returns a Map
247248 logger .debug ("Skip nullness check for data fetcher '" + dataFetcherMethod .getName () + "' because of batch loading." );
248249 }
249- else if (isMismatch (schemaNullness , applicationNullness )) {
250+ else if (isNullnessError (schemaNullness , applicationNullness )) {
250251 DescribedAnnotatedElement annotatedElement = new DescribedAnnotatedElement (dataFetcherMethod , dataFetcher .getDescription ());
251- this .reportBuilder .fieldNullnessMismatch (fieldCoordinates ,
252- new DefaultNullnessMismatch (schemaNullness , applicationNullness , annotatedElement ));
252+ this .reportBuilder .fieldNullnessError (fieldCoordinates ,
253+ new DefaultNullnessError (schemaNullness , applicationNullness , annotatedElement ));
253254
254255 }
255256 }
@@ -270,30 +271,30 @@ private void checkFieldArguments(GraphQLFieldDefinition field, SelfDescribingDat
270271 private void checkFieldArgumentsNullness (GraphQLFieldDefinition field , SelfDescribingDataFetcher <?> dataFetcher ) {
271272 Method dataFetcherMethod = dataFetcher .asMethod ();
272273 if (dataFetcherMethod != null ) {
273- List <SchemaReport .NullnessMismatch > mismatches = new ArrayList <>();
274+ List <SchemaReport .NullnessError > nullnessErrors = new ArrayList <>();
274275 for (Parameter parameter : dataFetcherMethod .getParameters ()) {
275276 GraphQLArgument argument = field .getArgument (parameter .getName ());
276- if (argument != null ) {
277+ if (argument != null && argument . getDefinition () != null ) {
277278 Nullness schemaNullness = resolveNullness (argument .getDefinition ().getType ());
278279 Nullness applicationNullness = Nullness .forMethodParameter (MethodParameter .forParameter (parameter ));
279- if (isMismatch (schemaNullness , applicationNullness )) {
280- mismatches .add (new DefaultNullnessMismatch (schemaNullness , applicationNullness , parameter ));
280+ if (isNullnessError (schemaNullness , applicationNullness )) {
281+ nullnessErrors .add (new DefaultNullnessError (schemaNullness , applicationNullness , parameter ));
281282 }
282283 }
283284 }
284- if (!mismatches .isEmpty ()) {
285- this .reportBuilder .argumentsNullnessMismatches (dataFetcher , mismatches );
285+ if (!nullnessErrors .isEmpty ()) {
286+ this .reportBuilder .argumentsNullnessErrors (dataFetcher , nullnessErrors );
286287 }
287288 }
288289 }
289290
290291 private void checkReadMethodNullness (FieldCoordinates fieldCoordinates , ResolvableType resolvableType , PropertyDescriptor descriptor , Nullness schemaNullness ) {
291292 Nullness applicationNullness = Nullness .forMethodReturnType (descriptor .getReadMethod ());
292- if (isMismatch (schemaNullness , applicationNullness )) {
293+ if (isNullnessError (schemaNullness , applicationNullness )) {
293294 DescribedAnnotatedElement annotatedElement = new DescribedAnnotatedElement (descriptor .getReadMethod (),
294295 resolvableType .toClass ().getSimpleName () + "#" + descriptor .getName ());
295- this .reportBuilder .fieldNullnessMismatch (fieldCoordinates ,
296- new DefaultNullnessMismatch (schemaNullness , applicationNullness , annotatedElement ));
296+ this .reportBuilder .fieldNullnessError (fieldCoordinates ,
297+ new DefaultNullnessError (schemaNullness , applicationNullness , annotatedElement ));
297298 }
298299 }
299300
@@ -408,12 +409,11 @@ private Nullness resolveNullness(Type type) {
408409 if (type instanceof NonNullType ) {
409410 return Nullness .NON_NULL ;
410411 }
411- return Nullness .NULLABLE ;
412+ return Nullness .NULLABLE ;
412413 }
413414
414- private boolean isMismatch (Nullness first , Nullness second ) {
415- return (first == Nullness .NON_NULL && second == Nullness .NULLABLE ) ||
416- (first == Nullness .NULLABLE && second == Nullness .NON_NULL );
415+ private boolean isNullnessError (Nullness schemaNullness , Nullness applicationNullness ) {
416+ return (schemaNullness == Nullness .NON_NULL && applicationNullness == Nullness .NULLABLE );
417417 }
418418
419419
@@ -909,9 +909,9 @@ private final class ReportBuilder {
909909
910910 private final MultiValueMap <DataFetcher <?>, String > unmappedArguments = new LinkedMultiValueMap <>();
911911
912- private final Map <FieldCoordinates , SchemaReport .NullnessMismatch > fieldNullnessMismatches = new LinkedHashMap <>();
912+ private final Map <FieldCoordinates , SchemaReport .NullnessError > fieldNullnessErrors = new LinkedHashMap <>();
913913
914- private final MultiValueMap <DataFetcher <?>, SchemaReport .NullnessMismatch > argumentsNullnessMismatches = new LinkedMultiValueMap <>();
914+ private final MultiValueMap <DataFetcher <?>, SchemaReport .NullnessError > argumentsNullnessErrors = new LinkedMultiValueMap <>();
915915
916916 private final List <DefaultSkippedType > skippedTypes = new ArrayList <>();
917917
@@ -929,12 +929,12 @@ void unmappedArgument(DataFetcher<?> dataFetcher, List<String> arguments) {
929929 this .unmappedArguments .put (dataFetcher , arguments );
930930 }
931931
932- void fieldNullnessMismatch (FieldCoordinates coordinates , SchemaReport .NullnessMismatch nullnessMismatch ) {
933- this .fieldNullnessMismatches .put (coordinates , nullnessMismatch );
932+ void fieldNullnessError (FieldCoordinates coordinates , SchemaReport .NullnessError nullnessError ) {
933+ this .fieldNullnessErrors .put (coordinates , nullnessError );
934934 }
935935
936- void argumentsNullnessMismatches (DataFetcher <?> dataFetcher , List <SchemaReport .NullnessMismatch > nullnessMismatches ) {
937- this .argumentsNullnessMismatches .put (dataFetcher , nullnessMismatches );
936+ void argumentsNullnessErrors (DataFetcher <?> dataFetcher , List <SchemaReport .NullnessError > nullnessErrors ) {
937+ this .argumentsNullnessErrors .put (dataFetcher , nullnessErrors );
938938 }
939939
940940 void skippedType (
@@ -973,7 +973,7 @@ SchemaReport build() {
973973 });
974974
975975 return new DefaultSchemaReport (this .unmappedFields , this .unmappedRegistrations ,
976- this .unmappedArguments , this .fieldNullnessMismatches , this .argumentsNullnessMismatches , this .skippedTypes );
976+ this .unmappedArguments , this .fieldNullnessErrors , this .argumentsNullnessErrors , this .skippedTypes );
977977 }
978978 }
979979
@@ -989,24 +989,24 @@ private final class DefaultSchemaReport implements SchemaReport {
989989
990990 private final MultiValueMap <DataFetcher <?>, String > unmappedArguments ;
991991
992- private final Map <FieldCoordinates , NullnessMismatch > fieldsNullnessMismatches ;
992+ private final Map <FieldCoordinates , NullnessError > fieldNullnessErrors ;
993993
994- private final MultiValueMap <DataFetcher <?>, NullnessMismatch > argumentsNullnessMismatches ;
994+ private final MultiValueMap <DataFetcher <?>, NullnessError > argumentNullnessErrors ;
995995
996996 private final List <SchemaReport .SkippedType > skippedTypes ;
997997
998998 DefaultSchemaReport (
999999 List <FieldCoordinates > unmappedFields , Map <FieldCoordinates , DataFetcher <?>> unmappedRegistrations ,
10001000 MultiValueMap <DataFetcher <?>, String > unmappedArguments ,
1001- Map <FieldCoordinates , NullnessMismatch > fieldsNullnessMismatches ,
1002- MultiValueMap <DataFetcher <?>, NullnessMismatch > argumentsNullnessMismatches ,
1001+ Map <FieldCoordinates , NullnessError > fieldNullnessErrors ,
1002+ MultiValueMap <DataFetcher <?>, NullnessError > argumentNullnessErrors ,
10031003 List <DefaultSkippedType > skippedTypes ) {
10041004
10051005 this .unmappedFields = Collections .unmodifiableList (unmappedFields );
10061006 this .unmappedRegistrations = Collections .unmodifiableMap (unmappedRegistrations );
10071007 this .unmappedArguments = CollectionUtils .unmodifiableMultiValueMap (unmappedArguments );
1008- this .fieldsNullnessMismatches = Collections .unmodifiableMap (fieldsNullnessMismatches );
1009- this .argumentsNullnessMismatches = CollectionUtils .unmodifiableMultiValueMap (argumentsNullnessMismatches );
1008+ this .fieldNullnessErrors = Collections .unmodifiableMap (fieldNullnessErrors );
1009+ this .argumentNullnessErrors = CollectionUtils .unmodifiableMultiValueMap (argumentNullnessErrors );
10101010 this .skippedTypes = Collections .unmodifiableList (skippedTypes );
10111011 }
10121012
@@ -1026,13 +1026,13 @@ public MultiValueMap<DataFetcher<?>, String> unmappedArguments() {
10261026 }
10271027
10281028 @ Override
1029- public Map <FieldCoordinates , NullnessMismatch > fieldsNullnessMismatches () {
1030- return this .fieldsNullnessMismatches ;
1029+ public Map <FieldCoordinates , NullnessError > fieldNullnessErrors () {
1030+ return this .fieldNullnessErrors ;
10311031 }
10321032
10331033 @ Override
1034- public MultiValueMap <DataFetcher <?>, NullnessMismatch > argumentsNullnessMismatches () {
1035- return this .argumentsNullnessMismatches ;
1034+ public MultiValueMap <DataFetcher <?>, NullnessError > argumentNullnessErrors () {
1035+ return this .argumentNullnessErrors ;
10361036 }
10371037
10381038 @ Override
@@ -1058,8 +1058,8 @@ public String toString() {
10581058 "\t Unmapped fields: " + formatUnmappedFields () + "\n " +
10591059 "\t Unmapped registrations: " + this .unmappedRegistrations + "\n " +
10601060 "\t Unmapped arguments: " + this .unmappedArguments + "\n " +
1061- "\t Fields nullness mismatches : " + formatFieldsNullnessMismatches () + "\n " +
1062- "\t Arguments nullness mismatches : " + formatArgumentsNullnessMismatches () + "\n " +
1061+ "\t Field nullness errors : " + formatFieldNullnessErrors () + "\n " +
1062+ "\t Argument nullness errors : " + formatArgumentNullnessErrors () + "\n " +
10631063 "\t Skipped types: " + this .skippedTypes ;
10641064 }
10651065
@@ -1072,21 +1072,21 @@ private String formatUnmappedFields() {
10721072 return map .toString ();
10731073 }
10741074
1075- private String formatFieldsNullnessMismatches () {
1075+ private String formatFieldNullnessErrors () {
10761076 MultiValueMap <String , String > map = new LinkedMultiValueMap <>();
1077- this .fieldsNullnessMismatches .forEach ((coordinates , mismatch ) -> {
1077+ this .fieldNullnessErrors .forEach ((coordinates , nullnessError ) -> {
10781078 List <String > fields = map .computeIfAbsent (coordinates .getTypeName (), (s ) -> new ArrayList <>());
1079- fields .add (String .format ("%s is %s -> '%s' is %s" , coordinates .getFieldName (), mismatch .schemaNullness (),
1080- mismatch .annotatedElement (), mismatch .applicationNullness ()));
1079+ fields .add (String .format ("%s is %s -> '%s' is %s" , coordinates .getFieldName (), nullnessError .schemaNullness (),
1080+ nullnessError .annotatedElement (), nullnessError .applicationNullness ()));
10811081 });
10821082 return map .toString ();
10831083 }
10841084
1085- private String formatArgumentsNullnessMismatches () {
1085+ private String formatArgumentNullnessErrors () {
10861086 MultiValueMap <String , String > map = new LinkedMultiValueMap <>();
1087- this .argumentsNullnessMismatches .forEach ((dataFetcher , mismatches ) -> {
1088- List <String > arguments = mismatches .stream ()
1089- .map ((mismatch ) -> String .format ("%s should be %s" , mismatch .annotatedElement (), mismatch .schemaNullness ()))
1087+ this .argumentNullnessErrors .forEach ((dataFetcher , nullnessErrors ) -> {
1088+ List <String > arguments = nullnessErrors .stream ()
1089+ .map ((nullnessError ) -> String .format ("%s should be %s" , nullnessError .annotatedElement (), nullnessError .schemaNullness ()))
10901090 .toList ();
10911091 map .put (dataFetcher .toString (), arguments );
10921092 });
@@ -1116,11 +1116,11 @@ public static DefaultSkippedType create(
11161116 }
11171117
11181118 /**
1119- * Default implementation of a {@link SchemaReport.NullnessMismatch }.
1119+ * Default implementation of a {@link SchemaReport.NullnessError }.
11201120 */
1121- private record DefaultNullnessMismatch (
1121+ private record DefaultNullnessError (
11221122 Nullness schemaNullness , Nullness applicationNullness , AnnotatedElement annotatedElement )
1123- implements SchemaReport .NullnessMismatch {
1123+ implements SchemaReport .NullnessError {
11241124
11251125 }
11261126
0 commit comments