From f906695e7a723024bc65b98db914cfefb7c27149 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 3 May 2017 17:22:54 +0200 Subject: [PATCH] DATAREST-1064 - Adapt to API changes in repository interfaces. Additional cleanups in QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver to make sure a QuerydslRepositoryInvokerAdapter is only applied if the QuerydslPredicateBuilder actually exposes a predicate. Extracted a couple of methods to make sure the mapping pipeline reads nicely. --- .../data/rest/core/UriToEntityConverter.java | 2 +- .../config/EntityLookupConfiguration.java | 48 ++++++++----------- .../core/config/EntityLookupRegistrar.java | 14 +++--- .../data/rest/core/support/EntityLookup.java | 5 +- .../UnwrappingRepositoryInvokerFactory.java | 13 ++--- .../core/UriToEntityConverterUnitTests.java | 2 +- .../rest/core/domain/OrderRepository.java | 6 +-- ...dMethodsSupportedHttpMethodsUnitTests.java | 2 +- ...pingRepositoryInvokerFactoryUnitTests.java | 2 +- .../data/rest/tests/CommonWebTests.java | 3 +- ...itoryEntityControllerIntegrationTests.java | 6 +-- .../rest/webmvc/jpa/TestDataPopulator.java | 4 +- ...ackson2DatatypeHelperIntegrationTests.java | 2 +- .../rest/tests/mongodb/ProfileRepository.java | 2 +- .../rest/tests/mongodb/MongoWebTests.java | 8 ++-- ...andlerMethodArgumentResolverUnitTests.java | 8 ++-- .../PreAuthorizedOrderRepository.java | 4 +- .../security/SecuredPersonRepository.java | 4 +- .../data/rest/webmvc/solr/SolrWebTests.java | 2 +- .../webmvc/RepositoryEntityController.java | 6 +-- ...RepositoryPropertyReferenceController.java | 4 +- .../alps/AlpsJsonHttpMessageConverter.java | 9 ++++ ...ResourceHandlerMethodArgumentResolver.java | 2 +- ...ormationHandlerMethodArgumentResolver.java | 27 +++++++---- .../json/PersistentEntityJackson2Module.java | 2 +- ...yPropertyReferenceControllerUnitTests.java | 6 +-- 26 files changed, 104 insertions(+), 89 deletions(-) diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/UriToEntityConverter.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/UriToEntityConverter.java index 0c50e0415..946821153 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/UriToEntityConverter.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/UriToEntityConverter.java @@ -123,6 +123,6 @@ public class UriToEntityConverter implements ConditionalGenericConverter { "Cannot resolve URI " + uri + ". Is it local or remote? Only local URIs are resolvable.")); } - return invokerFactory.getInvokerFor(targetType.getType()).invokeFindOne(parts[parts.length - 1]).orElse(null); + return invokerFactory.getInvokerFor(targetType.getType()).invokeFindById(parts[parts.length - 1]).orElse(null); } } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java index fb8a02e4d..8ef8e06ee 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupConfiguration.java @@ -19,7 +19,6 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Value; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -31,6 +30,7 @@ import org.springframework.data.repository.core.support.AbstractRepositoryMetada import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup; import org.springframework.data.rest.core.support.EntityLookup; +import org.springframework.data.util.StreamUtils; import org.springframework.util.Assert; /** @@ -42,16 +42,16 @@ import org.springframework.util.Assert; */ class EntityLookupConfiguration implements EntityLookupRegistrar { - private final List>> lookupInformation = new ArrayList>>(); - private final List> lookupTypes = new ArrayList>(); + private final List>> lookupInformation = new ArrayList<>(); + private final List> lookupTypes = new ArrayList<>(); /* * (non-Javadoc) * @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forRepository(java.lang.Class, org.springframework.core.convert.converter.Converter, org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup) */ @Override - public > EntityLookupRegistrar forRepository( - Class repositoryType, Converter converter, Lookup lookup) { + public > EntityLookupRegistrar forRepository(Class repositoryType, + Converter converter, Lookup lookup) { new MappingBuilder(repositoryType).withIdMapping(converter).withLookup(lookup); return this; @@ -62,8 +62,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forValueRepository(java.lang.Class) */ @Override - public > IdMappingRegistrar forLookupRepository( - Class type) { + public > IdMappingRegistrar forLookupRepository(Class type) { this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType()); return forRepository(type); } @@ -73,8 +72,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forRepository(java.lang.Class) */ @Override - public > IdMappingRegistrar forRepository( - Class type) { + public > IdMappingRegistrar forRepository(Class type) { return new MappingBuilder(type); } @@ -83,8 +81,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.config.EntityLookupRegistrar#forValueRepository(java.lang.Class, org.springframework.core.convert.converter.Converter, org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup) */ @Override - public > EntityLookupRegistrar forValueRepository( - Class type, Converter identifierMapping, Lookup lookup) { + public > EntityLookupRegistrar forValueRepository(Class type, + Converter identifierMapping, Lookup lookup) { this.lookupTypes.add(AbstractRepositoryMetadata.getMetadata(type).getDomainType()); return forRepository(type, identifierMapping, lookup); @@ -96,7 +94,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @author Oliver Gierke */ @RequiredArgsConstructor - private class MappingBuilder> + private class MappingBuilder> implements LookupRegistrar, IdMappingRegistrar { private @NonNull final Class repositoryType; @@ -125,8 +123,8 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { @SuppressWarnings("unchecked") public EntityLookupRegistrar withLookup(Lookup lookup) { - EntityLookupConfiguration.this.lookupInformation.add( - (LookupInformation>) new LookupInformation( + EntityLookupConfiguration.this.lookupInformation + .add((LookupInformation>) new LookupInformation( repositoryType, idMapping, lookup)); return EntityLookupConfiguration.this; @@ -137,7 +135,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.config.EntityLookupRegistrar.IdMappingRegistrar#withIdMapping(org.springframework.core.convert.converter.Converter) */ @Override - public LookupRegistrar withIdMapping(Converter idMapping) { + public LookupRegistrar withIdMapping(Converter idMapping) { return new MappingBuilder(repositoryType, idMapping); } } @@ -152,13 +150,9 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { Assert.notNull(repositories, "Repositories must not be null!"); - List> lookups = new ArrayList>(lookupInformation.size()); - - for (LookupInformation> information : lookupInformation) { - lookups.add(new RepositoriesEntityLookup(repositories, information)); - } - - return lookups; + return lookupInformation.stream()// + .map(it -> new RepositoriesEntityLookup<>(repositories, it))// + .collect(StreamUtils.toUnmodifiableList()); } public boolean isLookupType(Class type) { @@ -172,7 +166,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { */ private static class RepositoriesEntityLookup implements EntityLookup { - private final LookupInformation> lookupInfo; + private final LookupInformation> lookupInfo; private final Repository repository; private final Class domainType; @@ -184,7 +178,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { */ @SuppressWarnings("unchecked") public RepositoriesEntityLookup(Repositories repositories, - LookupInformation> lookupInformation) { + LookupInformation> lookupInformation) { Assert.notNull(repositories, "Repositories must not be null!"); Assert.notNull(lookupInformation, "LookupInformation must not be null!"); @@ -205,7 +199,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.support.EntityLookup#getResourceIdentifier(java.lang.Object) */ @Override - public Serializable getResourceIdentifier(T entity) { + public Object getResourceIdentifier(T entity) { return lookupInfo.getIdentifierMapping().convert(entity); } @@ -214,7 +208,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { * @see org.springframework.data.rest.core.support.EntityLookup#lookupEntity(java.io.Serializable) */ @Override - public Optional lookupEntity(Serializable id) { + public Optional lookupEntity(Object id) { return Optional.ofNullable(lookupInfo.getLookup().lookup(repository, id)); } @@ -229,7 +223,7 @@ class EntityLookupConfiguration implements EntityLookupRegistrar { } @Value - private static class LookupInformation> { + private static class LookupInformation> { private final Class repositoryType; private final Converter identifierMapping; diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupRegistrar.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupRegistrar.java index 8689a5aec..6563dbb59 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupRegistrar.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/EntityLookupRegistrar.java @@ -15,8 +15,6 @@ */ package org.springframework.data.rest.core.config; -import java.io.Serializable; - import org.springframework.core.convert.converter.Converter; import org.springframework.data.repository.Repository; import org.springframework.data.rest.core.config.EntityLookupRegistrar.LookupRegistrar.Lookup; @@ -36,7 +34,7 @@ public interface EntityLookupRegistrar { * @param type must not be {@literal null}. * @return */ - > IdMappingRegistrar forRepository(Class type); + > IdMappingRegistrar forRepository(Class type); /** * Starts building a custom {@link EntityLookup} for the given repository type and registers the domain type of the @@ -45,7 +43,7 @@ public interface EntityLookupRegistrar { * @param type must not be {@literal null}. * @return */ - > IdMappingRegistrar forLookupRepository(Class type); + > IdMappingRegistrar forLookupRepository(Class type); interface IdMappingRegistrar> { @@ -55,7 +53,7 @@ public interface EntityLookupRegistrar { * @param mapping must not be {@literal null}. * @return */ - LookupRegistrar withIdMapping(Converter mapping); + LookupRegistrar withIdMapping(Converter mapping); } /** @@ -65,7 +63,7 @@ public interface EntityLookupRegistrar { * @param identifierMapping must not be {@literal null}. * @param lookup must not be {@literal null}. */ - > EntityLookupRegistrar forRepository(Class type, + > EntityLookupRegistrar forRepository(Class type, Converter identifierMapping, Lookup lookup); /** @@ -76,10 +74,10 @@ public interface EntityLookupRegistrar { * @param identifierMapping must not be {@literal null}. * @param lookup must not be {@literal null}. */ - > EntityLookupRegistrar forValueRepository(Class type, + > EntityLookupRegistrar forValueRepository(Class type, Converter identifierMapping, Lookup lookup); - interface LookupRegistrar> { + interface LookupRegistrar> { /** * Registers the given {@link Lookup} to obtain entity instances. diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/EntityLookup.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/EntityLookup.java index 808bfc785..3a2b03282 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/EntityLookup.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/EntityLookup.java @@ -15,7 +15,6 @@ */ package org.springframework.data.rest.core.support; -import java.io.Serializable; import java.util.Optional; import org.springframework.plugin.core.Plugin; @@ -42,7 +41,7 @@ public interface EntityLookup extends Plugin> { * @param entity will never be {@literal null}. * @return must not be {@literal null}. */ - Serializable getResourceIdentifier(T entity); + Object getResourceIdentifier(T entity); /** * Returns the entity instance to be used if an entity with the given identifier value is requested. Implementations @@ -55,5 +54,5 @@ public interface EntityLookup extends Plugin> { * @param id will never be {@literal null}. * @return can be {@literal null}. */ - Optional lookupEntity(Serializable id); + Optional lookupEntity(Object id); } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java index bb6f2dc9e..26b691760 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactory.java @@ -85,12 +85,13 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact * (non-Javadoc) * @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindOne(java.io.Serializable) */ + @Override @SuppressWarnings("unchecked") - public Optional invokeFindOne(Serializable id) { + public Optional invokeFindById(Object id) { return (Optional) lookup// .map(it -> it.lookupEntity(id).orElse(Optional.empty()))// - .orElseGet(() -> delegate.invokeFindOne(id)); + .orElseGet(() -> delegate.invokeFindById(id)); } /* @@ -139,13 +140,13 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact return delegate.hasSaveMethod(); } - /* + /* * (non-Javadoc) - * @see org.springframework.data.repository.support.RepositoryInvoker#invokeDelete(java.io.Serializable) + * @see org.springframework.data.repository.support.RepositoryInvoker#invokeDeleteById(java.lang.Object) */ @Override - public void invokeDelete(Serializable id) { - delegate.invokeDelete(id); + public void invokeDeleteById(Object id) { + delegate.invokeDeleteById(id); } /* diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/UriToEntityConverterUnitTests.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/UriToEntityConverterUnitTests.java index 88d94d16f..b6a2ad6ea 100755 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/UriToEntityConverterUnitTests.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/UriToEntityConverterUnitTests.java @@ -105,7 +105,7 @@ public class UriToEntityConverterUnitTests { Entity reference = new Entity(); RepositoryInvoker invoker = mock(RepositoryInvoker.class); - doReturn(Optional.of(reference)).when(invoker).invokeFindOne("1"); + doReturn(Optional.of(reference)).when(invoker).invokeFindById("1"); doReturn(invoker).when(invokerFactory).getInvokerFor(ENTITY_TYPE.getType()); assertThat(converter.convert(URI.create("/foo/bar/1"), URI_TYPE, ENTITY_TYPE)).isEqualTo((Object) reference); diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/domain/OrderRepository.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/domain/OrderRepository.java index b2080f83b..be28f896e 100644 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/domain/OrderRepository.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/domain/OrderRepository.java @@ -32,10 +32,10 @@ public interface OrderRepository extends CrudRepository { @Override S save(S entity); - /* + /* * (non-Javadoc) - * @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable) + * @see org.springframework.data.repository.CrudRepository#findById(java.lang.Object) */ @Override - Optional findOne(UUID id); + Optional findById(UUID id); } diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/mapping/CrudMethodsSupportedHttpMethodsUnitTests.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/mapping/CrudMethodsSupportedHttpMethodsUnitTests.java index d3d957c61..483b9de1f 100755 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/mapping/CrudMethodsSupportedHttpMethodsUnitTests.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/mapping/CrudMethodsSupportedHttpMethodsUnitTests.java @@ -152,7 +152,7 @@ public class CrudMethodsSupportedHttpMethodsUnitTests { @Override @RestResource(exported = false) - Optional findOne(Long id); + Optional findById(Long id); } interface NoFindOne extends Repository { diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactoryUnitTests.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactoryUnitTests.java index ab8c1226e..622cf06cd 100755 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactoryUnitTests.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/UnwrappingRepositoryInvokerFactoryUnitTests.java @@ -86,7 +86,7 @@ public class UnwrappingRepositoryInvokerFactoryUnitTests { when(delegate.getInvokerFor(Profile.class)).thenReturn(invoker); factory = new UnwrappingRepositoryInvokerFactory(delegate, Arrays.asList(lookup)); - factory.getInvokerFor(Profile.class).invokeFindOne(1L); + factory.getInvokerFor(Profile.class).invokeFindById(1L); verify(lookup, times(1)).lookupEntity(eq(1L)); } diff --git a/spring-data-rest-tests/spring-data-rest-tests-core/src/test/java/org/springframework/data/rest/tests/CommonWebTests.java b/spring-data-rest-tests/spring-data-rest-tests-core/src/test/java/org/springframework/data/rest/tests/CommonWebTests.java index f3404b16c..2905d7f19 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-core/src/test/java/org/springframework/data/rest/tests/CommonWebTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-core/src/test/java/org/springframework/data/rest/tests/CommonWebTests.java @@ -37,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import com.jayway.jsonpath.JsonPath; @@ -62,7 +63,7 @@ public abstract class CommonWebTests extends AbstractWebIntegrationTests { ResultActions actions = mvc.perform(get("/").accept(TestMvcClient.DEFAULT_MEDIA_TYPE)).andExpect(status().isOk()); for (String rel : expectedRootLinkRels()) { - actions.andExpect(client.hasLinkWithRel(rel)); + actions.andDo(MockMvcResultHandlers.print()).andExpect(client.hasLinkWithRel(rel)); } } diff --git a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java index 49feed000..e4ca20906 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java @@ -237,18 +237,18 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll public void deletesEntityWithCustomLookupCorrectly() throws Exception { Address address = repository.save(new Address()); - assertThat(repository.findOne(address.id)).isNotNull(); + assertThat(repository.findById(address.id)).isNotNull(); RootResourceInformation resourceInformation = getResourceInformation(Address.class); RepositoryInvoker invoker = spy(resourceInformation.getInvoker()); - doReturn(Optional.of(address)).when(invoker).invokeFindOne("foo"); + doReturn(Optional.of(address)).when(invoker).invokeFindById("foo"); RootResourceInformation informationSpy = Mockito.spy(resourceInformation); doReturn(invoker).when(informationSpy).getInvoker(); controller.deleteItemResource(informationSpy, "foo", ETag.from("0")); - assertThat(repository.findOne(address.id)).isEmpty(); + assertThat(repository.findById(address.id)).isEmpty(); } interface AddressProjection {} diff --git a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java index 1e16f7345..0dfbe7ff6 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java +++ b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java @@ -53,7 +53,7 @@ public class TestDataPopulator { Author john = new Author("John"); Author thomas = new Author("Thomas"); - Iterable authors = this.authors.save(Arrays.asList(ollie, mark, michael, david, john, thomas)); + Iterable authors = this.authors.saveAll(Arrays.asList(ollie, mark, michael, david, john, thomas)); books.save(new Book("1449323952", "Spring Data", 1000, authors, new Offer(21.21, "EUR"))); books.save(new Book("1449323953", "Spring Data (Second Edition)", 2000, authors, new Offer(30.99, "EUR"))); @@ -79,6 +79,6 @@ public class TestDataPopulator { jane.addSibling(john); jane.setFather(billyBob); - people.save(Arrays.asList(john, jane)); + people.saveAll(Arrays.asList(john, jane)); } } diff --git a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/json/Jackson2DatatypeHelperIntegrationTests.java b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/json/Jackson2DatatypeHelperIntegrationTests.java index c6f362457..66f2bb1ec 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/json/Jackson2DatatypeHelperIntegrationTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/json/Jackson2DatatypeHelperIntegrationTests.java @@ -73,7 +73,7 @@ public class Jackson2DatatypeHelperIntegrationTests { PersistentEntity entity = entities.getRequiredPersistentEntity(Order.class); PersistentProperty property = entity.getRequiredPersistentProperty("creator"); - PersistentPropertyAccessor accessor = entity.getPropertyAccessor(orders.findOne(this.order.getId()).orElse(null)); + PersistentPropertyAccessor accessor = entity.getPropertyAccessor(orders.findById(this.order.getId()).orElse(null)); assertThat(objectMapper.writeValueAsString(accessor.getProperty(property))).isNotEqualTo("null"); } diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/ProfileRepository.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/ProfileRepository.java index a259affb9..9e986ce44 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/ProfileRepository.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/ProfileRepository.java @@ -33,5 +33,5 @@ public interface ProfileRepository extends PagingAndSortingRepository findById(@Param("id") String id); + Optional findProfileById(@Param("id") String id); } 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 6c511346b..ac6b5811d 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 @@ -71,7 +71,7 @@ public class MongoWebTests extends CommonWebTests { linkedIn.setPerson(1L); linkedIn.setType("LinkedIn"); - repository.save(Arrays.asList(twitter, linkedIn)); + repository.saveAll(Arrays.asList(twitter, linkedIn)); Address address = new Address(); address.street = "ETagDoesntMatchExceptionUnitTests"; @@ -288,7 +288,7 @@ public class MongoWebTests extends CommonWebTests { Profile profile = repository.findAll().iterator().next(); - Link link = client.discoverUnique("profiles", "search", "findById"); + Link link = client.discoverUnique("profiles", "search", "findProfileById"); mvc.perform(get(link.expand(profile.getId()).getHref())).// andExpect(status().isOk()); @@ -297,7 +297,7 @@ public class MongoWebTests extends CommonWebTests { @Test // DATAREST-517 public void returnsNotFoundIfQueryExecutionDoesNotReturnResult() throws Exception { - Link link = client.discoverUnique("profiles", "search", "findById"); + Link link = client.discoverUnique("profiles", "search", "findProfileById"); mvc.perform(get(link.expand("").getHref())).// andExpect(status().isNotFound()); @@ -319,7 +319,7 @@ public class MongoWebTests extends CommonWebTests { @Test // DATAREST-835 public void exposesETagHeaderForSearchResourceYieldingItemResource() throws Exception { - Link link = client.discoverUnique("profiles", "search", "findById"); + Link link = client.discoverUnique("profiles", "search", "findProfileById"); Profile profile = repository.findAll().iterator().next(); diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUnitTests.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUnitTests.java index d99704042..0731f7e66 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUnitTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.rest.webmvc.config; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Collections; @@ -29,7 +30,6 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.core.MethodParameter; -import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.querydsl.QuerydslRepositoryInvokerAdapter; import org.springframework.data.querydsl.SimpleEntityPathResolver; @@ -47,6 +47,8 @@ import org.springframework.data.rest.tests.mongodb.ReceiptRepository; import org.springframework.data.rest.tests.mongodb.User; import org.springframework.test.util.ReflectionTestUtils; +import com.querydsl.core.types.Predicate; + /** * Unit tests for {@link QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver}. * @@ -60,6 +62,7 @@ public class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUn @Mock Repositories repositories; @Mock RepositoryInvokerFactory invokerFactory; @Mock ResourceMetadataHandlerMethodArgumentResolver resourceMetadataResolver; + @Mock QuerydslPredicateBuilder builder; @Mock RepositoryInvoker invoker; @Mock MethodParameter parameter; @@ -71,12 +74,11 @@ public class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolverUn QuerydslBindingsFactory factory = new QuerydslBindingsFactory(SimpleEntityPathResolver.INSTANCE); ReflectionTestUtils.setField(factory, "repositories", Optional.of(repositories)); - QuerydslPredicateBuilder builder = new QuerydslPredicateBuilder(new DefaultConversionService(), - factory.getEntityPathResolver()); this.resolver = new QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver(repositories, invokerFactory, resourceMetadataResolver, builder, factory); + when(builder.getPredicate(any(), any(), any())).thenReturn(mock(Predicate.class)); when(parameter.hasParameterAnnotation(QuerydslPredicate.class)).thenReturn(true); } diff --git a/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java b/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java index df72862a3..7f1a10237 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java +++ b/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/PreAuthorizedOrderRepository.java @@ -30,7 +30,7 @@ public interface PreAuthorizedOrderRepository extends CrudRepository @Override - void delete(UUID aLong); + void deleteById(UUID aLong); @PreAuthorize("hasRole('ROLE_ADMIN')") @Override @@ -38,7 +38,7 @@ public interface PreAuthorizedOrderRepository extends CrudRepository orders); + void deleteAll(Iterable orders); @PreAuthorize("hasRole('ROLE_ADMIN')") @Override diff --git a/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecuredPersonRepository.java b/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecuredPersonRepository.java index 9169351eb..6a3bfe0ff 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecuredPersonRepository.java +++ b/spring-data-rest-tests/spring-data-rest-tests-security/src/test/java/org/springframework/data/rest/tests/security/SecuredPersonRepository.java @@ -28,7 +28,7 @@ public interface SecuredPersonRepository extends CrudRepository { @Secured("ROLE_ADMIN") // <2> @Override - void delete(UUID aLong); + void deleteById(UUID aLong); @Secured("ROLE_ADMIN") @Override @@ -36,7 +36,7 @@ public interface SecuredPersonRepository extends CrudRepository { @Secured("ROLE_ADMIN") @Override - void delete(Iterable persons); + void deleteAll(Iterable persons); @Secured("ROLE_ADMIN") @Override diff --git a/spring-data-rest-tests/spring-data-rest-tests-solr/src/test/java/org/springframework/data/rest/webmvc/solr/SolrWebTests.java b/spring-data-rest-tests/spring-data-rest-tests-solr/src/test/java/org/springframework/data/rest/webmvc/solr/SolrWebTests.java index 5c70ed3ec..a9a822117 100755 --- a/spring-data-rest-tests/spring-data-rest-tests-solr/src/test/java/org/springframework/data/rest/webmvc/solr/SolrWebTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-solr/src/test/java/org/springframework/data/rest/webmvc/solr/SolrWebTests.java @@ -69,7 +69,7 @@ public class SolrWebTests extends CommonWebTests { public void setUp() { super.setUp(); - repo.save(Arrays.asList(PLAYSTATION, GAMEBOY, AMIGA500)); + repo.saveAll(Arrays.asList(PLAYSTATION, GAMEBOY, AMIGA500)); } @After 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 761223533..1c62ec8d9 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 @@ -416,7 +416,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem resourceInformation.verifySupportedMethod(HttpMethod.DELETE, ResourceType.ITEM); RepositoryInvoker invoker = resourceInformation.getInvoker(); - Optional domainObj = invoker.invokeFindOne(id); + Optional domainObj = invoker.invokeFindById(id); return domainObj.map(it -> { @@ -425,7 +425,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem eTag.verify(entity, it); publisher.publishEvent(new BeforeDeleteEvent(it)); - invoker.invokeDelete((Serializable) entity.getIdentifierAccessor(it).getIdentifier().orElse(null)); + invoker.invokeDeleteById((Serializable) entity.getIdentifierAccessor(it).getIdentifier().orElse(null)); publisher.publishEvent(new AfterDeleteEvent(it)); return new ResponseEntity(HttpStatus.NO_CONTENT); @@ -513,6 +513,6 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem resourceInformation.verifySupportedMethod(HttpMethod.GET, ResourceType.ITEM); - return resourceInformation.getInvoker().invokeFindOne(id); + return resourceInformation.getInvoker().invokeFindById(id); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java index e2dbefcfb..26d46c7a6 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java @@ -397,7 +397,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(type); - return invoker.invokeFindOne(id); + return invoker.invokeFindById(id); } private Optional doWithReferencedProperty(RootResourceInformation resourceInformation, @@ -415,7 +415,7 @@ class RepositoryPropertyReferenceController extends AbstractRepositoryRestContro resourceInformation.verifySupportedMethod(method, property); RepositoryInvoker invoker = resourceInformation.getInvoker(); - Optional domainObj = invoker.invokeFindOne(id); + Optional domainObj = invoker.invokeFindById(id); domainObj.orElseThrow(() -> new ResourceNotFoundException()); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/AlpsJsonHttpMessageConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/AlpsJsonHttpMessageConverter.java index 590b4324c..e4afe016f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/AlpsJsonHttpMessageConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/alps/AlpsJsonHttpMessageConverter.java @@ -74,6 +74,15 @@ public class AlpsJsonHttpMessageConverter extends MappingJackson2HttpMessageConv && super.canWrite(clazz, mediaType); } + /* + * (non-Javadoc) + * @see org.springframework.http.converter.AbstractGenericHttpMessageConverter#canWrite(java.lang.reflect.Type, java.lang.Class, org.springframework.http.MediaType) + */ + @Override + public boolean canWrite(Type type, Class clazz, MediaType mediaType) { + return canWrite(clazz, mediaType); + } + /* * (non-Javadoc) * @see org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#canRead(java.lang.reflect.Type, java.lang.Class, org.springframework.http.MediaType) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java index 825703377..04615bc08 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceHandlerMethodArgumentResolver.java @@ -128,7 +128,7 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha Optional id = Optional .ofNullable(idResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory)); - Optional objectToUpdate = id.flatMap(it -> resourceInformation.getInvoker().invokeFindOne(it)); + Optional objectToUpdate = id.flatMap(it -> resourceInformation.getInvoker().invokeFindById(it)); Object obj = read(resourceInformation, incoming, converter, objectToUpdate); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java index 309d7e739..1fc24ce90 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java @@ -18,6 +18,7 @@ package org.springframework.data.rest.webmvc.config; import java.util.Arrays; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import org.springframework.core.MethodParameter; import org.springframework.data.querydsl.QuerydslPredicateExecutor; @@ -35,6 +36,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import com.mysema.commons.lang.Pair; import com.querydsl.core.types.Predicate; /** @@ -75,7 +77,6 @@ class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver * @see org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver#postProcess(org.springframework.data.repository.support.RepositoryInvoker, java.lang.Class, java.util.Map) */ @Override - @SuppressWarnings({ "unchecked" }) protected RepositoryInvoker postProcess(MethodParameter parameter, RepositoryInvoker invoker, Class domainType, Map parameters) { @@ -85,17 +86,27 @@ class QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver return repositories.getRepositoryFor(domainType)// .filter(it -> QuerydslPredicateExecutor.class.isInstance(it))// - .map(it -> { + .map(it -> QuerydslPredicateExecutor.class.cast(it))// + .flatMap(it -> getRepositoryAndPredicate(it, domainType, parameters))// + .map(it -> getQuerydslAdapter(invoker, it.getFirst(), it.getSecond()))// + .orElse(invoker); + } - ClassTypeInformation type = ClassTypeInformation.from(domainType); + private Optional, Predicate>> getRepositoryAndPredicate( + QuerydslPredicateExecutor repository, Class domainType, Map parameters) { - QuerydslBindings bindings = factory.createBindingsFor(type); - Predicate predicate = predicateBuilder.getPredicate(type, toMultiValueMap(parameters), bindings); + ClassTypeInformation type = ClassTypeInformation.from(domainType); - return (RepositoryInvoker) new QuerydslRepositoryInvokerAdapter(invoker, - (QuerydslPredicateExecutor) it, predicate); + QuerydslBindings bindings = factory.createBindingsFor(type); + Predicate predicate = predicateBuilder.getPredicate(type, toMultiValueMap(parameters), bindings); - }).orElse(invoker); + return Optional.ofNullable(predicate).map(it -> Pair.of(repository, it)); + } + + @SuppressWarnings("unchecked") + private static RepositoryInvoker getQuerydslAdapter(RepositoryInvoker invoker, + QuerydslPredicateExecutor repository, Predicate predicate) { + return new QuerydslRepositoryInvokerAdapter(invoker, (QuerydslPredicateExecutor) repository, predicate); } /** diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java index 6f5bd2a69..4e45349c0 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java @@ -762,7 +762,7 @@ public class PersistentEntityJackson2Module extends SimpleModule { */ @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - return invoker.invokeFindOne(p.getValueAsString()); + return invoker.invokeFindById(p.getValueAsString()); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceControllerUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceControllerUnitTests.java index 3c6b55293..cd15ff6ed 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceControllerUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceControllerUnitTests.java @@ -80,8 +80,8 @@ public class RepositoryPropertyReferenceControllerUnitTests { controller.setApplicationEventPublisher(publisher); doReturn(invoker).when(invokerFactory).getInvokerFor(Reference.class); - doReturn(Optional.of(new Sample())).when(invoker).invokeFindOne(4711); - doReturn(Optional.of(new Reference())).when(invoker).invokeFindOne("some-id"); + doReturn(Optional.of(new Sample())).when(invoker).invokeFindById(4711); + doReturn(Optional.of(new Reference())).when(invoker).invokeFindById("some-id"); doReturn(new Sample()).when(invoker).invokeSave(any(Object.class)); RootResourceInformation information = new RootResourceInformation(metadata, entity, invoker); @@ -90,7 +90,7 @@ public class RepositoryPropertyReferenceControllerUnitTests { controller.createPropertyReference(information, HttpMethod.POST, request, 4711, "references"); verify(invokerFactory).getInvokerFor(Reference.class); - verify(invoker).invokeFindOne("some-id"); + verify(invoker).invokeFindById("some-id"); } @RestResource