From ca3b3bb3548147fe75c03c25d480e1baa321cacc 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 | 26 +++++++++++++++++++ 2 files changed, 43 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 3d5d3eb42..35ab33eac 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; @@ -319,7 +319,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem HttpHeaders headers = new HttpHeaders(); if (PUT.equals(httpMethod)) { - headers.setLocation(URI.create(assembler.getSelfLinkFor(obj).getHref())); + addLocationHeader(headers, assembler, obj); } if (config.isReturnBodyOnUpdate()) { @@ -344,10 +344,24 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem publisher.publishEvent(new AfterCreateEvent(savedObject)); HttpHeaders headers = new HttpHeaders(); - headers.setLocation(URI.create(assembler.getSelfLinkFor(savedObject).expand().getHref())); + addLocationHeader(headers, assembler, savedObject); PersistentEntityResource resource = config.isReturnBodyOnCreate() ? assembler.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 07881494a..373ac67a7 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.mapping.context.PersistentEntities; +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,9 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll @Autowired RepositoryEntityController controller; @Autowired AddressRepository repository; + @Autowired RepositoryRestConfiguration configuration; + @Autowired PersistentEntityResourceAssembler assembler; + @Autowired PersistentEntities entities; /** * @see DATAREST-217 @@ -58,4 +69,19 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll controller.postCollectionResource(request, null, null); } + + /** + * @see DATAREST-301 + */ + @Test + public void setsExpandedSelfUriInLocationHeader() throws Exception { + + RootResourceInformation information = getResourceInformation(Order.class); + PersistentEntityResource persistentEntityResource = new PersistentEntityResource( + entities.getPersistentEntity(Order.class), new Order(new Person())); + + ResponseEntity entity = controller.putItemResource(information, persistentEntityResource, 1L, assembler); + + assertThat(entity.getHeaders().getLocation().toString(), not(endsWith("{?projection}"))); + } }