DATAREST-792 - Fixed handling of PUT request with customized entity lookups.
Until now, the controller handling a PUT request for an item resource defensively tried to set the identifier of the entity to update to guard against request payloads accidentally modifying the identifier of entities to be uploaded by using the raw identifier from the URI. Through the introduction of customized entity lookups this isn't necessarily the actual entity identifier anymore. We now apply this defensive logic in the argument resolver for the incoming PersistentEntityResource where we have access to the object to update, can lookup the actual identifier directly and set it back after Jackson has applied the request body to the object to update. Related tickets: DATAREST-724.
This commit is contained in:
@@ -31,8 +31,6 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.auditing.AuditableBeanWrapperFactory;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.querydsl.binding.QuerydslPredicate;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.data.repository.support.RepositoryInvoker;
|
||||
@@ -387,17 +385,9 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
|
||||
resourceInformation.verifySupportedMethod(HttpMethod.PUT, ResourceType.ITEM);
|
||||
|
||||
// Force ID on unmarshalled object
|
||||
PersistentPropertyAccessor incomingWrapper = new ConvertingPropertyAccessor(payload.getPropertyAccessor(),
|
||||
conversionService);
|
||||
incomingWrapper.setProperty(payload.getPersistentEntity().getIdProperty(), id);
|
||||
|
||||
RepositoryInvoker invoker = resourceInformation.getInvoker();
|
||||
Object objectToSave = incomingWrapper.getBean();
|
||||
|
||||
Object domainObject = payload.getContent();
|
||||
|
||||
eTag.verify(resourceInformation.getPersistentEntity(), domainObject);
|
||||
Object objectToSave = payload.getContent();
|
||||
eTag.verify(resourceInformation.getPersistentEntity(), objectToSave);
|
||||
|
||||
return payload.isNew() ? createAndReturn(objectToSave, invoker, assembler, config.returnBodyOnCreate(acceptHeader))
|
||||
: saveAndReturn(objectToSave, invoker, PUT, assembler, config.returnBodyOnUpdate(acceptHeader));
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.repository.support.RepositoryInvoker;
|
||||
import org.springframework.data.rest.webmvc.IncomingRequest;
|
||||
import org.springframework.data.rest.webmvc.PersistentEntityResource;
|
||||
@@ -124,14 +125,27 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha
|
||||
|
||||
Serializable id = idResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
|
||||
Object objectToUpdate = getObjectToUpdate(id, resourceInformation);
|
||||
boolean forUpdate = objectToUpdate != null;
|
||||
|
||||
boolean forUpdate = false;
|
||||
Object entityIdentifier = null;
|
||||
PersistentEntity<?, ?> entity = resourceInformation.getPersistentEntity();
|
||||
|
||||
if (objectToUpdate != null) {
|
||||
forUpdate = true;
|
||||
entityIdentifier = entity.getIdentifierAccessor(objectToUpdate).getIdentifier();
|
||||
}
|
||||
|
||||
Object obj = read(resourceInformation, incoming, converter, objectToUpdate);
|
||||
|
||||
if (obj == null) {
|
||||
throw new HttpMessageNotReadableException(String.format(ERROR_MESSAGE, domainType));
|
||||
}
|
||||
|
||||
Builder build = PersistentEntityResource.build(obj, resourceInformation.getPersistentEntity());
|
||||
if (entityIdentifier != null) {
|
||||
entity.getPropertyAccessor(obj).setProperty(entity.getIdProperty(), entityIdentifier);
|
||||
}
|
||||
|
||||
Builder build = PersistentEntityResource.build(obj, entity);
|
||||
return forUpdate ? build.build() : build.forCreation();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user