CursorStrategy is now also detected as a bean
See gh-620
This commit is contained in:
@@ -58,6 +58,7 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.ScrollPosition;
|
||||
import org.springframework.format.FormatterRegistrar;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
@@ -82,14 +83,27 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.DataBinder;
|
||||
|
||||
/**
|
||||
* {@link RuntimeWiringConfigurer} that detects {@link SchemaMapping @SchemaMapping}
|
||||
* annotated handler methods in {@link Controller @Controller} classes and
|
||||
* registers them as {@link DataFetcher}s.
|
||||
* {@link RuntimeWiringConfigurer} that finds {@link SchemaMapping @SchemaMapping}
|
||||
* annotated handler methods in {@link Controller @Controller} classes declared in
|
||||
* Spring configuration, and registers them as {@link DataFetcher}s.
|
||||
*
|
||||
* <p>In addition to initializing a {@link RuntimeWiring.Builder}, this class, also
|
||||
* provides an option to {@link #configure(GraphQLCodeRegistry.Builder) configure}
|
||||
* data fetchers on a {@link GraphQLCodeRegistry.Builder}.
|
||||
*
|
||||
* <p>This class detects the following strategies in Spring configuration,
|
||||
* expecting to find a single, unique bean of that type:
|
||||
* <ul>
|
||||
* <li>{@link CursorStrategy} -- if Spring Data is present, and the strategy
|
||||
* supports {@code ScrollPosition}, then {@link ScrollSubrangeMethodArgumentResolver}
|
||||
* is configured for use. If not, then {@link SubrangeMethodArgumentResolver}
|
||||
* is added instead.
|
||||
* <li>{@link SortStrategy} -- if present, then {@link SortMethodArgumentResolver}
|
||||
* is configured for use.
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Brian Clozel
|
||||
* @since 1.0.0
|
||||
@@ -125,9 +139,6 @@ public class AnnotatedControllerConfigurer implements ApplicationContextAware, I
|
||||
|
||||
private final FormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||
|
||||
@Nullable
|
||||
private CursorStrategy<?> cursorStrategy;
|
||||
|
||||
private final List<HandlerMethodArgumentResolver> customArgumentResolvers = new ArrayList<>(8);
|
||||
|
||||
@Nullable
|
||||
@@ -156,21 +167,6 @@ public class AnnotatedControllerConfigurer implements ApplicationContextAware, I
|
||||
registrar.registerFormatters(this.conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a {@link CursorStrategy} to handle pagination requests, which
|
||||
* results in one of the following:
|
||||
* <ul>
|
||||
* <li>If Spring Data is present, and the strategy supports {@code ScrollPosition},
|
||||
* then {@link ScrollSubrangeMethodArgumentResolver} is configured as a method
|
||||
* argument resolver.
|
||||
* <li>Otherwise {@link SubrangeMethodArgumentResolver} is added.
|
||||
* </ul>
|
||||
* @since 1.2
|
||||
*/
|
||||
public void setCursorStrategy(@Nullable CursorStrategy<?> cursorStrategy) {
|
||||
this.cursorStrategy = cursorStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link HandlerMethodArgumentResolver} for custom controller method
|
||||
* arguments. Such custom resolvers are ordered after built-in resolvers
|
||||
@@ -270,18 +266,8 @@ public class AnnotatedControllerConfigurer implements ApplicationContextAware, I
|
||||
// Type based
|
||||
resolvers.addResolver(new DataFetchingEnvironmentMethodArgumentResolver());
|
||||
resolvers.addResolver(new DataLoaderMethodArgumentResolver());
|
||||
if (this.cursorStrategy != null) {
|
||||
resolvers.addResolver(createSubrangeMethodArgumentResolver(this.cursorStrategy));
|
||||
}
|
||||
if (springDataPresent) {
|
||||
try {
|
||||
resolvers.addResolver(
|
||||
new SortMethodArgumentResolver(obtainApplicationContext().getBean(SortStrategy.class)));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
addSubrangeMethodArgumentResolver(resolvers);
|
||||
addSortMethodArgumentResolver(resolvers);
|
||||
if (springSecurityPresent) {
|
||||
ApplicationContext context = obtainApplicationContext();
|
||||
resolvers.addResolver(new PrincipalMethodArgumentResolver());
|
||||
@@ -299,15 +285,34 @@ public class AnnotatedControllerConfigurer implements ApplicationContextAware, I
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static HandlerMethodArgumentResolver createSubrangeMethodArgumentResolver(CursorStrategy<?> strategy) {
|
||||
@SuppressWarnings({"unchecked", "CastCanBeRemovedNarrowingVariableType"})
|
||||
private void addSubrangeMethodArgumentResolver(HandlerMethodArgumentResolverComposite resolvers) {
|
||||
try {
|
||||
CursorStrategy<?> strategy = obtainApplicationContext().getBean(CursorStrategy.class);
|
||||
if (springDataPresent) {
|
||||
if (strategy.supports(ScrollPosition.class)) {
|
||||
CursorStrategy<ScrollPosition> strategyToUse = (CursorStrategy<ScrollPosition>) strategy;
|
||||
resolvers.addResolver(new ScrollSubrangeMethodArgumentResolver(strategyToUse));
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolvers.addResolver(new SubrangeMethodArgumentResolver<>(strategy));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void addSortMethodArgumentResolver(HandlerMethodArgumentResolverComposite resolvers) {
|
||||
if (springDataPresent) {
|
||||
if (strategy.supports(org.springframework.data.domain.ScrollPosition.class)) {
|
||||
return new ScrollSubrangeMethodArgumentResolver(
|
||||
(CursorStrategy<org.springframework.data.domain.ScrollPosition>) strategy);
|
||||
try {
|
||||
SortStrategy strategy = obtainApplicationContext().getBean(SortStrategy.class);
|
||||
resolvers.addResolver(new SortMethodArgumentResolver(strategy));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return new SubrangeMethodArgumentResolver<>(strategy);
|
||||
}
|
||||
|
||||
protected final ApplicationContext obtainApplicationContext() {
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.graphql.GraphQlSetup;
|
||||
import org.springframework.graphql.TestExecutionRequest;
|
||||
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||
import org.springframework.graphql.data.pagination.ConnectionFieldTypeVisitor;
|
||||
import org.springframework.graphql.data.pagination.CursorStrategy;
|
||||
import org.springframework.graphql.data.query.ScrollPositionCursorStrategy;
|
||||
import org.springframework.graphql.data.query.ScrollSubrange;
|
||||
import org.springframework.graphql.data.query.WindowConnectionAdapter;
|
||||
@@ -81,16 +82,7 @@ public class SchemaMappingPaginationTests {
|
||||
}
|
||||
""";
|
||||
|
||||
ExecutionGraphQlService graphQlService = graphQlService((configurer, setup) -> {
|
||||
|
||||
setup.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer());
|
||||
|
||||
ScrollPositionCursorStrategy cursorStrategy = new ScrollPositionCursorStrategy();
|
||||
WindowConnectionAdapter connectionAdapter = new WindowConnectionAdapter(cursorStrategy);
|
||||
setup.typeVisitor(ConnectionFieldTypeVisitor.create(List.of(connectionAdapter)));
|
||||
|
||||
configurer.setCursorStrategy(cursorStrategy);
|
||||
});
|
||||
ExecutionGraphQlService graphQlService = graphQlService();
|
||||
|
||||
ExecutionGraphQlResponse response =
|
||||
graphQlService.execute(TestExecutionRequest.forDocument(document)).block();
|
||||
@@ -110,19 +102,22 @@ public class SchemaMappingPaginationTests {
|
||||
"}}}");
|
||||
}
|
||||
|
||||
private ExecutionGraphQlService graphQlService(BiConsumer<AnnotatedControllerConfigurer, GraphQlSetup> consumer) {
|
||||
private ExecutionGraphQlService graphQlService() {
|
||||
|
||||
ScrollPositionCursorStrategy cursorStrategy = new ScrollPositionCursorStrategy();
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(BookController.class);
|
||||
context.registerBean(CursorStrategy.class, () -> cursorStrategy);
|
||||
context.refresh();
|
||||
|
||||
AnnotatedControllerConfigurer configurer = new AnnotatedControllerConfigurer();
|
||||
configurer.setApplicationContext(context);
|
||||
configurer.afterPropertiesSet();
|
||||
|
||||
GraphQlSetup setup = GraphQlSetup.schemaContent(SCHEMA).runtimeWiring(configurer);
|
||||
consumer.accept(configurer, setup);
|
||||
|
||||
configurer.afterPropertiesSet();
|
||||
setup.typeDefinitionConfigurer(new ConnectionTypeDefinitionConfigurer());
|
||||
setup.typeVisitor(ConnectionFieldTypeVisitor.create(List.of(new WindowConnectionAdapter(cursorStrategy))));
|
||||
|
||||
return setup.toGraphQlService();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user