diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ResolvableResourceDescriptionSupport.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ResolvableResourceDescriptionSupport.java index bda50c0ca..ac6816757 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ResolvableResourceDescriptionSupport.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/ResolvableResourceDescriptionSupport.java @@ -15,8 +15,11 @@ */ package org.springframework.data.rest.core.mapping; +import org.springframework.context.MessageSourceResolvable; + /** - * + * Adapter class for the {@link MessageSourceResolvable} part of a {@link ResourceDescription}. + * * @author Oliver Gierke */ public abstract class ResolvableResourceDescriptionSupport implements ResourceDescription { @@ -29,7 +32,7 @@ public abstract class ResolvableResourceDescriptionSupport implements ResourceDe public String[] getCodes() { return new String[] { getMessage() }; } - + /* * (non-Javadoc) * @see org.springframework.context.MessageSourceResolvable#getArguments() @@ -38,7 +41,7 @@ public abstract class ResolvableResourceDescriptionSupport implements ResourceDe public Object[] getArguments() { return new Object[0]; } - + /* * (non-Javadoc) * @see org.springframework.context.MessageSourceResolvable#getDefaultMessage() diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java index c14c0a847..ae9236d45 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/mapping/TypeBasedCollectionResourceMapping.java @@ -106,7 +106,7 @@ class TypeBasedCollectionResourceMapping implements CollectionResourceMapping { */ @Override public String getItemResourceRel() { - return relProvider.getSingleResourceRelFor(type); + return relProvider.getItemResourceRelFor(type); } /* diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/RepositoryRelProvider.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/RepositoryRelProvider.java index 9376f92dd..9dd289667 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/RepositoryRelProvider.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/RepositoryRelProvider.java @@ -50,10 +50,10 @@ public class RepositoryRelProvider implements RelProvider { /* * (non-Javadoc) - * @see org.springframework.hateoas.RelProvider#getSingleResourceRelFor(java.lang.Class) + * @see org.springframework.hateoas.RelProvider#getItemResourceRelFor(java.lang.Class) */ @Override - public String getSingleResourceRelFor(Class type) { + public String getItemResourceRelFor(Class type) { return mappings.getMappingFor(type).getItemResourceRel(); } diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/SimpleRelProvider.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/SimpleRelProvider.java index 71136584f..4a8a72c08 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/SimpleRelProvider.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/support/SimpleRelProvider.java @@ -32,11 +32,13 @@ public class SimpleRelProvider implements RelProvider { return true; } - /* (non-Javadoc) - * @see org.springframework.hateoas.RelProvider#getSingleResourceRelFor(java.lang.Class) + /* + * (non-Javadoc) + * @see org.springframework.hateoas.RelProvider#getItemResourceRelFor(java.lang.Class) */ @Override - public String getSingleResourceRelFor(Class type) { + public String getItemResourceRelFor(Class type) { + String collectionRel = getCollectionResourceRelFor(type); return String.format("%s.%s", collectionRel, collectionRel); } diff --git a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTest.java b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTests.java similarity index 93% rename from spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTest.java rename to spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTests.java index e36b49519..8cebacd63 100644 --- a/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTest.java +++ b/spring-data-rest-core/src/test/java/org/springframework/data/rest/core/support/ResourceStringUtilsTests.java @@ -33,13 +33,13 @@ import static org.junit.runners.Parameterized.Parameters; * @author Florent Biville */ @RunWith(Parameterized.class) -public class ResourceStringUtilsTest { +public class ResourceStringUtilsTests { final String actual; final String expected; final boolean hasText; - public ResourceStringUtilsTest(String testDescription, String actual, String expected, boolean hasText) { + public ResourceStringUtilsTests(String testDescription, String actual, String expected, boolean hasText) { this.actual = actual; this.expected = expected; diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ControllerUtils.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ControllerUtils.java index d1c479ecc..7af93648a 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ControllerUtils.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ControllerUtils.java @@ -38,14 +38,15 @@ public class ControllerUtils { /** * Wrap a resource as a {@link ResourceEntity} and attach given headers and status. + * + * @param status * @param headers * @param resource - * @param status * @param * @return */ - public static ResponseEntity toResponseEntity(HttpHeaders headers, - R resource, HttpStatus status) { + public static ResponseEntity toResponseEntity(HttpStatus status, + HttpHeaders headers, R resource) { HttpHeaders hdrs = new HttpHeaders(); if (null != headers) { @@ -57,20 +58,22 @@ public class ControllerUtils { /** * Return an empty response that is only comprised of a status + * * @param status * @return */ public static ResponseEntity toEmptyResponse(HttpStatus status) { - return toResponseEntity(null, EMPTY_RESOURCES, status); + return toResponseEntity(status, null, EMPTY_RESOURCES); } /** * Return an empty response that is only comprised of headers and a status - * @param headers + * * @param status + * @param headers * @return */ - public static ResponseEntity toEmptyResponse(HttpHeaders headers, HttpStatus status) { - return toResponseEntity(headers, EMPTY_RESOURCES, status); + public static ResponseEntity toEmptyResponse(HttpStatus status, HttpHeaders headers) { + return toResponseEntity(status, headers, EMPTY_RESOURCES); } } 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 32387427d..96b73e0b8 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 @@ -176,7 +176,7 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem headers.setLocation(URI.create(selfLink.getHref())); PersistentEntityResource resource = config.isReturnBodyOnCreate() ? perAssembler.toResource(obj) : null; - return ControllerUtils.toResponseEntity(headers, resource, HttpStatus.CREATED); + return ControllerUtils.toResponseEntity(HttpStatus.CREATED, headers, resource); } /** @@ -238,9 +238,9 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem publisher.publishEvent(new AfterSaveEvent(obj)); if (config.isReturnBodyOnUpdate()) { - return ControllerUtils.toResponseEntity(null, perAssembler.toResource(obj), HttpStatus.OK); + return ControllerUtils.toResponseEntity(HttpStatus.OK, null, perAssembler.toResource(obj)); } else { - return ControllerUtils.toResponseEntity(null, null, HttpStatus.NO_CONTENT); + return ControllerUtils.toResponseEntity(HttpStatus.NO_CONTENT, null, null); } } 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 299a616e6..745b8291c 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 @@ -18,7 +18,6 @@ package org.springframework.data.rest.webmvc; import static org.springframework.data.rest.webmvc.ControllerUtils.*; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; -import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -30,6 +29,7 @@ import java.util.Map.Entry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.core.CollectionFactory; import org.springframework.core.convert.TypeDescriptor; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; @@ -60,7 +60,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.util.UriComponentsBuilder; /** * @author Jon Brisbin @@ -145,7 +145,7 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes }; ResourceSupport responseResource = doWithReferencedProperty(repoRequest, id, property, handler); - return ControllerUtils.toResponseEntity(headers, responseResource, HttpStatus.OK); + return ControllerUtils.toResponseEntity(HttpStatus.OK, headers, responseResource); } @RequestMapping(value = BASE_MAPPING, method = RequestMethod.DELETE) @@ -244,7 +244,7 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes }; ResourceSupport responseResource = doWithReferencedProperty(repoRequest, id, property, handler); - return ControllerUtils.toResponseEntity(headers, responseResource, HttpStatus.OK); + return ControllerUtils.toResponseEntity(HttpStatus.OK, headers, responseResource); } @RequestMapping(value = BASE_MAPPING, method = RequestMethod.GET, produces = { @@ -292,7 +292,7 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes links.add(linkBuilder.withRel(propertyMapping.getRel())); } - return ControllerUtils.toResponseEntity(null, new Resource(EMPTY_RESOURCE_LIST, links), HttpStatus.OK); + return ControllerUtils.toResponseEntity(HttpStatus.OK, null, new Resource(EMPTY_RESOURCE_LIST, links)); } @RequestMapping(value = BASE_MAPPING, // @@ -301,28 +301,28 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes @ResponseBody public ResponseEntity createPropertyReference(final RepositoryRestRequest repoRequest, final @RequestBody Resources incoming, @PathVariable String id, @PathVariable String property, - final HttpServletRequest request) - throws NoSuchMethodException { + final UriComponentsBuilder builder) throws NoSuchMethodException { final RepositoryInvoker invoker = repoRequest.getRepositoryInvoker(); if (!invoker.exposesSave()) { return new ResponseEntity>(HttpStatus.METHOD_NOT_ALLOWED); } + Function handler = new Function() { @Override public ResourceSupport apply(ReferencedProperty prop) { + Class propertyType = prop.property.getType(); + if (prop.property.isCollectionLike()) { - Collection coll; + Collection coll = CollectionFactory.createCollection(propertyType, 0); // Either load the exist collection to add to it (POST) if (HttpMethod.POST.equals(repoRequest.getRequestMethod())) { coll = (Collection) prop.propertyValue; - } else { // Or start from an empty collection to replace it (PUT) - coll = new ArrayList(); } // Add to the existing collection @@ -335,13 +335,11 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes } else if (prop.property.isMap()) { - Map m; + Map m = CollectionFactory.createMap(propertyType, 0); // Either load the exist collection to add to it (POST) if (HttpMethod.POST.equals(repoRequest.getRequestMethod())) { m = (Map) prop.propertyValue; - } else { // Or start from an empty collection to replace it (PUT) - m = new HashMap(); } // Add to the existing collection @@ -378,10 +376,10 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes doWithReferencedProperty(repoRequest, id, property, handler); - final HttpHeaders headers = new HttpHeaders(); - headers.set("Location", String.valueOf(request.getRequestURL())); + HttpHeaders headers = new HttpHeaders(); + headers.set("Location", builder.build().toUriString()); - return ControllerUtils.toEmptyResponse(headers, HttpStatus.CREATED); + return ControllerUtils.toEmptyResponse(HttpStatus.CREATED, headers); } @RequestMapping(value = BASE_MAPPING + "/{propertyId}", method = RequestMethod.DELETE) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/convert/UriListHttpMessageConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/convert/UriListHttpMessageConverter.java index 36272d535..c606b15f5 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/convert/UriListHttpMessageConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/convert/UriListHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,15 @@ */ package org.springframework.data.rest.webmvc.convert; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; -import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Scanner; +import org.springframework.core.convert.converter.Converter; import org.springframework.hateoas.Link; import org.springframework.hateoas.ResourceSupport; import org.springframework.hateoas.Resources; @@ -33,10 +33,15 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.StringUtils; /** + * {@link Converter} to render all {@link Link}s contained in a {@link ResourceSupport} as {@code text/uri-list} and + * parse a request of that media type back into a {@link ResourceSupport} instance. + * * @author Jon Brisbin * @author Greg Turnquist + * @author Oliver Gierke */ public class UriListHttpMessageConverter implements HttpMessageConverter { @@ -46,6 +51,10 @@ public class UriListHttpMessageConverter implements HttpMessageConverter clazz, MediaType mediaType) { if (null == mediaType) { @@ -54,37 +63,68 @@ public class UriListHttpMessageConverter implements HttpMessageConverter clazz, MediaType mediaType) { return canRead(clazz, mediaType); } + /* + * (non-Javadoc) + * @see org.springframework.http.converter.HttpMessageConverter#getSupportedMediaTypes() + */ @Override public List getSupportedMediaTypes() { return MEDIA_TYPES; } + /* + * (non-Javadoc) + * @see org.springframework.http.converter.HttpMessageConverter#read(java.lang.Class, org.springframework.http.HttpInputMessage) + */ @Override - public ResourceSupport read(Class clazz, HttpInputMessage inputMessage) throws IOException, - HttpMessageNotReadableException { + public ResourceSupport read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + List links = new ArrayList(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputMessage.getBody())); - String line; - while (null != (line = reader.readLine())) { - links.add(new Link(line)); + + Scanner scanner = new Scanner(inputMessage.getBody()); + + try { + + while (scanner.hasNextLine()) { + + String line = scanner.nextLine(); + if (StringUtils.hasText(line)) { + links.add(new Link(line)); + } + } + + } finally { + scanner.close(); } + return new Resources(Collections.emptyList(), links); } + /* + * (non-Javadoc) + * @see org.springframework.http.converter.HttpMessageConverter#write(java.lang.Object, org.springframework.http.MediaType, org.springframework.http.HttpOutputMessage) + */ @Override - public void write(ResourceSupport resource, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, - HttpMessageNotWritableException { + public void write(ResourceSupport resource, MediaType contentType, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputMessage.getBody())); + for (Link link : resource.getLinks()) { writer.write(link.getHref()); writer.newLine(); } + writer.flush(); } - } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java index 8173ae5cc..99756403b 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java @@ -138,12 +138,7 @@ public abstract class AbstractWebIntegrationTests { protected MockHttpServletResponse postAndGet(Link link, Object payload, MediaType mediaType) throws Exception { - String href; - if (link.isTemplated()) { - href = link.expand().getHref(); - } else { - href = link.getHref(); - } + String href = link.isTemplated() ? link.expand().getHref() : link.getHref(); MockHttpServletResponse response = mvc.perform(post(href).content(payload.toString()).contentType(mediaType)).// andExpect(status().isCreated()).// @@ -161,12 +156,7 @@ public abstract class AbstractWebIntegrationTests { protected MockHttpServletResponse putAndGet(Link link, Object payload, MediaType mediaType) throws Exception { - String href; - if (link.isTemplated()) { - href = link.expand().getHref(); - } else { - href = link.getHref(); - } + String href = link.isTemplated() ? link.expand().getHref() : link.getHref(); MockHttpServletResponse response = mvc.perform(put(href).content(payload.toString()).contentType(mediaType)).// andExpect(status().isCreated()).// @@ -184,12 +174,7 @@ public abstract class AbstractWebIntegrationTests { protected MockHttpServletResponse deleteAndGet(Link link, MediaType mediaType) throws Exception { - String href; - if (link.isTemplated()) { - href = link.expand().getHref(); - } else { - href = link.getHref(); - } + String href = link.isTemplated() ? link.expand().getHref() : link.getHref(); MockHttpServletResponse response = mvc.perform(delete(href).contentType(mediaType)).// andExpect(status().isNoContent()).// diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java index f1e5650be..aaea3d138 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.rest.webmvc.jpa; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -23,11 +23,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Scanner; -import net.minidev.json.JSONArray; - import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -41,12 +40,11 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.util.UriTemplate; import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; -import org.springframework.util.StringUtils; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriTemplate; /** * Web integration tests specific to JPA. @@ -194,40 +192,24 @@ public class JpaWebTests extends AbstractWebIntegrationTests { mvc.perform(get(href)).andExpect(status().isOk()); } - /** * @see DATAREST-219 */ @Test public void manipulatePropertyCollectionRestfullyWithMultiplePosts() throws Exception { - ObjectMapper mapper = new ObjectMapper(); + List links = preparePersonResources(new Person("Frodo", "Baggins"), // + new Person("Bilbo", "Baggins"), // + new Person("Merry", "Baggins"), // + new Person("Pippin", "Baggins")); - String bilbo = mapper.writeValueAsString(new Person("Bilbo", "Baggins")); - String frodo = mapper.writeValueAsString(new Person("Frodo", "Baggins")); - String merry = mapper.writeValueAsString(new Person("Merry", "Baggins")); - String pippin = mapper.writeValueAsString(new Person("Pippin", "Baggins")); + Link frodosSiblingLink = links.get(0); - Link peopleLink = discoverUnique("people"); + postAndGet(frodosSiblingLink, links.get(1).getHref(), TEXT_URI_LIST); + postAndGet(frodosSiblingLink, links.get(2).getHref(), TEXT_URI_LIST); + postAndGet(frodosSiblingLink, links.get(3).getHref(), TEXT_URI_LIST); - MockHttpServletResponse bilboResponse = postAndGet(peopleLink, bilbo, MediaType.APPLICATION_JSON); - MockHttpServletResponse frodoResponse = postAndGet(peopleLink, frodo, MediaType.APPLICATION_JSON); - MockHttpServletResponse merryResponse = postAndGet(peopleLink, merry, MediaType.APPLICATION_JSON); - MockHttpServletResponse pippinResponse = postAndGet(peopleLink, pippin, MediaType.APPLICATION_JSON); - - Link bilboSelfLink = assertHasLinkWithRel(Link.REL_SELF, bilboResponse); - Link merrySelfLink = assertHasLinkWithRel(Link.REL_SELF, merryResponse); - Link pippinSelfLink = assertHasLinkWithRel(Link.REL_SELF, pippinResponse); - Link frodosSiblingsLink = assertHasLinkWithRel("siblings", frodoResponse); - - postAndGet(frodosSiblingsLink, bilboSelfLink.getHref(), TEXT_URI_LIST); - postAndGet(frodosSiblingsLink, merrySelfLink.getHref(), TEXT_URI_LIST); - postAndGet(frodosSiblingsLink, pippinSelfLink.getHref(), TEXT_URI_LIST); - - MockHttpServletResponse frodosLatestSiblings = request(frodosSiblingsLink); - String[] persons = ((JSONArray) JsonPath.read(frodosLatestSiblings.getContentAsString(), "$._embedded.persons[*].firstName")).toArray(new String[]{}); - assertThat(persons.length, equalTo(3)); - assertThat(Arrays.asList(persons), hasItems("Bilbo", "Merry", "Pippin")); + assertSiblingNames(frodosSiblingLink, "Bilbo", "Merry", "Pippin"); } /** @@ -236,34 +218,16 @@ public class JpaWebTests extends AbstractWebIntegrationTests { @Test public void manipulatePropertyCollectionRestfullyWithSinglePost() throws Exception { - ObjectMapper mapper = new ObjectMapper(); + List links = preparePersonResources(new Person("Frodo", "Baggins"), // + new Person("Bilbo", "Baggins"), // + new Person("Merry", "Baggins"), // + new Person("Pippin", "Baggins")); - String bilbo = mapper.writeValueAsString(new Person("Bilbo", "Baggins")); - String frodo = mapper.writeValueAsString(new Person("Frodo", "Baggins")); - String merry = mapper.writeValueAsString(new Person("Merry", "Baggins")); - String pippin = mapper.writeValueAsString(new Person("Pippin", "Baggins")); + Link frodosSiblingLink = links.get(0); - Link peopleLink = discoverUnique("people"); + postAndGet(frodosSiblingLink, toUriList(links.get(1), links.get(2), links.get(3)), TEXT_URI_LIST); - MockHttpServletResponse bilboResponse = postAndGet(peopleLink, bilbo, MediaType.APPLICATION_JSON); - MockHttpServletResponse frodoResponse = postAndGet(peopleLink, frodo, MediaType.APPLICATION_JSON); - MockHttpServletResponse merryResponse = postAndGet(peopleLink, merry, MediaType.APPLICATION_JSON); - MockHttpServletResponse pippinResponse = postAndGet(peopleLink, pippin, MediaType.APPLICATION_JSON); - - final Link bilboSelfLink = assertHasLinkWithRel(Link.REL_SELF, bilboResponse); - final Link merrySelfLink = assertHasLinkWithRel(Link.REL_SELF, merryResponse); - final Link pippinSelfLink = assertHasLinkWithRel(Link.REL_SELF, pippinResponse); - Link frodosSiblingsLink = assertHasLinkWithRel("siblings", frodoResponse); - - postAndGet(frodosSiblingsLink, - StringUtils.arrayToDelimitedString(new Object[]{bilboSelfLink.getHref(), - merrySelfLink.getHref(), pippinSelfLink.getHref()}, "\n"), - TEXT_URI_LIST); - - MockHttpServletResponse frodosLatestSiblings = request(frodosSiblingsLink); - String[] persons = ((JSONArray) JsonPath.read(frodosLatestSiblings.getContentAsString(), "$._embedded.persons[*].firstName")).toArray(new String[]{}); - assertThat(persons.length, equalTo(3)); - assertThat(Arrays.asList(persons), hasItems("Bilbo", "Merry", "Pippin")); + assertSiblingNames(frodosSiblingLink, "Bilbo", "Merry", "Pippin"); } /** @@ -272,40 +236,20 @@ public class JpaWebTests extends AbstractWebIntegrationTests { @Test public void manipulatePropertyCollectionRestfullyWithMultiplePuts() throws Exception { - ObjectMapper mapper = new ObjectMapper(); + List links = preparePersonResources(new Person("Frodo", "Baggins"), // + new Person("Bilbo", "Baggins"), // + new Person("Merry", "Baggins"), // + new Person("Pippin", "Baggins")); - String bilbo = mapper.writeValueAsString(new Person("Bilbo", "Baggins")); - String frodo = mapper.writeValueAsString(new Person("Frodo", "Baggins")); - String merry = mapper.writeValueAsString(new Person("Merry", "Baggins")); - String pippin = mapper.writeValueAsString(new Person("Pippin", "Baggins")); + Link frodosSiblingsLink = links.get(0); - Link peopleLink = discoverUnique("people"); + putAndGet(frodosSiblingsLink, links.get(1).getHref(), TEXT_URI_LIST); + putAndGet(frodosSiblingsLink, links.get(2).getHref(), TEXT_URI_LIST); + putAndGet(frodosSiblingsLink, links.get(3).getHref(), TEXT_URI_LIST); + assertSiblingNames(frodosSiblingsLink, "Pippin"); - MockHttpServletResponse bilboResponse = postAndGet(peopleLink, bilbo, MediaType.APPLICATION_JSON); - MockHttpServletResponse frodoResponse = postAndGet(peopleLink, frodo, MediaType.APPLICATION_JSON); - MockHttpServletResponse merryResponse = postAndGet(peopleLink, merry, MediaType.APPLICATION_JSON); - MockHttpServletResponse pippinResponse = postAndGet(peopleLink, pippin, MediaType.APPLICATION_JSON); - - Link bilboSelfLink = assertHasLinkWithRel(Link.REL_SELF, bilboResponse); - Link merrySelfLink = assertHasLinkWithRel(Link.REL_SELF, merryResponse); - Link pippinSelfLink = assertHasLinkWithRel(Link.REL_SELF, pippinResponse); - Link frodosSiblingsLink = assertHasLinkWithRel("siblings", frodoResponse); - - putAndGet(frodosSiblingsLink, bilboSelfLink.getHref(), TEXT_URI_LIST); - putAndGet(frodosSiblingsLink, merrySelfLink.getHref(), TEXT_URI_LIST); - putAndGet(frodosSiblingsLink, pippinSelfLink.getHref(), TEXT_URI_LIST); - - MockHttpServletResponse frodosLatestSiblings = request(frodosSiblingsLink); - String firstName = JsonPath.read(frodosLatestSiblings.getContentAsString(), "$._embedded.person.firstName"); - assertThat(firstName, equalTo("Pippin")); - - postAndGet(frodosSiblingsLink, merrySelfLink.getHref(), TEXT_URI_LIST); - - frodosLatestSiblings = request(frodosSiblingsLink); - String[] persons = ((JSONArray) JsonPath.read(frodosLatestSiblings.getContentAsString(), - "$._embedded.persons[*].firstName")).toArray(new String[]{}); - assertThat(persons.length, equalTo(2)); - assertThat(Arrays.asList(persons), hasItems("Merry", "Pippin")); + postAndGet(frodosSiblingsLink, links.get(2).getHref(), TEXT_URI_LIST); + assertSiblingNames(frodosSiblingsLink, "Merry", "Pippin"); } /** @@ -314,42 +258,21 @@ public class JpaWebTests extends AbstractWebIntegrationTests { @Test public void manipulatePropertyCollectionRestfullyWithSinglePut() throws Exception { - ObjectMapper mapper = new ObjectMapper(); + List links = preparePersonResources(new Person("Frodo", "Baggins"), // + new Person("Bilbo", "Baggins"), // + new Person("Merry", "Baggins"), // + new Person("Pippin", "Baggins")); - String bilbo = mapper.writeValueAsString(new Person("Bilbo", "Baggins")); - String frodo = mapper.writeValueAsString(new Person("Frodo", "Baggins")); - String merry = mapper.writeValueAsString(new Person("Merry", "Baggins")); - String pippin = mapper.writeValueAsString(new Person("Pippin", "Baggins")); + Link frodoSiblingLink = links.get(0); - Link peopleLink = discoverUnique("people"); + putAndGet(frodoSiblingLink, toUriList(links.get(1), links.get(2), (links.get(3))), TEXT_URI_LIST); + assertSiblingNames(frodoSiblingLink, "Bilbo", "Merry", "Pippin"); - MockHttpServletResponse bilboResponse = postAndGet(peopleLink, bilbo, MediaType.APPLICATION_JSON); - MockHttpServletResponse frodoResponse = postAndGet(peopleLink, frodo, MediaType.APPLICATION_JSON); - MockHttpServletResponse merryResponse = postAndGet(peopleLink, merry, MediaType.APPLICATION_JSON); - MockHttpServletResponse pippinResponse = postAndGet(peopleLink, pippin, MediaType.APPLICATION_JSON); + putAndGet(frodoSiblingLink, toUriList(links.get(3)), TEXT_URI_LIST); + assertSiblingNames(frodoSiblingLink, "Pippin"); - Link bilboSelfLink = assertHasLinkWithRel(Link.REL_SELF, bilboResponse); - Link merrySelfLink = assertHasLinkWithRel(Link.REL_SELF, merryResponse); - Link pippinSelfLink = assertHasLinkWithRel(Link.REL_SELF, pippinResponse); - Link frodosSiblingsLink = assertHasLinkWithRel("siblings", frodoResponse); - - putAndGet(frodosSiblingsLink, - StringUtils.arrayToDelimitedString(new Object[]{bilboSelfLink.getHref(), - merrySelfLink.getHref()}, "\n"), - TEXT_URI_LIST); - putAndGet(frodosSiblingsLink, pippinSelfLink.getHref(), TEXT_URI_LIST); - - MockHttpServletResponse frodosLatestSiblings = request(frodosSiblingsLink); - String firstName = JsonPath.read(frodosLatestSiblings.getContentAsString(), "$._embedded.person.firstName"); - assertThat(firstName, equalTo("Pippin")); - - postAndGet(frodosSiblingsLink, merrySelfLink.getHref(), TEXT_URI_LIST); - - frodosLatestSiblings = request(frodosSiblingsLink); - String[] persons = ((JSONArray) JsonPath.read(frodosLatestSiblings.getContentAsString(), - "$._embedded.persons[*].firstName")).toArray(new String[]{}); - assertThat(persons.length, equalTo(2)); - assertThat(Arrays.asList(persons), hasItems("Merry", "Pippin")); + postAndGet(frodoSiblingLink, toUriList(links.get(2)), TEXT_URI_LIST); + assertSiblingNames(frodoSiblingLink, "Merry", "Pippin"); } /** @@ -358,49 +281,88 @@ public class JpaWebTests extends AbstractWebIntegrationTests { @Test public void manipulatePropertyCollectionRestfullyWithDelete() throws Exception { - ObjectMapper mapper = new ObjectMapper(); + List links = preparePersonResources(new Person("Frodo", "Baggins"), // + new Person("Bilbo", "Baggins"), // + new Person("Merry", "Baggins"), // + new Person("Pippin", "Baggins")); - String bilbo = mapper.writeValueAsString(new Person("Bilbo", "Baggins")); - String frodo = mapper.writeValueAsString(new Person("Frodo", "Baggins")); - String merry = mapper.writeValueAsString(new Person("Merry", "Baggins")); - String pippin = mapper.writeValueAsString(new Person("Pippin", "Baggins")); + Link frodosSiblingsLink = links.get(0); - Link peopleLink = discoverUnique("people"); + postAndGet(frodosSiblingsLink, links.get(1).getHref(), TEXT_URI_LIST); + postAndGet(frodosSiblingsLink, links.get(2).getHref(), TEXT_URI_LIST); + postAndGet(frodosSiblingsLink, links.get(3).getHref(), TEXT_URI_LIST); - MockHttpServletResponse bilboResponse = postAndGet(peopleLink, bilbo, MediaType.APPLICATION_JSON); - MockHttpServletResponse frodoResponse = postAndGet(peopleLink, frodo, MediaType.APPLICATION_JSON); - MockHttpServletResponse merryResponse = postAndGet(peopleLink, merry, MediaType.APPLICATION_JSON); - MockHttpServletResponse pippinResponse = postAndGet(peopleLink, pippin, MediaType.APPLICATION_JSON); - - Link bilboSelfLink = assertHasLinkWithRel(Link.REL_SELF, bilboResponse); - Link merrySelfLink = assertHasLinkWithRel(Link.REL_SELF, merryResponse); - Link pippinSelfLink = assertHasLinkWithRel(Link.REL_SELF, pippinResponse); - Link frodosSiblingsLink = assertHasLinkWithRel("siblings", frodoResponse); - - postAndGet(frodosSiblingsLink, bilboSelfLink.getHref(), TEXT_URI_LIST); - postAndGet(frodosSiblingsLink, merrySelfLink.getHref(), TEXT_URI_LIST); - postAndGet(frodosSiblingsLink, pippinSelfLink.getHref(), TEXT_URI_LIST); - - String pippinId = new UriTemplate("/people/{id}").match(pippinSelfLink.getHref()).get("id"); + String pippinId = new UriTemplate("/people/{id}").match(links.get(3).getHref()).get("id"); deleteAndGet(new Link(frodosSiblingsLink.getHref() + "/" + pippinId), TEXT_URI_LIST); - MockHttpServletResponse frodosLatestSiblings = request(frodosSiblingsLink); - String[] persons = ((JSONArray) JsonPath.read(frodosLatestSiblings.getContentAsString(), "$._embedded.persons[*].firstName")).toArray(new String[]{}); - assertThat(persons.length, equalTo(2)); - assertThat(Arrays.asList(persons), hasItems("Bilbo", "Merry")); + assertSiblingNames(frodosSiblingsLink, "Bilbo", "Merry"); } + private List preparePersonResources(Person primary, Person... persons) throws Exception { - private String readFile(String name) throws Exception { + Link peopleLink = discoverUnique("people"); + ObjectMapper mapper = new ObjectMapper(); + List links = new ArrayList(); - ClassPathResource file = new ClassPathResource(name, getClass()); + MockHttpServletResponse primaryResponse = postAndGet(peopleLink, mapper.writeValueAsString(primary), + MediaType.APPLICATION_JSON); + links.add(assertHasLinkWithRel("siblings", primaryResponse)); + + for (Person person : persons) { + + String payload = mapper.writeValueAsString(person); + MockHttpServletResponse response = postAndGet(peopleLink, payload, MediaType.APPLICATION_JSON); + + links.add(assertHasLinkWithRel(Link.REL_SELF, response)); + } + + return links; + } + + /** + * Asserts the {@link Person} resource the given link points to contains siblings with the given names. + * + * @param link + * @param siblingNames + * @throws Exception + */ + private void assertSiblingNames(Link link, String... siblingNames) throws Exception { + + String responseBody = request(link).getContentAsString(); + List persons = JsonPath.read(responseBody, "$._embedded.persons[*].firstName"); + + assertThat(persons, hasSize(siblingNames.length)); + assertThat(persons, hasItems(siblingNames)); + } + + private static String readFile(String name) throws Exception { + + ClassPathResource file = new ClassPathResource(name, JpaWebTests.class); StringBuilder builder = new StringBuilder(); + Scanner scanner = new Scanner(file.getFile(), "UTF-8"); - while (scanner.hasNextLine()) { - builder.append(scanner.nextLine()); + try { + + while (scanner.hasNextLine()) { + builder.append(scanner.nextLine()); + } + + } finally { + scanner.close(); } return builder.toString(); } + + private static String toUriList(Link... links) { + + List uris = new ArrayList(links.length); + + for (Link link : links) { + uris.add(link.expand().getHref()); + } + + return StringUtils.collectionToDelimitedString(uris, "\n"); + } }