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"?> <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <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"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
id="WebApp_ID" version="3.0">
<display-name>Spring Security REST Application</display-name> <display-name>Spring Security REST Application</display-name>
<!-- Spring root --> <!-- Spring root -->
<context-param> <context-param>
<param-name>contextClass</param-name> <param-name>contextClass</param-name>
<param-value> <param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value> </param-value>
</context-param> </context-param>
<context-param> <context-param>
<param-name>contextConfigLocation</param-name> <param-name>contextConfigLocation</param-name>
<param-value>org.baeldung.spring</param-value> <param-value>org.baeldung.spring</param-value>
</context-param> </context-param>
<listener> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> </listener>
<!-- Spring child --> <filter>
<servlet> <filter-name>etagFilter</filter-name>
<servlet-name>api</servlet-name> <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </filter>
<load-on-startup>1</load-on-startup> <filter-mapping>
</servlet> <filter-name>etagFilter</filter-name>
<servlet-mapping> <url-pattern>/*</url-pattern>
<servlet-name>api</servlet-name> </filter-mapping>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring Security --> <!-- Spring child -->
<filter> <servlet>
<filter-name>springSecurityFilterChain</filter-name> <servlet-name>api</servlet-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</filter> <load-on-startup>1</load-on-startup>
<filter-mapping> </servlet>
<filter-name>springSecurityFilterChain</filter-name> <servlet-mapping>
<url-pattern>/*</url-pattern> <servlet-name>api</servlet-name>
</filter-mapping> <url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list> <!-- Spring Security -->
<welcome-file>index.html</welcome-file> <filter>
</welcome-file-list> <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> </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; 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.io.Serializable;
import java.util.List;
import org.baeldung.test.IMarshaller; import org.baeldung.test.IMarshaller;
import org.hamcrest.core.AnyOf;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
@ -37,90 +25,6 @@ public abstract class AbstractLiveTest<T extends Serializable> {
clazz = clazzToSet; 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 // template method
public abstract void create(); public abstract void create();
@ -145,12 +49,12 @@ public abstract class AbstractLiveTest<T extends Serializable> {
final RequestSpecification givenAuthenticated = givenAuth(); final RequestSpecification givenAuthenticated = givenAuth();
final String resourceAsString = marshaller.encode(resource); 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"; 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 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.persistence.model.Foo;
import org.baeldung.spring.ConfigTest; import org.baeldung.spring.ConfigTest;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -12,7 +12,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class) @ContextConfiguration(classes = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class)
public class FooLiveTest extends AbstractLiveTest<Foo> { public class FooLiveTest extends AbstractBasicLiveTest<Foo> {
public FooLiveTest() { public FooLiveTest() {
super(Foo.class); super(Foo.class);