etag work

This commit is contained in:
eugenp 2014-01-05 20:25:03 +02:00
parent 71122adb3e
commit c2c3b5ed74
6 changed files with 316 additions and 140 deletions

View File

@ -1,52 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>Spring Security REST Application</display-name>
<display-name>Spring Security REST Application</display-name>
<!-- Spring root -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
<!-- Spring root -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.baeldung.spring</param-value>
</context-param>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.baeldung.spring</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring child -->
<servlet>
<servlet-name>api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>api</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>etagFilter</filter-name>
<filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>etagFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring child -->
<servlet>
<servlet-name>api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>api</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -0,0 +1,158 @@
package org.baeldung.common.web;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
import static org.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel;
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.google.common.net.HttpHeaders;
import com.jayway.restassured.response.Response;
public abstract class AbstractBasicLiveTest<T extends Serializable> extends AbstractLiveTest<T> {
public AbstractBasicLiveTest(final Class<T> clazzToSet) {
super(clazzToSet);
}
// tests
@Test
public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() {
// Given
final String uriOfResource = createAsUri();
// When
final Response findOneResponse = givenAuth().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 = givenAuth().header("Accept", "application/json").get(uriOfResource);
final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);
// When
final Response secondFindOneResponse = givenAuth().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 = givenAuth().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 = givenAuth().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 = givenAuth().header("Accept", "application/json").headers("If-Match", randomAlphabetic(8)).get(uriOfResource);
// Then
assertTrue(findOneResponse.getStatusCode() == 412);
}
// find - one
// find - all
// find - all - paginated
@Test
public void whenResourcesAreRetrievedPaged_then200IsReceived() {
final Response response = givenAuth().get(getURL() + "?page=0&size=10");
assertThat(response.getStatusCode(), is(200));
}
@Test
public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() {
final String url = getURL() + "?page=" + randomNumeric(5) + "&size=10";
final Response response = givenAuth().get(url);
assertThat(response.getStatusCode(), is(404));
}
@Test
public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() {
create();
final Response response = givenAuth().get(getURL() + "?page=0&size=10");
assertFalse(response.body().as(List.class).isEmpty());
}
@Test
public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() {
final Response response = givenAuth().get(getURL() + "?page=0&size=2");
final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
assertEquals(getURL() + "?page=1&size=2", uriToNextPage);
}
@Test
public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() {
final Response response = givenAuth().get(getURL() + "?page=0&size=2");
final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
assertNull(uriToPrevPage);
}
@Test
public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() {
create();
create();
final Response response = givenAuth().get(getURL() + "?page=1&size=2");
final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
assertEquals(getURL() + "?page=0&size=2", uriToPrevPage);
}
@Test
public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() {
final Response first = givenAuth().get(getURL() + "?page=0&size=2");
final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last");
final Response response = givenAuth().get(uriToLastPage);
final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
assertNull(uriToNextPage);
}
// count
}

View File

@ -0,0 +1,74 @@
package org.baeldung.common.web;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.Serializable;
import org.baeldung.persistence.model.Foo;
import org.baeldung.web.util.HTTPLinkHeaderUtil;
import org.hamcrest.core.AnyOf;
import org.junit.Test;
import org.springframework.http.MediaType;
import com.google.common.net.HttpHeaders;
import com.jayway.restassured.response.Response;
public abstract class AbstractDiscoverabilityLiveTest<T extends Serializable> extends AbstractLiveTest<T> {
public AbstractDiscoverabilityLiveTest(final Class<T> clazzToSet) {
super(clazzToSet);
}
// tests
// discoverability
@Test
public void whenInvalidPOSTIsSentToValidURIOfResource_thenAllowHeaderListsTheAllowedActions() {
// Given
final String uriOfExistingResource = createAsUri();
// When
final Response res = givenAuth().post(uriOfExistingResource);
// Then
final String allowHeader = res.getHeader(HttpHeaders.ALLOW);
assertThat(allowHeader, AnyOf.<String> anyOf(containsString("GET"), containsString("PUT"), containsString("DELETE")));
}
@Test
public void whenResourceIsCreated_thenUriOfTheNewlyCreatedResourceIsDiscoverable() {
// When
final Foo newResource = new Foo(randomAlphabetic(6));
final Response createResp = givenAuth().contentType(MediaType.APPLICATION_JSON_VALUE).body(newResource).post(getURL());
final String uriOfNewResource = createResp.getHeader(HttpHeaders.LOCATION);
// Then
final Response response = givenAuth().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE).get(uriOfNewResource);
final Foo resourceFromServer = response.body().as(Foo.class);
assertThat(newResource, equalTo(resourceFromServer));
}
@Test
public void whenResourceIsRetrieved_thenUriToGetAllResourcesIsDiscoverable() {
// Given
final String uriOfExistingResource = createAsUri();
// When
final Response getResponse = givenAuth().get(uriOfExistingResource);
// Then
final String uriToAllResources = HTTPLinkHeaderUtil.extractURIByRel(getResponse.getHeader("Link"), "collection");
final Response getAllResponse = givenAuth().get(uriToAllResources);
assertThat(getAllResponse.getStatusCode(), is(200));
}
// template method
}

