From db5995eee0a991600b7be83fcf58a6a9eafeecb0 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Fri, 27 Mar 2020 11:54:18 +0100 Subject: [PATCH] DATAREST-762 - Collection resource's base link now forwards parameters. We now use the current request's URI as base link for all links created for a collection resource. This especially has effect in the creation of pagination links as we now carry potentially applied critierias (induced by our Querydsl based filtering support) forward to the navigation links generated. --- .../rest/tests/mongodb/UserRepository.java | 16 +++++++- .../rest/tests/mongodb/MongoWebTests.java | 39 +++++++++++++++++++ .../webmvc/RepositoryEntityController.java | 3 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/UserRepository.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/UserRepository.java index b683d6483..74f9e26e2 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/UserRepository.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/UserRepository.java @@ -19,15 +19,27 @@ import java.math.BigInteger; import java.util.List; import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; +import org.springframework.data.querydsl.binding.QuerydslBindings; +import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; /** * @author Oliver Gierke */ -public interface UserRepository extends CrudRepository, QuerydslPredicateExecutor { +public interface UserRepository extends PagingAndSortingRepository, QuerydslPredicateExecutor, + QuerydslBinderCustomizer { List findByFirstname(String firstname); List findByColleaguesContains(@Param("colleagues") User colleague); + + /* + * (non-Javadoc) + * @see org.springframework.data.querydsl.binding.QuerydslBinderCustomizer#customize(org.springframework.data.querydsl.binding.QuerydslBindings, com.querydsl.core.types.EntityPath) + */ + @Override + default void customize(QuerydslBindings bindings, QUser root) { + bindings.bind(root.firstname).first((path, value) -> path.containsIgnoreCase(value)); + } } diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/tests/mongodb/MongoWebTests.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/tests/mongodb/MongoWebTests.java index fc9d30494..8f51c3adb 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/tests/mongodb/MongoWebTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/tests/mongodb/MongoWebTests.java @@ -22,9 +22,12 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.math.BigDecimal; +import java.net.URI; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; import org.assertj.core.api.Condition; import org.junit.After; @@ -38,10 +41,14 @@ import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.TemplateVariable; +import org.springframework.hateoas.TemplateVariable.VariableType; +import org.springframework.hateoas.client.LinkDiscoverer; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import com.fasterxml.jackson.annotation.JsonInclude.Include; @@ -400,4 +407,36 @@ public class MongoWebTests extends CommonWebTests { mvc.perform(get(mapLink.expand().getHref()).accept(TEXT_URI_LIST)) // .andExpect(status().isUnsupportedMediaType()); } + + @Test // DATAREST-762 + public void paginatedLinksContainQuerydslPropertyReferences() throws Exception { + + Map parameters = new HashMap<>(); + parameters.put("page", "0"); + parameters.put("size", "1"); + parameters.put("firstname", "a"); + + Link receipts = client.discoverUnique("users"); + URI firstnameLikeA = receipts.getTemplate() // + .with(new TemplateVariable("firstname", VariableType.REQUEST_PARAM)) // + .expand(parameters); + + MockHttpServletResponse response = mvc// + .perform(get(firstnameLikeA)) // + .andReturn() // + .getResponse(); + + LinkDiscoverer discoverer = client.getDiscoverer(response); + String content = response.getContentAsString(); + + Stream.of(IanaLinkRelations.FIRST, IanaLinkRelations.NEXT, IanaLinkRelations.LAST) // + .forEach(it -> { + + Link firstLink = discoverer.findRequiredLinkWithRel(it, content); + UriComponents components = UriComponentsBuilder.fromUriString(firstLink.getHref()).build(); + + assertThat(components.getQueryParams().containsKey("firstname")); + }); + + } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java index 56e7d1edc..727924de5 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryEntityController.java @@ -203,8 +203,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem : invoker.invokeFindAll(sort); ResourceMetadata metadata = resourceInformation.getResourceMetadata(); - Optional baseLink = Optional.of(entityLinks.linkToPagedResource(resourceInformation.getDomainType(), - pageable.isDefault() ? null : pageable.getPageable())); + Optional baseLink = Optional.of(getDefaultSelfLink()); return toCollectionModel(results, assembler, metadata.getDomainType(), baseLink) .add(getCollectionResourceLinks(resourceInformation, pageable));