diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java index 583dff808..4d8fe194b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResource.java @@ -41,6 +41,7 @@ public class PersistentEntityResource extends Resource { private final PersistentEntity entity; private final Iterable embeddeds; private final boolean enforceAssociationLinks; + private final boolean isNew; /** * Creates a new {@link PersistentEntityResource} for the given {@link PersistentEntity}, content, embedded @@ -53,7 +54,7 @@ public class PersistentEntityResource extends Resource { * @param embeddeds can be {@literal null}. */ private PersistentEntityResource(PersistentEntity entity, Object content, Iterable links, - boolean renderAllAssociations, Iterable embeddeds) { + boolean renderAllAssociations, Iterable embeddeds, boolean isNew) { super(content, links); @@ -62,6 +63,7 @@ public class PersistentEntityResource extends Resource { this.entity = entity; this.embeddeds = embeddeds == null ? NO_EMBEDDEDS : embeddeds; this.enforceAssociationLinks = renderAllAssociations; + this.isNew = isNew; } /** @@ -91,6 +93,16 @@ public class PersistentEntityResource extends Resource { return embeddeds; } + /** + * Returns whether the content of the resource is a new entity about to be created. Used to distinguish between + * creation and updates for incoming requests. + * + * @return + */ + public boolean isNew() { + return isNew; + } + /** * Creates a new {@link Builder} to create {@link PersistentEntityResource}s eventually. * @@ -174,7 +186,17 @@ public class PersistentEntityResource extends Resource { * @return */ public PersistentEntityResource build() { - return new PersistentEntityResource(entity, content, links, renderAllAssociationLinks, embeddeds); + return new PersistentEntityResource(entity, content, links, renderAllAssociationLinks, embeddeds, false); + } + + /** + * Finally creates the {@link PersistentEntityResource} instance to symbolize the contained entity is about to be + * created. + * + * @return + */ + public PersistentEntityResource forCreation() { + return new PersistentEntityResource(entity, content, links, renderAllAssociationLinks, embeddeds, true); } } } 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 02a940e19..e64cf9963 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 @@ -371,13 +371,12 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem RepositoryInvoker invoker = resourceInformation.getInvoker(); Object objectToSave = incomingWrapper.getBean(); - Object domainObject = invoker.invokeFindOne(id); + Object domainObject = payload.getContent(); eTag.verify(resourceInformation.getPersistentEntity(), domainObject); - return domainObject == null ? createAndReturn(objectToSave, invoker, assembler, - config.returnBodyOnCreate(acceptHeader)) : saveAndReturn(objectToSave, invoker, PUT, assembler, - config.returnBodyOnUpdate(acceptHeader)); + return payload.isNew() ? createAndReturn(objectToSave, invoker, assembler, config.returnBodyOnCreate(acceptHeader)) + : saveAndReturn(objectToSave, invoker, PUT, assembler, config.returnBodyOnUpdate(acceptHeader)); } /** @@ -402,15 +401,11 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem resourceInformation.verifySupportedMethod(HttpMethod.PATCH, ResourceType.ITEM); - Object domainObject = resourceInformation.getInvoker().invokeFindOne(id); - - if (domainObject == null) { - throw new ResourceNotFoundException(); - } + Object domainObject = payload.getContent(); eTag.verify(resourceInformation.getPersistentEntity(), domainObject); - return saveAndReturn(payload.getContent(), resourceInformation.getInvoker(), PATCH, assembler, + return saveAndReturn(domainObject, resourceInformation.getInvoker(), PATCH, assembler, config.returnBodyOnUpdate(acceptHeader)); } 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 8605e709d..b02e12088 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 @@ -25,6 +25,7 @@ import org.springframework.core.MethodParameter; import org.springframework.data.repository.support.RepositoryInvoker; import org.springframework.data.rest.webmvc.IncomingRequest; import org.springframework.data.rest.webmvc.PersistentEntityResource; +import org.springframework.data.rest.webmvc.PersistentEntityResource.Builder; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.data.rest.webmvc.RootResourceInformation; import org.springframework.data.rest.webmvc.json.DomainObjectReader; @@ -122,13 +123,16 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha } Serializable id = idResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); - Object obj = read(resourceInformation, incoming, converter, id); + Object objectToUpdate = getObjectToUpdate(id, resourceInformation); + boolean forUpdate = objectToUpdate != null; + Object obj = read(resourceInformation, incoming, converter, objectToUpdate); if (obj == null) { throw new HttpMessageNotReadableException(String.format(ERROR_MESSAGE, domainType)); } - return PersistentEntityResource.build(obj, resourceInformation.getPersistentEntity()).build(); + Builder build = PersistentEntityResource.build(obj, resourceInformation.getPersistentEntity()); + return forUpdate ? build.build() : build.forCreation(); } throw new HttpMessageNotReadableException(String.format(NO_CONVERTER_FOUND, domainType, contentType)); @@ -145,9 +149,7 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha * @return */ private Object read(RootResourceInformation information, IncomingRequest request, - HttpMessageConverter converter, Serializable id) { - - Object objectToUpdate = getObjectToUpdate(id, information); + HttpMessageConverter converter, Object objectToUpdate) { // JSON + PATCH request if (request.isPatchRequest() && converter instanceof MappingJackson2HttpMessageConverter) {