diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 447dd07159..a0adc5a51f 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -8,3 +8,4 @@ Module for the articles that are part of the Spring REST E-book: 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) 7. [Versioning a REST API](http://www.baeldung.com/rest-versioning) 8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) +9. [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java index f19d1c0e0b..c8af731bc5 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -7,6 +7,7 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.Version; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -20,6 +21,9 @@ public class Foo implements Serializable { @Column(nullable = false) private String name; + + @Version + private long version; public Foo() { super(); @@ -49,6 +53,14 @@ public class Foo implements Serializable { this.name = name; } + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } + // @Override diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index f581e4ec10..d5559bfae7 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -9,6 +9,7 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; import org.springframework.oxm.xstream.XStreamMarshaller; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @@ -45,5 +46,15 @@ public class WebConfig implements WebMvcConfigurer { // // return xmlConverter; // } + + + // Etags + + // If we're not using Spring Boot we can make use of + // AbstractAnnotationConfigDispatcherServletInitializer#getServletFilters + @Bean + public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { + return new ShallowEtagHeaderFilter(); + } } \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index 59e33263db..255fcaabb7 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -9,6 +9,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -45,6 +46,18 @@ public class FooController { } // API + + // Note: the global filter overrides the ETag value we set here. We can still analyze its behaviour in the Integration Test. + @GetMapping(value = "/{id}/custom-etag") + public ResponseEntity findByIdWithCustomEtag(@PathVariable("id") final Long id, + final HttpServletResponse response) { + final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + + eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); + return ResponseEntity.ok() + .eTag(Long.toString(resourceById.getVersion())) + .body(resourceById); + } // read - one diff --git a/spring-boot-rest/src/main/resources/WEB-INF/web.xml b/spring-boot-rest/src/main/resources/WEB-INF/web.xml new file mode 100644 index 0000000000..7f36b33b38 --- /dev/null +++ b/spring-boot-rest/src/main/resources/WEB-INF/web.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java index 61eb9400cc..ecf938be50 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java @@ -1,21 +1,28 @@ package com.baeldung.common.web; import static com.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.util.List; +import org.junit.Ignore; import org.junit.Test; +import com.baeldung.persistence.model.Foo; import com.google.common.net.HttpHeaders; import io.restassured.RestAssured; +import io.restassured.http.ContentType; import io.restassured.response.Response; public abstract class AbstractBasicLiveTest extends AbstractLiveTest { @@ -97,7 +104,82 @@ public abstract class AbstractBasicLiveTest extends Abst final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); assertNull(uriToNextPage); } + + // etags - // count + @Test + public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() { + // Given + final String uriOfResource = createAsUri(); + + // When + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + + // Then + assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG)); + } + + @Test + public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() { + // Given + final String uriOfResource = createAsUri(); + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); + + // When + final Response secondFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-None-Match", etagValue) + .get(uriOfResource); + + // Then + assertTrue(secondFindOneResponse.getStatusCode() == 304); + } + + @Test + public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtag_thenResourceIsReturned() { + // Given + final String uriOfResource = createAsUri(); + final Response firstFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + final String etagValue = firstFindOneResponse.getHeader(HttpHeaders.ETAG); + final long createdId = firstFindOneResponse.jsonPath().getLong("id"); + + Foo updatedFoo = new Foo("updated value"); + updatedFoo.setId(createdId); + Response updatedResponse = RestAssured.given().contentType(ContentType.JSON).body(updatedFoo) + .put(uriOfResource); + assertThat(updatedResponse.getStatusCode() == 200); + + // When + final Response secondFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-None-Match", etagValue) + .get(uriOfResource); + + // Then + assertTrue(secondFindOneResponse.getStatusCode() == 200); + } + + @Test + @Ignore("Not Yet Implemented By Spring - https://jira.springsource.org/browse/SPR-10164") + public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() { + // Given + final String uriOfResource = createAsUri(); + + // When + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-Match", randomAlphabetic(8)) + .get(uriOfResource); + + // Then + assertTrue(findOneResponse.getStatusCode() == 412); + } } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java new file mode 100644 index 0000000000..dc48c21b30 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java @@ -0,0 +1,116 @@ +package com.baeldung.web; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import com.baeldung.persistence.model.Foo; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.net.HttpHeaders; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc(addFilters = false) +public class FooControllerCustomEtagIntegrationTest { + + @Autowired + private MockMvc mvc; + + private String FOOS_ENDPOINT = "/auth/foos/"; + private String CUSTOM_ETAG_ENDPOINT_SUFFIX = "/custom-etag"; + + private static String serializeFoo(Foo foo) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(foo); + } + + private static String createFooJson() throws Exception { + return serializeFoo(new Foo(randomAlphabetic(6))); + } + + private static Foo deserializeFoo(String fooJson) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(fooJson, Foo.class); + } + + @Test + public void givenResourceExists_whenRetrievingResourceUsingCustomEtagEndpoint_thenEtagIsAlsoReturned() + throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + + // Then + result.andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ETAG, "\"0\"")); + } + + @Test + public void givenResourceWasRetrieved_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenNotModifiedReturned() throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + ResultActions findOneResponse = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag)); + + // Then + result.andExpect(status().isNotModified()); + } + + @Test + public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenResourceIsReturned() throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + ResultActions findOneResponse = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG); + Foo createdFoo = deserializeFoo(findOneResponse.andReturn().getResponse().getContentAsString()); + createdFoo.setName("updated name"); + this.mvc + .perform(put(createdResourceUri).contentType(MediaType.APPLICATION_JSON).content(serializeFoo(createdFoo))); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag)); + + // Then + result.andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ETAG, "\"1\"")); + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java index b7cceb9008..bc45d8352a 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java @@ -8,8 +8,8 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ // @formatter:off FooDiscoverabilityLiveTest.class, - FooLiveTest.class - ,FooPageableLiveTest.class + FooLiveTest.class, + FooPageableLiveTest.class }) // public class LiveTestSuiteLiveTest { diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index b8b9034a0b..32b65ccc6a 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -8,7 +8,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) - [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin) - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java index 9a3f473b8b..950e2085a6 100644 --- a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java +++ b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java @@ -8,11 +8,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.context.request.RequestContextListener; -import org.springframework.web.filter.ShallowEtagHeaderFilter; /** * Main Application Class - uses Spring Boot. Just run this as a normal Java @@ -40,8 +38,4 @@ public class Application extends SpringBootServletInitializer { SpringApplication.run(Application.class, args); } - @Bean - public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { - return new ShallowEtagHeaderFilter(); - } } \ No newline at end of file diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 9cb028bfdb..caaf422410 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -6,10 +6,8 @@ import javax.servlet.http.HttpServletResponse; import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; -import org.baeldung.web.hateoas.event.ResourceCreatedEvent; import org.baeldung.web.util.RestPreconditions; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -26,9 +24,6 @@ import com.google.common.base.Preconditions; @RequestMapping(value = "/auth/foos") public class FooController { - @Autowired - private ApplicationEventPublisher eventPublisher; - @Autowired private IFooService service; @@ -71,9 +66,6 @@ public class FooController { public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { Preconditions.checkNotNull(resource); final Foo foo = service.create(resource); - final Long idOfCreatedResource = foo.getId(); - - eventPublisher.publishEvent(new ResourceCreatedEvent(this, response, idOfCreatedResource)); return foo; } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java b/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java deleted file mode 100644 index efc04299bc..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.web.hateoas.event; - -import javax.servlet.http.HttpServletResponse; - -import org.springframework.context.ApplicationEvent; - -public class ResourceCreatedEvent extends ApplicationEvent { - private final HttpServletResponse response; - private final long idOfNewResource; - - public ResourceCreatedEvent(final Object source, final HttpServletResponse response, final long idOfNewResource) { - super(source); - - this.response = response; - this.idOfNewResource = idOfNewResource; - } - - // API - - public HttpServletResponse getResponse() { - return response; - } - - public long getIdOfNewResource() { - return idOfNewResource; - } - -} diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java b/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java deleted file mode 100644 index 0b308712cb..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.web.hateoas.listener; - -import java.net.URI; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.http.HttpHeaders; -import org.baeldung.web.hateoas.event.ResourceCreatedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import com.google.common.base.Preconditions; - -@Component -class ResourceCreatedDiscoverabilityListener implements ApplicationListener { - - @Override - public void onApplicationEvent(final ResourceCreatedEvent resourceCreatedEvent) { - Preconditions.checkNotNull(resourceCreatedEvent); - - final HttpServletResponse response = resourceCreatedEvent.getResponse(); - final long idOfNewResource = resourceCreatedEvent.getIdOfNewResource(); - - addLinkHeaderOnResourceCreation(response, idOfNewResource); - } - - void addLinkHeaderOnResourceCreation(final HttpServletResponse response, final long idOfNewResource) { - // final String requestUrl = request.getRequestURL().toString(); - // final URI uri = new UriTemplate("{requestUrl}/{idOfNewResource}").expand(requestUrl, idOfNewResource); - - final URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/{idOfNewResource}").buildAndExpand(idOfNewResource).toUri(); - response.setHeader(HttpHeaders.LOCATION, uri.toASCIIString()); - } - -} \ No newline at end of file diff --git a/spring-rest-full/src/main/webapp/WEB-INF/web.xml b/spring-rest-full/src/main/webapp/WEB-INF/web.xml index 85bc72469e..5f90c3519f 100644 --- a/spring-rest-full/src/main/webapp/WEB-INF/web.xml +++ b/spring-rest-full/src/main/webapp/WEB-INF/web.xml @@ -23,15 +23,6 @@ org.springframework.web.context.ContextLoaderListener - - etagFilter - org.springframework.web.filter.ShallowEtagHeaderFilter - - - etagFilter - /* - - api diff --git a/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java deleted file mode 100644 index 76215bb6e3..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.baeldung; - -import org.baeldung.persistence.PersistenceTestSuite; -import org.baeldung.web.LiveTestSuiteLiveTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ -// @formatter:off - PersistenceTestSuite.class - ,LiveTestSuiteLiveTest.class -}) // -public class TestSuiteLiveTest { - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java deleted file mode 100644 index d64807d97f..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.baeldung.common.web; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; - -import org.junit.Ignore; -import org.junit.Test; - -import com.google.common.net.HttpHeaders; - -import io.restassured.RestAssured; -import io.restassured.response.Response; - -public abstract class AbstractBasicLiveTest extends AbstractLiveTest { - - public AbstractBasicLiveTest(final Class clazzToSet) { - super(clazzToSet); - } - - // tests - - @Test - public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() { - // Given - final String uriOfResource = createAsUri(); - - // When - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - - // Then - assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG)); - } - - @Test - public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() { - // Given - final String uriOfResource = createAsUri(); - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); - - // When - final Response secondFindOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-None-Match", etagValue) - .get(uriOfResource); - - // Then - assertTrue(secondFindOneResponse.getStatusCode() == 304); - } - - @Test - @Ignore("No Update operation yet") - public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtag_thenResourceIsReturned() { - // Given - final String uriOfResource = createAsUri(); - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); - - // existingResource.setName(randomAlphabetic(6)); - // getApi().update(existingResource.setName("randomString")); - - // When - final Response secondFindOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-None-Match", etagValue) - .get(uriOfResource); - - // Then - assertTrue(secondFindOneResponse.getStatusCode() == 200); - } - - @Test - @Ignore("Not Yet Implemented By Spring - https://jira.springsource.org/browse/SPR-10164") - public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() { - // Given - final String uriOfResource = createAsUri(); - - // When - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-Match", randomAlphabetic(8)) - .get(uriOfResource); - - // Then - assertTrue(findOneResponse.getStatusCode() == 412); - } - - // find - one - - // find - all -} diff --git a/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java deleted file mode 100644 index 65564a6845..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.baeldung.web; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; - -import org.baeldung.common.web.AbstractBasicLiveTest; -import org.baeldung.persistence.model.Foo; -import org.baeldung.spring.ConfigIntegrationTest; -import org.junit.runner.RunWith; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class) -@ActiveProfiles("test") -public class FooLiveTest extends AbstractBasicLiveTest { - - public FooLiveTest() { - super(Foo.class); - } - - // API - - @Override - public final void create() { - create(new Foo(randomAlphabetic(6))); - } - - @Override - public final String createAsUri() { - return createAsUri(new Foo(randomAlphabetic(6))); - } - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java deleted file mode 100644 index 663935e72f..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.web; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ -// @formatter:off - FooLiveTest.class -}) // -public class LiveTestSuiteLiveTest { - -}