DATAREST-581 - Fixed ETag calculation for projected item resources.
Instead of using the PersistentEntityResource to obtain the ETag we now calculate headers based on the domain object and PersistentEntity upfront. This prevents the failure of trying to read the ETag from a potentially projected proxy.
This commit is contained in:
@@ -321,12 +321,13 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
List<String> ifNoneMatch = headers.getIfNoneMatch();
|
||||
ETag eTag = ifNoneMatch.isEmpty() ? ETag.NO_ETAG : ETag.from(ifNoneMatch.get(0));
|
||||
PersistentEntity<?, ?> entity = resourceInformation.getPersistentEntity();
|
||||
HttpHeaders responseHeaders = prepareHeaders(entity, domainObj);
|
||||
|
||||
if (eTag.matches(entity, domainObj)) {
|
||||
return new ResponseEntity<Resource<?>>(prepareHeaders(entity, domainObj), HttpStatus.NOT_MODIFIED);
|
||||
return new ResponseEntity<Resource<?>>(responseHeaders, HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
// Check last modification for If-Modfied-Since
|
||||
// Check last modification for If-Modified-Since
|
||||
|
||||
if (headers.getIfModifiedSince() != -1) {
|
||||
|
||||
@@ -334,12 +335,12 @@ class RepositoryEntityController extends AbstractRepositoryRestController implem
|
||||
long current = wrapper.getLastModifiedDate().getTimeInMillis() / 1000 * 1000;
|
||||
|
||||
if (current <= headers.getIfModifiedSince()) {
|
||||
return new ResponseEntity<Resource<?>>(prepareHeaders(entity, domainObj), HttpStatus.NOT_MODIFIED);
|
||||
return new ResponseEntity<Resource<?>>(responseHeaders, HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
PersistentEntityResource resource = assembler.toFullResource(domainObj);
|
||||
return new ResponseEntity<Resource<?>>(resource, prepareHeaders(resource), HttpStatus.OK);
|
||||
return new ResponseEntity<Resource<?>>(resource, responseHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,8 +23,10 @@ import static org.springframework.http.HttpMethod.*;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
|
||||
import org.springframework.data.rest.webmvc.jpa.Address;
|
||||
import org.springframework.data.rest.webmvc.jpa.AddressRepository;
|
||||
@@ -33,12 +35,14 @@ 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.data.rest.webmvc.support.ETag;
|
||||
import org.springframework.hateoas.Resource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
|
||||
/**
|
||||
@@ -244,4 +248,29 @@ public class RepositoryEntityControllerIntegrationTests extends AbstractControll
|
||||
is(false));
|
||||
assertThat(controller.postCollectionResource(request, persistentEntityResource, assembler, "").hasBody(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-581
|
||||
*/
|
||||
@Test
|
||||
public void createsEtagForProjectedEntityCorrectly() throws Exception {
|
||||
|
||||
Address address = repository.save(new Address());
|
||||
|
||||
PersistentEntityResourceAssembler assembler = Mockito.mock(PersistentEntityResourceAssembler.class);
|
||||
AddressProjection addressProjection = new SpelAwareProxyProjectionFactory()
|
||||
.createProjection(AddressProjection.class);
|
||||
|
||||
PersistentEntityResource resource = PersistentEntityResource
|
||||
.build(addressProjection, entities.getPersistentEntity(Address.class)).build();
|
||||
|
||||
Mockito.when(assembler.toFullResource(Mockito.any(Object.class))).thenReturn(resource);
|
||||
|
||||
ResponseEntity<Resource<?>> entity = controller.getItemResource(getResourceInformation(Address.class), address.id,
|
||||
assembler, new LinkedMultiValueMap<String, String>());
|
||||
|
||||
assertThat(entity.getHeaders().getETag(), is(notNullValue()));
|
||||
}
|
||||
|
||||
interface AddressProjection {}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.rest.webmvc.jpa;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
@@ -26,4 +27,5 @@ import javax.persistence.Id;
|
||||
public class Address {
|
||||
|
||||
public @Id @GeneratedValue Long id;
|
||||
public @Version Long version;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user