From 482c78c925c802b2166fed2464dea1e7228f52c9 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 5 Jan 2016 12:33:47 +0100 Subject: [PATCH] DATAREST-724 - Fixed invocation of DELETE on item resource with entity lookup present. Tweaked the RepositoryEntityController to lookup the identifier of the entity to be deleted from the entity obtained rather than forwarding the given id directly. This makes sure we use the real entity identifier on calls to delete in case the one to be used in URIs is customized via an EntityLookup. --- .../UnwrappingRepositoryInvokerFactory.java | 1 - .../webmvc/RepositoryEntityController.java | 6 +++-- ...itoryEntityControllerIntegrationTests.java | 26 ++++++++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) 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 dc313fba6..fbe5147d7 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 @@ -126,7 +126,6 @@ public class UnwrappingRepositoryInvokerFactory implements RepositoryInvokerFact * (non-Javadoc) * @see org.springframework.data.repository.support.RepositoryInvoker#invokeFindOne(java.io.Serializable) */ - public T invokeFindOne(Serializable id) { return postProcess(lookup != null ? lookup.lookupEntity(id) : delegate.invokeFindOne(id)); } 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 e0e839cb0..1f1a5d50b 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 @@ -462,10 +462,12 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem throw new ResourceNotFoundException(); } - eTag.verify(resourceInformation.getPersistentEntity(), domainObj); + PersistentEntity entity = resourceInformation.getPersistentEntity(); + + eTag.verify(entity, domainObj); publisher.publishEvent(new BeforeDeleteEvent(domainObj)); - invoker.invokeDelete(id); + invoker.invokeDelete((Serializable) entity.getIdentifierAccessor(domainObj).getIdentifier()); publisher.publishEvent(new AfterDeleteEvent(domainObj)); return new ResponseEntity(HttpStatus.NO_CONTENT); diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java index f04ec776d..0f2ba0f73 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryEntityControllerIntegrationTests.java @@ -17,16 +17,19 @@ package org.springframework.data.rest.webmvc; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import static org.springframework.data.rest.webmvc.TestMvcClient.*; import static org.springframework.http.HttpMethod.*; import java.util.List; +import org.hamcrest.Matchers; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; +import org.springframework.data.repository.support.RepositoryInvoker; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.data.rest.webmvc.jpa.Address; import org.springframework.data.rest.webmvc.jpa.AddressRepository; @@ -99,7 +102,7 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll ResponseEntity entity = controller.putItemResource(information, persistentEntityResource, 1L, assembler, ETag.NO_ETAG, MediaType.APPLICATION_JSON_VALUE); - assertThat(entity.getHeaders().getLocation().toString(), not(endsWith("{?projection}"))); + assertThat(entity.getHeaders().getLocation().toString(), not(Matchers.endsWith("{?projection}"))); } /** @@ -274,5 +277,26 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll assertThat(entity.getHeaders().getETag(), is(notNullValue())); } + /** + * @see DATAREST-724 + */ + @Test + public void deletesEntityWithCustomLookupCorrectly() throws Exception { + + Address address = repository.save(new Address()); + assertThat(repository.findOne(address.id), is(notNullValue())); + + RootResourceInformation resourceInformation = getResourceInformation(Address.class); + RepositoryInvoker invoker = spy(resourceInformation.getInvoker()); + doReturn(address).when(invoker).invokeFindOne("foo"); + + RootResourceInformation informationSpy = Mockito.spy(resourceInformation); + doReturn(invoker).when(informationSpy).getInvoker(); + + controller.deleteItemResource(informationSpy, "foo", ETag.from("0")); + + assertThat(repository.findOne(address.id), is(nullValue())); + } + interface AddressProjection {} }