From 77cf175b26fbae0a97dfde7cdcdbb50d27b70c79 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 6 May 2014 12:10:55 +0200 Subject: [PATCH] DATAREST-301 - Fixed location header creation for self links containing URI templates. We now consistently expand the self links created before adding them as location header to make sure we can create a URI instance successfully. --- .../webmvc/RepositoryEntityController.java | 20 ++++++++++++--- ...itoryEntityControllerIntegrationTests.java | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) 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 c63f85b29..035d16363 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 @@ -19,7 +19,6 @@ import static org.springframework.data.rest.core.support.DomainObjectMerger.Null import static org.springframework.http.HttpMethod.*; import java.io.Serializable; -import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -53,6 +52,7 @@ import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.Resource; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.Resources; +import org.springframework.hateoas.UriTemplate; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -318,7 +318,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem HttpHeaders headers = new HttpHeaders(); if (PUT.equals(httpMethod)) { - headers.setLocation(URI.create(perAssembler.getSelfLinkFor(obj).getHref())); + addLocationHeader(headers, perAssembler, obj); } if (config.isReturnBodyOnUpdate()) { @@ -342,10 +342,24 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem publisher.publishEvent(new AfterCreateEvent(savedObject)); HttpHeaders headers = new HttpHeaders(); - headers.setLocation(URI.create(perAssembler.getSelfLinkFor(savedObject).getHref())); + addLocationHeader(headers, perAssembler, savedObject); PersistentEntityResource resource = config.isReturnBodyOnCreate() ? perAssembler.toResource(savedObject) : null; return ControllerUtils.toResponseEntity(HttpStatus.CREATED, headers, resource); } + + /** + * Sets the location header pointing to the resource representing the given instance. Will make sure we properly + * expand the URI template potentially created as self link. + * + * @param headers must not be {@literal null}. + * @param assembler must not be {@literal null}. + * @param source must not be {@literal null}. + */ + private void addLocationHeader(HttpHeaders headers, PersistentEntityResourceAssembler assembler, Object source) { + + String selfLink = assembler.getSelfLinkFor(source).getHref(); + headers.setLocation(new UriTemplate(selfLink).expand()); + } } 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 32aeb7c73..ed5904898 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 @@ -15,11 +15,19 @@ */ package org.springframework.data.rest.webmvc; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.support.Repositories; +import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.data.rest.webmvc.jpa.Address; import org.springframework.data.rest.webmvc.jpa.AddressRepository; import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig; +import org.springframework.data.rest.webmvc.jpa.Order; +import org.springframework.data.rest.webmvc.jpa.Person; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.HttpRequestMethodNotSupportedException; @@ -35,6 +43,8 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll @Autowired RepositoryEntityController controller; @Autowired AddressRepository repository; + @Autowired RepositoryRestConfiguration configuration; + @Autowired Repositories repositories; /** * @see DATAREST-217 @@ -58,4 +68,19 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll controller.postEntity(request, null); } + + /** + * @see DATAREST-301 + */ + @Test + public void setsExpandedSelfUriInLocationHeader() throws Exception { + + RootResourceInformation information = getResourceInformation(Order.class); + PersistentEntityResource persistentEntityResource = new PersistentEntityResource( + repositories.getPersistentEntity(Order.class), new Order(new Person())); + + ResponseEntity entity = controller.putEntity(information, persistentEntityResource, 1L); + + assertThat(entity.getHeaders().getLocation().toString(), not(endsWith("{?projection}"))); + } }