View File

@ -1,20 +1,8 @@
package org.baeldung.common.web;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
import static org.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import java.io.Serializable;
import java.util.List;
import org.baeldung.test.IMarshaller;
import org.hamcrest.core.AnyOf;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Preconditions;
@ -37,90 +25,6 @@ public abstract class AbstractLiveTest<T extends Serializable> {
clazz = clazzToSet;
}
// tests
@Test
public void whenInvalidPOSTIsSentToValidURIOfResource_thenAllowHeaderListsTheAllowedActions() {
// Given
final String uriOfExistingResource = createAsUri();
// When
final Response res = givenAuth().post(uriOfExistingResource);
// Then
final String allowHeader = res.getHeader(HttpHeaders.ALLOW);
assertThat(allowHeader, AnyOf.<String> anyOf(containsString("GET"), containsString("PUT"), containsString("DELETE")));
}
// find - one
// find - all
// find - all - paginated
@Test
public void whenResourcesAreRetrievedPaged_then200IsReceived() {
final Response response = givenAuth().get(getFooURL() + "?page=0&size=10");
assertThat(response.getStatusCode(), is(200));
}
@Test
public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() {
final String url = getFooURL() + "?page=" + randomNumeric(5) + "&size=10";
final Response response = givenAuth().get(url);
assertThat(response.getStatusCode(), is(404));
}
@Test
public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() {
create();
final Response response = givenAuth().get(getFooURL() + "?page=0&size=10");
assertFalse(response.body().as(List.class).isEmpty());
}
@Test
public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() {
final Response response = givenAuth().get(getFooURL() + "?page=0&size=2");
final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
assertEquals(getFooURL() + "?page=1&size=2", uriToNextPage);
}
@Test
public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() {
final Response response = givenAuth().get(getFooURL() + "?page=0&size=2");
final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
assertNull(uriToPrevPage);
}
@Test
public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() {
create();
create();
final Response response = givenAuth().get(getFooURL() + "?page=1&size=2");
final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev");
assertEquals(getFooURL() + "?page=0&size=2", uriToPrevPage);
}
@Test
public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() {
final Response first = givenAuth().get(getFooURL() + "?page=0&size=2");
final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last");
final Response response = givenAuth().get(uriToLastPage);
final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
assertNull(uriToNextPage);
}
// count
// template method
public abstract void create();
@ -145,12 +49,12 @@ public abstract class AbstractLiveTest<T extends Serializable> {
final RequestSpecification givenAuthenticated = givenAuth();
final String resourceAsString = marshaller.encode(resource);
return givenAuthenticated.contentType(marshaller.getMime()).body(resourceAsString).post(getFooURL());
return givenAuthenticated.contentType(marshaller.getMime()).body(resourceAsString).post(getURL());
}
//
private String getFooURL() {
protected String getURL() {
return "http://localhost:8080/spring-security-rest-full/foos";
}

View File

@ -0,0 +1,33 @@
package org.baeldung.web;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import org.baeldung.common.web.AbstractDiscoverabilityLiveTest;
import org.baeldung.persistence.model.Foo;
import org.baeldung.spring.ConfigTest;
import org.junit.runner.RunWith;
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 = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class)
public class FooDiscoverabilityLiveTest extends AbstractDiscoverabilityLiveTest<Foo> {
public FooDiscoverabilityLiveTest() {
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)));
}
}

View File

@ -2,7 +2,7 @@ package org.baeldung.web;
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import org.baeldung.common.web.AbstractLiveTest;
import org.baeldung.common.web.AbstractBasicLiveTest;
import org.baeldung.persistence.model.Foo;
import org.baeldung.spring.ConfigTest;
import org.junit.runner.RunWith;
@ -12,7 +12,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class)
public class FooLiveTest extends AbstractLiveTest<Foo> {
public class FooLiveTest extends AbstractBasicLiveTest<Foo> {
public FooLiveTest() {
super(Foo.class);