Use ReactiveAdapterRegistry for return type checks

See gh-991
This commit is contained in:
rstoyanchev
2024-06-12 12:20:42 +01:00
parent 3ea4b38ace
commit e00e10c742
2 changed files with 16 additions and 37 deletions

View File

@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
@@ -31,13 +30,13 @@ import graphql.schema.GraphQLSchema;
import graphql.schema.TypeResolver;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.TypeDefinitionRegistry;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.context.ApplicationContext;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.graphql.data.GraphQlArgumentBinder;
import org.springframework.graphql.data.method.HandlerMethod;
@@ -188,15 +187,16 @@ public final class FederationSchemaFactory
public record EntityMappingInfo(String typeName, HandlerMethod handlerMethod) {
public boolean isBatchHandlerMethod() {
MethodParameter type = handlerMethod().getReturnType();
Class<?> paramType = type.getParameterType();
if (Flux.class.isAssignableFrom(paramType)) {
return true;
MethodParameter returnType = handlerMethod().getReturnType();
Class<?> clazz = returnType.getParameterType();
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(clazz);
if (adapter != null) {
if (adapter.isMultiValue()) {
return true;
}
returnType = returnType.nested();
}
if (Mono.class.isAssignableFrom(paramType) || CompletionStage.class.isAssignableFrom(paramType)) {
type = type.nested();
}
return List.class.isAssignableFrom(type.getParameterType());
return List.class.isAssignableFrom(returnType.getNestedParameterType());
}
}

View File

@@ -45,13 +45,6 @@ import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLCodeRegistry;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.TypeDefinitionRegistry;
import kotlin.jvm.JvmClassMappingKt;
import kotlin.reflect.KFunction;
import kotlin.reflect.KType;
import kotlin.reflect.full.KClassifiers;
import kotlin.reflect.full.KTypes;
import kotlin.reflect.jvm.ReflectJvmMapping;
import kotlinx.coroutines.flow.Flow;
import org.dataloader.DataLoader;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@@ -64,6 +57,8 @@ import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.data.domain.ScrollPosition;
@@ -384,15 +379,15 @@ public class AnnotatedControllerConfigurer
clazz = returnType.getNestedParameterType();
}
if (clazz.equals(Flux.class) || Collection.class.isAssignableFrom(clazz) ||
(KotlinDetector.isSuspendingFunction(method) && KotlinDelegate.isFlowReturnType(method))) {
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(clazz);
if (Collection.class.isAssignableFrom(clazz) || (adapter != null && adapter.isMultiValue())) {
registration.registerBatchLoader(invocable::invokeForIterable);
ResolvableType valueType = ResolvableType.forMethodParameter(returnType.nested());
return new BatchMappingDataFetcher(info, valueType, dataLoaderKey);
}
if (clazz.equals(Mono.class)) {
if (adapter != null) {
returnType = returnType.nested();
clazz = returnType.getNestedParameterType();
}
@@ -672,20 +667,4 @@ public class AnnotatedControllerConfigurer
}
}
/**
* Inner class to avoid a hard dependency on Kotlin at runtime.
*/
private static final class KotlinDelegate {
private static final KType flowType =
KClassifiers.getStarProjectedType(JvmClassMappingKt.getKotlinClass(Flow.class));
static boolean isFlowReturnType(Method method) {
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
return (function != null && KTypes.isSubtypeOf(function.getReturnType(), flowType));
}
}
}