Avoid pre-computing base URI in PagedResourceAssemblerArgumentResolver.

We now avoid the pre-computation of the base URI in PagedResourceAssemblerArgumentResolver as the actual assembler will fall back to using the URI of the current request by default anyway. The latter makes sure that request parameters, that are contained in the original requests appear in links created. If a controller wants to deviate from that behavior, they can create a dedicated link themselves and hand that to the assembler explicitly.

Fixes GH-2173, GH-452.
This commit is contained in:
Oliver Drotbohm
2021-01-26 09:58:52 +01:00
parent 3d7cabf814
commit 1e13d40cbb
5 changed files with 37 additions and 67 deletions

View File

@@ -18,17 +18,13 @@ package org.springframework.data.web;
import static org.assertj.core.api.Assertions.*;
import java.lang.reflect.Method;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.Pageable;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.util.UriComponents;
/**
* Unit tests for {@link PagedResourcesAssemblerArgumentResolver}.
@@ -46,7 +42,7 @@ class PagedResourcesAssemblerArgumentResolverUnitTests {
WebTestUtils.initWebTest();
HateoasPageableHandlerMethodArgumentResolver hateoasPageableHandlerMethodArgumentResolver = new HateoasPageableHandlerMethodArgumentResolver();
this.resolver = new PagedResourcesAssemblerArgumentResolver(hateoasPageableHandlerMethodArgumentResolver, null);
this.resolver = new PagedResourcesAssemblerArgumentResolver(hateoasPageableHandlerMethodArgumentResolver);
}
@Test // DATACMNS-418
@@ -112,30 +108,6 @@ class PagedResourcesAssemblerArgumentResolverUnitTests {
assertThat(result).isNotNull();
}
@Test // DATACMNS-513
void detectsMappingOfInvokedSubType() throws Exception {
Method method = Controller.class.getMethod("methodWithMapping", PagedResourcesAssembler.class);
// Simulate HandlerMethod.HandlerMethodParameter.getDeclaringClass()
// as it's returning the invoked class as the declared one
MethodParameter methodParameter = new MethodParameter(method, 0) {
public java.lang.Class<?> getDeclaringClass() {
return SubController.class;
}
};
Object result = resolver.resolveArgument(methodParameter, null, null, null);
assertThat(result).isInstanceOf(PagedResourcesAssembler.class);
Optional<UriComponents> uriComponents = (Optional<UriComponents>) ReflectionTestUtils.getField(result, "baseUri");
assertThat(uriComponents).hasValueSatisfying(it -> {
assertThat(it.getPath()).isEqualTo("/foo/mapping");
});
}
private void assertSelectsParameter(Method method, int expectedIndex) {
MethodParameter parameter = new MethodParameter(method, 0);
@@ -190,9 +162,4 @@ class PagedResourcesAssemblerArgumentResolverUnitTests {
@RequestMapping("/mapping")
Object methodWithMapping(PagedResourcesAssembler<Object> pageable);
}
@RequestMapping("/foo")
interface SubController extends Controller {
}
}

View File

@@ -38,6 +38,7 @@ import org.springframework.hateoas.PagedModel.PageMetadata;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.hateoas.server.RepresentationModelAssembler;
import org.springframework.hateoas.server.core.EmbeddedWrapper;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
@@ -257,6 +258,17 @@ class PagedResourcesAssemblerUnitTests {
assertThat(resource.getRequiredLink(IanaLinkRelations.SELF).getHref()).endsWith("?page=0&size=1");
}
@Test // #2173
void keepsRequestParametersOfOriginalRequestUri() {
WebTestUtils.initWebTest(new MockHttpServletRequest("GET", "/sample?foo=bar"));
PagedModel<EntityModel<Person>> model = assembler.toModel(createPage(1));
assertThat(model.getRequiredLink(IanaLinkRelations.FIRST).getHref())
.isEqualTo("http://localhost/sample?foo=bar&page=0&size=1");
}
private static Page<Person> createPage(int index) {
Pageable request = PageRequest.of(index, 1);

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.web;
import javax.servlet.http.HttpServletRequest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.WebApplicationContext;
@@ -33,8 +35,14 @@ public class WebTestUtils {
* Initializes web tests. Will register a {@link MockHttpServletRequest} for the current thread.
*/
public static void initWebTest() {
initWebTest(new MockHttpServletRequest());
}
/**
* Initializes web tests for the given {@link HttpServletRequest} which will registered for the current thread.
*/
public static void initWebTest(HttpServletRequest request) {
MockHttpServletRequest request = new MockHttpServletRequest();
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
RequestContextHolder.setRequestAttributes(requestAttributes);
}