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:
Oliver Gierke
2015-06-18 19:05:55 +02:00
parent 3e0402b70b
commit 1417287b2b
3 changed files with 36 additions and 4 deletions

View File

@@ -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);
}
/**

View File

@@ -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 {}
}

View File

@@ -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;
}