diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java b/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java index 0306e5a0..5dc7940f 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java @@ -17,7 +17,6 @@ package org.springframework.graphql.data.query; import java.util.List; import java.util.Map; -import java.util.function.Function; import java.util.function.Predicate; import graphql.language.FieldDefinition; @@ -49,19 +48,15 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer private final static Log logger = LogFactory.getLog(AutoRegistrationRuntimeWiringConfigurer.class); - private final Map>> dataFetcherFactories; + private final Map dataFetcherFactories; /** - * Constructor with a Map of GraphQL type names for which auto-registration - * can be performed. - * @param dataFetcherFactories Map with GraphQL type names as keys, and - * functions to create a corresponding {@link DataFetcher} as values. + * Constructor with a Map of GraphQL type names as keys, and + * {@code DataFetcher} factories as values. */ - AutoRegistrationRuntimeWiringConfigurer( - Map>> dataFetcherFactories) { - - this.dataFetcherFactories = dataFetcherFactories; + AutoRegistrationRuntimeWiringConfigurer(Map factories) { + this.dataFetcherFactories = factories; } @@ -75,6 +70,24 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer } + /** + * Callback interface to create the desired type of {@code DataFetcher}. + */ + interface DataFetcherFactory { + + /** + * Create a singe item {@code DataFetcher}. + */ + DataFetcher single(); + + /** + * Create {@code DataFetcher} for multiple items. + */ + DataFetcher many(); + + } + + private class AutoRegistrationWiringFactory implements WiringFactory { private final RuntimeWiring.Builder builder; @@ -112,16 +125,21 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer @Nullable private String getOutputTypeName(FieldWiringEnvironment environment) { - GraphQLType outputType = (environment.getFieldType() instanceof GraphQLList ? - ((GraphQLList) environment.getFieldType()).getWrappedType() : - environment.getFieldType()); + GraphQLType outputType = removeNonNullWrapper(environment.getFieldType()); - if (outputType instanceof GraphQLNonNull) { - outputType = ((GraphQLNonNull) outputType).getWrappedType(); + if (outputType instanceof GraphQLList) { + outputType = removeNonNullWrapper(((GraphQLList) outputType).getWrappedType()); } - return (outputType instanceof GraphQLNamedOutputType ? - ((GraphQLNamedOutputType) outputType).getName() : null); + if (outputType instanceof GraphQLNamedOutputType namedType) { + return namedType.getName(); + } + + return null; + } + + private GraphQLType removeNonNullWrapper(GraphQLType outputType) { + return (outputType instanceof GraphQLNonNull wrapper ? wrapper.getWrappedType() : outputType); } private boolean hasDataFetcherFor(FieldDefinition fieldDefinition) { @@ -132,13 +150,11 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer return this.existingQueryDataFetcherPredicate.test(fieldDefinition.getName()); } - private void logTraceMessage( - FieldWiringEnvironment environment, @Nullable String outputTypeName, boolean match) { - + private void logTraceMessage(FieldWiringEnvironment environment, @Nullable String typeName, boolean match) { if (logger.isTraceEnabled()) { String query = environment.getFieldDefinition().getName(); logger.trace((match ? "Matched" : "Skipped") + - " output typeName " + (outputTypeName != null ? "'" + outputTypeName + "'" : "null") + + " output typeName " + (typeName != null ? "'" + typeName + "'" : "null") + " for query '" + query + "'"); } } @@ -149,11 +165,16 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer String outputTypeName = getOutputTypeName(environment); logTraceMessage(environment, outputTypeName, true); - Function> factory = dataFetcherFactories.get(outputTypeName); + DataFetcherFactory factory = dataFetcherFactories.get(outputTypeName); Assert.notNull(factory, "Expected DataFetcher factory for typeName '" + outputTypeName + "'"); - boolean single = !(environment.getFieldType() instanceof GraphQLList); - return factory.apply(single); + GraphQLType outputType = removeNonNullWrapper(environment.getFieldType()); + if (outputType instanceof GraphQLList) { + return factory.many(); + } + else { + return factory.single(); + } } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/query/QueryByExampleDataFetcher.java b/spring-graphql/src/main/java/org/springframework/graphql/data/query/QueryByExampleDataFetcher.java index a2aaed55..e623b64e 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/query/QueryByExampleDataFetcher.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/query/QueryByExampleDataFetcher.java @@ -42,6 +42,7 @@ import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; import org.springframework.data.util.TypeInformation; import org.springframework.graphql.data.GraphQlArgumentBinder; import org.springframework.graphql.data.GraphQlRepository; +import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory; import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.execution.SelfDescribingDataFetcher; import org.springframework.lang.Nullable; @@ -195,13 +196,23 @@ public abstract class QueryByExampleDataFetcher { List> executors, List> reactiveExecutors) { - Map>> factories = new HashMap<>(); + Map factories = new HashMap<>(); for (QueryByExampleExecutor executor : executors) { String typeName = RepositoryUtils.getGraphQlTypeName(executor); if (typeName != null) { Builder builder = customize(executor, builder(executor)); - factories.put(typeName, single -> single ? builder.single() : builder.many()); + factories.put(typeName, new DataFetcherFactory() { + @Override + public DataFetcher single() { + return builder.single(); + } + + @Override + public DataFetcher many() { + return builder.many(); + } + }); } } @@ -209,7 +220,17 @@ public abstract class QueryByExampleDataFetcher { String typeName = RepositoryUtils.getGraphQlTypeName(executor); if (typeName != null) { ReactiveBuilder builder = customize(executor, builder(executor)); - factories.put(typeName, single -> single ? builder.single() : builder.many()); + factories.put(typeName, new DataFetcherFactory() { + @Override + public DataFetcher single() { + return builder.single(); + } + + @Override + public DataFetcher many() { + return builder.many(); + } + }); } } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/query/QuerydslDataFetcher.java b/spring-graphql/src/main/java/org/springframework/graphql/data/query/QuerydslDataFetcher.java index 26e0ca8b..e7940cbb 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/query/QuerydslDataFetcher.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/query/QuerydslDataFetcher.java @@ -47,6 +47,7 @@ import org.springframework.data.repository.query.FluentQuery; import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery; import org.springframework.data.util.TypeInformation; import org.springframework.graphql.data.GraphQlRepository; +import org.springframework.graphql.data.query.AutoRegistrationRuntimeWiringConfigurer.DataFetcherFactory; import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.execution.SelfDescribingDataFetcher; import org.springframework.util.Assert; @@ -219,13 +220,23 @@ public abstract class QuerydslDataFetcher { List> executors, List> reactiveExecutors) { - Map>> factories = new HashMap<>(); + Map factories = new HashMap<>(); for (QuerydslPredicateExecutor executor : executors) { String typeName = RepositoryUtils.getGraphQlTypeName(executor); if (typeName != null) { Builder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor))); - factories.put(typeName, single -> single ? builder.single() : builder.many()); + factories.put(typeName, new DataFetcherFactory() { + @Override + public DataFetcher single() { + return builder.single(); + } + + @Override + public DataFetcher many() { + return builder.many(); + } + }); } } @@ -233,7 +244,17 @@ public abstract class QuerydslDataFetcher { String typeName = RepositoryUtils.getGraphQlTypeName(executor); if (typeName != null) { ReactiveBuilder builder = customize(executor, QuerydslDataFetcher.builder(executor).customizer(customizer(executor))); - factories.put(typeName, single -> single ? builder.single() : builder.many()); + factories.put(typeName, new DataFetcherFactory() { + @Override + public DataFetcher single() { + return builder.single(); + } + + @Override + public DataFetcher many() { + return builder.many(); + } + }); } }