Polishing.

Allow nullable OffsetScrollPosition and add support for values wrapped within Optional.

Update tests. Reformat code. Add issue tags to tests.

See #2856
Original pull request: #2861
This commit is contained in:
Mark Paluch
2023-07-04 15:44:54 +02:00
parent 391607bd14
commit 80b8e12641
6 changed files with 220 additions and 147 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@ package org.springframework.data.web;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -27,27 +26,31 @@ import org.springframework.web.method.support.ModelAndViewContainer;
/**
* Argument resolver to extract a {@link OffsetScrollPosition} object from a {@link NativeWebRequest} for a particular
* {@link MethodParameter}. A {@link OffsetScrollPositionArgumentResolver} can either resolve {@link OffsetScrollPosition} itself or wrap another
* {@link OffsetScrollPositionArgumentResolver} to post-process {@link OffsetScrollPosition}.
* {@link MethodParameter}. A {@link OffsetScrollPositionArgumentResolver} can either resolve
* {@link OffsetScrollPosition} itself or wrap another {@link OffsetScrollPositionArgumentResolver} to post-process
* {@link OffsetScrollPosition}.
*
* @since 3.2
* @author Yanming Zhou
* @see HandlerMethodArgumentResolver
* @author Mark Paluch
* @since 3.2
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver
*/
public interface OffsetScrollPositionArgumentResolver extends HandlerMethodArgumentResolver {
/**
* Resolves a {@link OffsetScrollPosition} method parameter into an argument value from a given request.
* Resolves a {@link OffsetScrollPosition} method parameter into an argument value from a given request. Supports also
* wrapped arguments in {@link java.util.Optional}.
*
* @param parameter the method parameter to resolve. This parameter must have previously been passed to
* {@link #supportsParameter} which must have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value
* @return the resolved argument value or {@literal null} if the value cannot be resolved. The returned value
* considers {@link MethodParameter#isOptional() Optional} wrapping by returing either the value wrapped
* within Optional or Optional.empty().
*/
@NonNull
@Override
OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
*/
package org.springframework.data.web;
import java.util.Arrays;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.lang.Nullable;
@@ -23,27 +25,28 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import java.util.Arrays;
/**
* {@link HandlerMethodArgumentResolver} to automatically create {@link OffsetScrollPosition} instances from request parameters.
* {@link HandlerMethodArgumentResolver} to automatically create {@link OffsetScrollPosition} instances from request
* parameters.
*
* @since 3.2
* @author Yanming Zhou
* @since 3.2
*/
public class OffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport
implements OffsetScrollPositionArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return OffsetScrollPosition.class.equals(parameter.getParameterType());
return OffsetScrollPosition.class.equals(parameter.nestedIfOptional().getNestedParameterType());
}
@Override
public OffsetScrollPosition resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
String[] offsetParameter = webRequest.getParameterValues(getOffsetParameter(parameter));
return parseParameterIntoOffsetScrollPosition(offsetParameter != null ? Arrays.asList(offsetParameter) : null);
String[] offsetParameter = webRequest.getParameterValues(getOffsetParameter(parameter.nestedIfOptional()));
return adaptArgumentIfNecessary(
parseParameterIntoOffsetScrollPosition(offsetParameter != null ? Arrays.asList(offsetParameter) : null),
parameter);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,22 +15,23 @@
*/
package org.springframework.data.web;
import java.util.List;
import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
/**
* Base class providing methods for handler method argument resolvers to create {@link OffsetScrollPosition} instances from request
* parameters.
* Base class providing methods for handler method argument resolvers to create {@link OffsetScrollPosition} instances
* from request parameters.
*
* @since 3.2
* @author Yanming Zhou
* @since 3.2
* @see OffsetScrollPositionHandlerMethodArgumentResolver
* @see ReactiveOffsetScrollPositionHandlerMethodArgumentResolver
*/
@@ -71,7 +72,7 @@ public abstract class OffsetScrollPositionHandlerMethodArgumentResolverSupport {
* @param parameter can be {@literal null}.
* @return the offset parameter
*/
protected String getOffsetParameter(@Nullable MethodParameter parameter) {
protected String getOffsetParameter(MethodParameter parameter) {
StringBuilder builder = new StringBuilder();
@@ -89,19 +90,39 @@ public abstract class OffsetScrollPositionHandlerMethodArgumentResolverSupport {
* Parses the given source into a {@link OffsetScrollPosition} instance.
*
* @param source could be {@literal null} or empty.
* @return parsed OffsetScrollPosition
* @return parsed OffsetScrollPosition or {@literal null} if it cannot be constructed.
*/
@Nullable
OffsetScrollPosition parseParameterIntoOffsetScrollPosition(@Nullable List<String> source) {
// No parameter or Single empty parameter, e.g "offset="
if (source == null || source.size() == 1 && !StringUtils.hasText(source.get(0))) {
return ScrollPosition.offset();
if (CollectionUtils.isEmpty(source) || (source.size() == 1 && !StringUtils.hasText(source.get(0)))) {
return null;
}
try {
long offset = Long.parseLong(source.get(0));
return ScrollPosition.offset(offset);
} catch (NumberFormatException ex) {
return ScrollPosition.offset();
return null;
}
}
/**
* Adapt the given argument against the method parameter, if necessary.
*
* @param arg the resolved argument.
* @param parameter the method parameter descriptor.
* @return the adapted argument, or the original resolved argument as-is.
*/
@Nullable
Object adaptArgumentIfNecessary(@Nullable Object arg, MethodParameter parameter) {
if (parameter.getParameterType() == Optional.class) {
return arg == null ? Optional.empty() : Optional.of(arg);
}
return arg;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,37 +15,36 @@
*/
package org.springframework.data.web;
import java.util.List;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.lang.NonNull;
import org.springframework.web.reactive.BindingContext;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.reactive.result.method.SyncHandlerMethodArgumentResolver;
import org.springframework.web.server.ServerWebExchange;
import java.util.List;
/**
* Reactive {@link HandlerMethodArgumentResolver} to create {@link OffsetScrollPosition} instances from query string parameters.
* Reactive {@link HandlerMethodArgumentResolver} to create {@link OffsetScrollPosition} instances from query string
* parameters.
*
* @since 3.2
* @author Yanming Zhou
* @since 3.2
*/
public class ReactiveOffsetScrollPositionHandlerMethodArgumentResolver extends OffsetScrollPositionHandlerMethodArgumentResolverSupport
implements SyncHandlerMethodArgumentResolver {
public class ReactiveOffsetScrollPositionHandlerMethodArgumentResolver
extends OffsetScrollPositionHandlerMethodArgumentResolverSupport implements SyncHandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return OffsetScrollPosition.class.equals(parameter.getParameterType());
return OffsetScrollPosition.class.equals(parameter.nestedIfOptional().getNestedParameterType());
}
@NonNull
@Override
public OffsetScrollPosition resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
ServerWebExchange exchange) {
List<String> offsetParameter = exchange.getRequest().getQueryParams().get(getOffsetParameter(parameter));
return parseParameterIntoOffsetScrollPosition(offsetParameter);
return adaptArgumentIfNecessary(parseParameterIntoOffsetScrollPosition(offsetParameter), parameter);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,12 @@
*/
package org.springframework.data.web;
import static org.assertj.core.api.Assertions.*;
import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeAll;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.MethodParameter;
@@ -28,40 +32,30 @@ import org.springframework.util.StringUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link OffsetScrollPositionHandlerMethodArgumentResolver}.
*
* @since 3.2
* @author Yanming Zhou
* @author Mark Paluch
*/
class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
static MethodParameter PARAMETER;
static final MethodParameter PARAMETER = getParameterOfMethod("supportedMethod");
static final MethodParameter OPTIONAL_PARAMETER = getOptionalParameterOfMethod("supportedMethodWithOptional");
@BeforeAll
static void setUp() throws Exception {
PARAMETER = getParameterOfMethod("supportedMethod");
}
final OffsetScrollPositionHandlerMethodArgumentResolver sut = new OffsetScrollPositionHandlerMethodArgumentResolver();
@Test
@Test // GH-2856
void supportsSortParameter() {
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver();
assertThat(resolver.supportsParameter(PARAMETER)).isTrue();
assertThat(sut.supportsParameter(PARAMETER)).isTrue();
}
@Test
void fallbackToDefaultOffset() {
var parameter = TestUtils.getParameterOfMethod(Controller.class, "unsupportedMethod", String.class);
var position = resolveOffset(new MockHttpServletRequest(), parameter);
assertThat(position).isEqualTo(ScrollPosition.offset());
@Test // GH-2856
void supportsOptionalOffsetScrollPositionParameter() {
assertThat(sut.supportsParameter(OPTIONAL_PARAMETER)).isTrue();
}
@Test
@Test // GH-2856
void discoversOffsetFromRequest() {
var reference = ScrollPosition.offset(5);
@@ -69,7 +63,35 @@ class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, null), PARAMETER, reference);
}
@Test
@Test // GH-2856
void returnsNullIfNotSpecified() {
var request = new MockHttpServletRequest();
var position = resolveOffset(request, PARAMETER);
assertThat(position).isNull();
}
@Test // GH-2856
void returnsOptionalParameterFromRequest() {
var request = new MockHttpServletRequest();
request.addParameter("offset", "5");
var position = resolveOffset(request, OPTIONAL_PARAMETER);
assertThat(position).isEqualTo(Optional.of(ScrollPosition.offset(5)));
}
@Test // GH-2856
void returnsEmptyOptionalIfNotSpecified() {
var request = new MockHttpServletRequest();
var position = resolveOffset(request, OPTIONAL_PARAMETER);
assertThat(position).isEqualTo(Optional.empty());
}
@Test // GH-2856
void discoversOffsetFromRequestWithMultipleParams() {
var request = new MockHttpServletRequest();
@@ -79,43 +101,43 @@ class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset(5));
}
@Test
@Test // GH-2856
void discoversQualifiedOffsetFromRequest() {
var parameter = getParameterOfMethod("qualifiedOffset");
var reference = ScrollPosition.offset(5);
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "qual"), parameter, reference);
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "hello"), parameter, reference);
}
@Test
void returnsDefaultForOffsetParamSetToNothing() {
@Test // GH-2856
void returnsNullForOffsetParamSetToNothing() {
var request = new MockHttpServletRequest();
request.addParameter("offset", (String) null);
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
assertThat(resolveOffset(request, PARAMETER)).isNull();
}
@Test
void returnsDefaultForEmptyOffsetParam() {
@Test // GH-2856
void returnsNullForEmptyOffsetParam() {
var request = new MockHttpServletRequest();
request.addParameter("offset", "");
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
assertThat(resolveOffset(request, PARAMETER)).isNull();
}
@Test
void returnsDefaultForOffsetParamIsInvalidProperty() {
@Test // GH-2856
void returnsNullForOffsetParamIsInvalidProperty() {
var request = new MockHttpServletRequest();
request.addParameter("offset", "invalid_number");
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
assertThat(resolveOffset(request, PARAMETER)).isNull();
}
@Test
@Test // GH-2856
void emptyQualifierIsUsedInParameterLookup() {
var parameter = getParameterOfMethod("emptyQualifier");
@@ -124,7 +146,7 @@ class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, ""), parameter, reference);
}
@Test
@Test // GH-2856
void mergedQualifierIsUsedInParameterLookup() {
var parameter = getParameterOfMethod("mergedQualifier");
@@ -133,30 +155,28 @@ class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "merged"), parameter, reference);
}
private static OffsetScrollPosition resolveOffset(HttpServletRequest request, MethodParameter parameter) {
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver();
return resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null);
@Nullable
private Object resolveOffset(HttpServletRequest request, MethodParameter parameter) {
return sut.resolveArgument(parameter, null, new ServletWebRequest(request), null);
}
private static void assertSupportedAndResolvedTo(NativeWebRequest request, MethodParameter parameter, OffsetScrollPosition position) {
private void assertSupportedAndResolvedTo(NativeWebRequest request, MethodParameter parameter,
OffsetScrollPosition position) {
var resolver = new OffsetScrollPositionHandlerMethodArgumentResolver();
assertThat(resolver.supportsParameter(parameter)).isTrue();
try {
assertThat(resolver.resolveArgument(parameter, null, request, null)).isEqualTo(position);
} catch (Exception e) {
throw new RuntimeException(e);
}
assertThat(sut.supportsParameter(parameter)).isTrue();
assertThat(sut.resolveArgument(parameter, null, request, null)).isEqualTo(position);
}
private static MethodParameter getParameterOfMethod(String name) {
return TestUtils.getParameterOfMethod(Controller.class, name, OffsetScrollPosition.class);
}
private static NativeWebRequest getRequestWithOffset(@Nullable OffsetScrollPosition position, @Nullable String qualifier) {
private static MethodParameter getOptionalParameterOfMethod(String name) {
return TestUtils.getParameterOfMethod(Controller.class, name, Optional.class);
}
private static NativeWebRequest getRequestWithOffset(@Nullable OffsetScrollPosition position,
@Nullable String qualifier) {
var request = new MockHttpServletRequest();
@@ -174,9 +194,11 @@ class OffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
void supportedMethod(OffsetScrollPosition offset);
void supportedMethodWithOptional(Optional<OffsetScrollPosition> offset);
void unsupportedMethod(String string);
void qualifiedOffset(@Qualifier("qual") OffsetScrollPosition offset);
void qualifiedOffset(@Qualifier("hello") OffsetScrollPosition offset);
void emptyQualifier(@Qualifier OffsetScrollPosition offset);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2023 the original author or authors.
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,10 @@
*/
package org.springframework.data.web;
import org.junit.jupiter.api.BeforeAll;
import static org.assertj.core.api.Assertions.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.MethodParameter;
@@ -26,41 +29,40 @@ import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests for {@link ReactiveOffsetScrollPositionHandlerMethodArgumentResolver}.
*
* @since 3.2
* @author Yanming Zhou
* @author Mark Paluch
*/
class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
static MethodParameter PARAMETER;
static final MethodParameter PARAMETER = getParameterOfMethod("supportedMethod");
static final MethodParameter OPTIONAL_PARAMETER = getOptionalParameterOfMethod("supportedMethodWithOptional");
@BeforeAll
static void setUp() throws Exception {
PARAMETER = getParameterOfMethod("supportedMethod");
final ReactiveOffsetScrollPositionHandlerMethodArgumentResolver sut = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver();
@Test // GH-2856
void supportsOffsetScrollPositionParameter() {
assertThat(sut.supportsParameter(PARAMETER)).isTrue();
}
@Test
void supportsSortParameter() {
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver();
assertThat(resolver.supportsParameter(PARAMETER)).isTrue();
@Test // GH-2856
void supportsOptionalOffsetScrollPositionParameter() {
assertThat(sut.supportsParameter(OPTIONAL_PARAMETER)).isTrue();
}
@Test
void fallbackToDefaultOffset() {
@Test // GH-2856
void fallbackToNullOffset() {
var parameter = TestUtils.getParameterOfMethod(Controller.class, "unsupportedMethod", String.class);
var request = MockServerHttpRequest.get("/foo").build();
var position = resolveOffset(request, parameter);
assertThat(position).isEqualTo(ScrollPosition.offset());
assertThat(position).isNull();
}
@Test
@Test // GH-2856
void discoversOffsetFromRequest() {
var reference = ScrollPosition.offset(5);
@@ -68,7 +70,34 @@ class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, null), PARAMETER, reference);
}
@Test
@Test // GH-2856
void returnsNullIfNotSpecified() {
var request = MockServerHttpRequest.get("/foo").build();
var position = resolveOffset(request, PARAMETER);
assertThat(position).isNull();
}
@Test // GH-2856
void returnsOptionalParameterFromRequest() {
var request = MockServerHttpRequest.get("/foo?offset=5").build();
var position = resolveOffset(request, OPTIONAL_PARAMETER);
assertThat(position).isEqualTo(Optional.of(ScrollPosition.offset(5)));
}
@Test // GH-2856
void returnsEmptyOptionalIfNotSpecified() {
var request = MockServerHttpRequest.get("/foo").build();
var position = resolveOffset(request, OPTIONAL_PARAMETER);
assertThat(position).isEqualTo(Optional.empty());
}
@Test // GH-2856
void discoversOffsetFromRequestWithMultipleParams() {
var request = MockServerHttpRequest.get("/foo?offset=5&offset=6").build();
@@ -76,40 +105,32 @@ class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset(5));
}
@Test
@Test // GH-2856
void discoversQualifiedOffsetFromRequest() {
var parameter = getParameterOfMethod("qualifiedOffset");
var reference = ScrollPosition.offset(5);
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "qual"), parameter, reference);
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "hello"), parameter, reference);
}
@Test
void returnsDefaultForOffsetParamSetToNothing() {
var request = MockServerHttpRequest.get("/foo").build();
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
}
@Test
void returnsDefaultForEmptyOffsetParam() {
@Test // GH-2856
void returnsNullForEmptyOffsetParam() {
var request = MockServerHttpRequest.get("/foo?offset=").build();
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
assertThat(resolveOffset(request, PARAMETER)).isNull();
}
@Test
void returnsDefaultForOffsetParamIsInvalidProperty() {
@Test // GH-2856
void returnsNullForOffsetParamIsInvalidProperty() {
var request = MockServerHttpRequest.get("/foo?offset=invalid_number").build();
assertThat(resolveOffset(request, PARAMETER)).isEqualTo(ScrollPosition.offset());
assertThat(resolveOffset(request, PARAMETER)).isNull();
}
@Test
@Test // GH-2856
void emptyQualifierIsUsedInParameterLookup() {
var parameter = getParameterOfMethod("emptyQualifier");
@@ -118,7 +139,7 @@ class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, ""), parameter, reference);
}
@Test
@Test // GH-2856
void mergedQualifierIsUsedInParameterLookup() {
var parameter = getParameterOfMethod("mergedQualifier");
@@ -127,47 +148,51 @@ class ReactiveOffsetScrollPositionHandlerMethodArgumentResolverUnitTests {
assertSupportedAndResolvedTo(getRequestWithOffset(reference, "merged"), parameter, reference);
}
private static OffsetScrollPosition resolveOffset(MockServerHttpRequest request, MethodParameter parameter) {
@Nullable
private static Object resolveOffset(MockServerHttpRequest request, MethodParameter parameter) {
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver();
return resolver.resolveArgumentValue(parameter, null, MockServerWebExchange.from(request));
}
private static void assertSupportedAndResolvedTo(MockServerHttpRequest request, MethodParameter parameter, OffsetScrollPosition position) {
private void assertSupportedAndResolvedTo(MockServerHttpRequest request, MethodParameter parameter,
OffsetScrollPosition position) {
var resolver = new ReactiveOffsetScrollPositionHandlerMethodArgumentResolver();
assertThat(resolver.supportsParameter(parameter)).isTrue();
assertThat(sut.supportsParameter(parameter)).isTrue();
try {
var resolved = resolveOffset(request, parameter);
assertThat(resolved).isEqualTo(position);
} catch (Exception e) {
throw new RuntimeException(e);
}
var resolved = resolveOffset(request, parameter);
assertThat(resolved).isEqualTo(position);
}
private static MethodParameter getParameterOfMethod(String name) {
return TestUtils.getParameterOfMethod(Controller.class, name, OffsetScrollPosition.class);
}
private static MockServerHttpRequest getRequestWithOffset(@Nullable OffsetScrollPosition position, @Nullable String qualifier) {
private static MethodParameter getOptionalParameterOfMethod(String name) {
return TestUtils.getParameterOfMethod(Controller.class, name, Optional.class);
}
private static MockServerHttpRequest getRequestWithOffset(@Nullable OffsetScrollPosition position,
@Nullable String qualifier) {
if (position == null) {
return TestUtils.getWebfluxRequest();
}
String parameterName = StringUtils.hasLength(qualifier) ? qualifier + "_offset" : "offset";
return MockServerHttpRequest.get(String.format("foo?%s=%s", parameterName, String.valueOf(position.getOffset()))).build();
return MockServerHttpRequest.get(String.format("foo?%s=%s", parameterName, String.valueOf(position.getOffset())))
.build();
}
interface Controller {
void supportedMethod(OffsetScrollPosition offset);
void supportedMethodWithOptional(Optional<OffsetScrollPosition> offset);
void unsupportedMethod(String string);
void qualifiedOffset(@Qualifier("qual") OffsetScrollPosition offset);
void qualifiedOffset(@Qualifier("hello") OffsetScrollPosition offset);
void emptyQualifier(@Qualifier OffsetScrollPosition offset);