summaryrefslogtreecommitdiff
path: root/spring-web/src/test/java/org/springframework/web
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2016-08-03 19:55:01 +0200
committerEmmanuel Bourg <ebourg@apache.org>2016-08-03 19:55:01 +0200
commit75a721d1019da2a2fa86e24ff439df4a224e5b19 (patch)
tree2c44c00ce2c8641cccad177177e5682e187a17ea /spring-web/src/test/java/org/springframework/web
parent9eaca6a06af3cbceb3754de19d477be770614265 (diff)
Imported Upstream version 4.3.2
Diffstat (limited to 'spring-web/src/test/java/org/springframework/web')
-rw-r--r--spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java18
-rw-r--r--spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java32
-rw-r--r--spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java34
-rw-r--r--spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java188
-rw-r--r--spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java70
-rw-r--r--spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java37
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java16
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java47
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/request/SessionScopeTests.java10
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequestTests.java2
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java16
-rw-r--r--spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java15
-rw-r--r--spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java6
-rw-r--r--spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java4
-rw-r--r--spring-web/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java24
-rw-r--r--spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java241
-rw-r--r--spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java43
-rw-r--r--spring-web/src/test/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessorTests.java198
-rw-r--r--spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java180
-rw-r--r--spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java121
-rw-r--r--spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java105
-rw-r--r--spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java115
-rw-r--r--spring-web/src/test/java/org/springframework/web/util/Log4jWebConfigurerTests.java6
-rw-r--r--spring-web/src/test/java/org/springframework/web/util/UriTemplateTests.java74
-rw-r--r--spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java21
25 files changed, 1208 insertions, 415 deletions
diff --git a/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java b/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java
index e9d95c2a..baabc764 100644
--- a/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java
+++ b/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java
@@ -30,10 +30,11 @@ import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
/**
* Test fixture for {@link ContentNegotiationManagerFactoryBean} tests.
+ *
* @author Rossen Stoyanchev
*/
public class ContentNegotiationManagerFactoryBeanTests {
@@ -119,9 +120,7 @@ public class ContentNegotiationManagerFactoryBeanTests {
assertEquals(Collections.emptyList(), manager.resolveMediaTypes(this.webRequest));
}
- // SPR-10170
-
- @Test(expected = HttpMediaTypeNotAcceptableException.class)
+ @Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-10170
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception {
this.factoryBean.setFavorPathExtension(true);
this.factoryBean.setIgnoreUnknownPathExtensions(false);
@@ -152,9 +151,7 @@ public class ContentNegotiationManagerFactoryBeanTests {
manager.resolveMediaTypes(this.webRequest));
}
- // SPR-10170
-
- @Test(expected = HttpMediaTypeNotAcceptableException.class)
+ @Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-10170
public void favorParameterWithUnknownMediaType() throws HttpMediaTypeNotAcceptableException {
this.factoryBean.setFavorParameter(true);
this.factoryBean.afterPropertiesSet();
@@ -188,16 +185,12 @@ public class ContentNegotiationManagerFactoryBeanTests {
manager.resolveMediaTypes(this.webRequest));
// SPR-10513
-
this.servletRequest.addHeader("Accept", MediaType.ALL_VALUE);
-
assertEquals(Collections.singletonList(MediaType.APPLICATION_JSON),
manager.resolveMediaTypes(this.webRequest));
}
- // SPR-12286
-
- @Test
+ @Test // SPR-12286
public void setDefaultContentTypeWithStrategy() throws Exception {
this.factoryBean.setDefaultContentTypeStrategy(new FixedContentNegotiationStrategy(MediaType.APPLICATION_JSON));
this.factoryBean.afterPropertiesSet();
@@ -216,7 +209,6 @@ public class ContentNegotiationManagerFactoryBeanTests {
private final Map<String, String> mimeTypes = new HashMap<>();
-
public Map<String, String> getMimeTypes() {
return this.mimeTypes;
}
diff --git a/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java b/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java
index 72f8aca9..f6fa0d6b 100644
--- a/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java
+++ b/spring-web/src/test/java/org/springframework/web/accept/HeaderContentNegotiationStrategyTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.springframework.web.accept;
import java.util.List;
-import org.junit.Before;
import org.junit.Test;
import org.springframework.http.MediaType;
@@ -32,21 +32,16 @@ import static org.junit.Assert.*;
* Test fixture for HeaderContentNegotiationStrategy tests.
*
* @author Rossen Stoyanchev
+ * @author Juergen Hoeller
*/
public class HeaderContentNegotiationStrategyTests {
- private HeaderContentNegotiationStrategy strategy;
+ private final HeaderContentNegotiationStrategy strategy = new HeaderContentNegotiationStrategy();
- private NativeWebRequest webRequest;
+ private final MockHttpServletRequest servletRequest = new MockHttpServletRequest();
- private MockHttpServletRequest servletRequest;
+ private final NativeWebRequest webRequest = new ServletWebRequest(this.servletRequest);
- @Before
- public void setup() {
- this.strategy = new HeaderContentNegotiationStrategy();
- this.servletRequest = new MockHttpServletRequest();
- this.webRequest = new ServletWebRequest(servletRequest );
- }
@Test
public void resolveMediaTypes() throws Exception {
@@ -60,7 +55,20 @@ public class HeaderContentNegotiationStrategyTests {
assertEquals("text/plain;q=0.5", mediaTypes.get(3).toString());
}
- @Test(expected=HttpMediaTypeNotAcceptableException.class)
+ @Test // SPR-14506
+ public void resolveMediaTypesFromMultipleHeaderValues() throws Exception {
+ this.servletRequest.addHeader("Accept", "text/plain; q=0.5, text/html");
+ this.servletRequest.addHeader("Accept", "text/x-dvi; q=0.8, text/x-c");
+ List<MediaType> mediaTypes = this.strategy.resolveMediaTypes(this.webRequest);
+
+ assertEquals(4, mediaTypes.size());
+ assertEquals("text/html", mediaTypes.get(0).toString());
+ assertEquals("text/x-c", mediaTypes.get(1).toString());
+ assertEquals("text/x-dvi;q=0.8", mediaTypes.get(2).toString());
+ assertEquals("text/plain;q=0.5", mediaTypes.get(3).toString());
+ }
+
+ @Test(expected = HttpMediaTypeNotAcceptableException.class)
public void resolveMediaTypesParseError() throws Exception {
this.servletRequest.addHeader("Accept", "textplain; q=0.5");
this.strategy.resolveMediaTypes(this.webRequest);
diff --git a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
index 32b4c0e1..508be6d3 100644
--- a/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
+++ b/spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,15 @@
package org.springframework.web.bind.support;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
import java.beans.PropertyEditorSupport;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.junit.Test;
@@ -34,8 +39,6 @@ import org.springframework.web.bind.ServletRequestParameterPropertyValues;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.support.StringMultipartFileEditor;
-import static org.junit.Assert.*;
-
/**
* @author Juergen Hoeller
*/
@@ -126,6 +129,31 @@ public class WebRequestDataBinderTests {
assertFalse(target.isPostProcessed());
}
+ // SPR-13502
+ @Test
+ public void testCollectionFieldsDefault() throws Exception {
+ TestBean target = new TestBean();
+ target.setSomeSet(null);
+ target.setSomeList(null);
+ target.setSomeMap(null);
+ WebRequestDataBinder binder = new WebRequestDataBinder(target);
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addParameter("_someSet", "visible");
+ request.addParameter("_someList", "visible");
+ request.addParameter("_someMap", "visible");
+
+ binder.bind(new ServletWebRequest(request));
+ assertThat(target.getSomeSet(), notNullValue());
+ assertThat(target.getSomeSet(), isA(Set.class));
+
+ assertThat(target.getSomeList(), notNullValue());
+ assertThat(target.getSomeList(), isA(List.class));
+
+ assertThat(target.getSomeMap(), notNullValue());
+ assertThat(target.getSomeMap(), isA(Map.class));
+ }
+
@Test
public void testFieldDefaultPreemptsFieldMarker() throws Exception {
TestBean target = new TestBean();
diff --git a/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java
index 6210cec1..258a9cc4 100644
--- a/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java
+++ b/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,11 @@
package org.springframework.web.client;
+import java.io.IOException;
import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.charset.Charset;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -25,6 +28,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.junit.Assert;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
@@ -32,16 +36,28 @@ import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.AsyncClientHttpRequestExecution;
+import org.springframework.http.client.AsyncClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
+import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+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.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author Arjen Poutsma
@@ -49,14 +65,14 @@ import static org.junit.Assert.*;
*/
public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCase {
- private final AsyncRestTemplate template = new AsyncRestTemplate(new HttpComponentsAsyncClientHttpRequestFactory());
+ private final AsyncRestTemplate template = new AsyncRestTemplate(
+ new HttpComponentsAsyncClientHttpRequestFactory());
@Test
public void getEntity() throws Exception {
- Future<ResponseEntity<String>> futureEntity =
- template.getForEntity(baseUrl + "/{method}", String.class, "get");
- ResponseEntity<String> entity = futureEntity.get();
+ Future<ResponseEntity<String>> future = template.getForEntity(baseUrl + "/{method}", String.class, "get");
+ ResponseEntity<String> entity = future.get();
assertEquals("Invalid content", helloWorld, entity.getBody());
assertFalse("No headers", entity.getHeaders().isEmpty());
assertEquals("Invalid content-type", textContentType, entity.getHeaders().getContentType());
@@ -65,10 +81,9 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
@Test
public void multipleFutureGets() throws Exception {
- Future<ResponseEntity<String>> futureEntity =
- template.getForEntity(baseUrl + "/{method}", String.class, "get");
- futureEntity.get();
- futureEntity.get();
+ Future<ResponseEntity<String>> future = template.getForEntity(baseUrl + "/{method}", String.class, "get");
+ future.get();
+ future.get();
}
@Test
@@ -88,9 +103,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- // wait till done
- while (!futureEntity.isDone()) {
- }
+ waitTillDone(futureEntity);
}
@Test
@@ -103,9 +116,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertEquals("Invalid content-type", textContentType, entity.getHeaders().getContentType());
assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode());
}, ex -> fail(ex.getMessage()));
- // wait till done
- while (!futureEntity.isDone()) {
- }
+ waitTillDone(futureEntity);
}
@Test
@@ -160,8 +171,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!headersFuture.isDone()) {
- }
+ waitTillDone(headersFuture);
}
@Test
@@ -169,15 +179,14 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
ListenableFuture<HttpHeaders> headersFuture = template.headForHeaders(baseUrl + "/get");
headersFuture.addCallback(result -> assertTrue("No Content-Type header",
result.containsKey("Content-Type")), ex -> fail(ex.getMessage()));
- while (!headersFuture.isDone()) {
- }
+ waitTillDone(headersFuture);
}
@Test
public void postForLocation() throws Exception {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
- HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
+ HttpEntity<String> entity = new HttpEntity<>(helloWorld, entityHeaders);
Future<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
URI location = locationFuture.get();
assertEquals("Invalid location", new URI(baseUrl + "/post/1"), location);
@@ -187,7 +196,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
public void postForLocationCallback() throws Exception {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
- HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
+ HttpEntity<String> entity = new HttpEntity<>(helloWorld, entityHeaders);
final URI expected = new URI(baseUrl + "/post/1");
ListenableFuture<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
locationFuture.addCallback(new ListenableFutureCallback<URI>() {
@@ -200,21 +209,19 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!locationFuture.isDone()) {
- }
+ waitTillDone(locationFuture);
}
@Test
public void postForLocationCallbackWithLambdas() throws Exception {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
- HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
+ HttpEntity<String> entity = new HttpEntity<>(helloWorld, entityHeaders);
final URI expected = new URI(baseUrl + "/post/1");
ListenableFuture<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
locationFuture.addCallback(result -> assertEquals("Invalid location", expected, result),
ex -> fail(ex.getMessage()));
- while (!locationFuture.isDone()) {
- }
+ waitTillDone(locationFuture);
}
@Test
@@ -241,8 +248,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!responseEntityFuture.isDone()) {
- }
+ waitTillDone(responseEntityFuture);
}
@Test
@@ -250,10 +256,10 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
ListenableFuture<ResponseEntity<String>> responseEntityFuture =
template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post");
- responseEntityFuture.addCallback(result -> assertEquals("Invalid content", helloWorld, result.getBody()),
+ responseEntityFuture.addCallback(
+ result -> assertEquals("Invalid content", helloWorld, result.getBody()),
ex -> fail(ex.getMessage()));
- while (!responseEntityFuture.isDone()) {
- }
+ waitTillDone(responseEntityFuture);
}
@Test
@@ -277,8 +283,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!responseEntityFuture.isDone()) {
- }
+ waitTillDone(responseEntityFuture);
}
@Test
@@ -300,16 +305,14 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!deletedFuture.isDone()) {
- }
+ waitTillDone(deletedFuture);
}
@Test
public void deleteCallbackWithLambdas() throws Exception {
ListenableFuture<?> deletedFuture = template.delete(new URI(baseUrl + "/delete"));
- deletedFuture.addCallback(result -> assertNull(result), ex -> fail(ex.getMessage()));
- while (!deletedFuture.isDone()) {
- }
+ deletedFuture.addCallback(Assert::assertNull, ex -> fail(ex.getMessage()));
+ waitTillDone(deletedFuture);
}
@Test
@@ -377,8 +380,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertNotNull(ex.getResponseBodyAsString());
}
});
- while (!future.isDone()) {
- }
+ waitTillDone(future);
}
@Test
@@ -391,8 +393,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertNotNull(hcex.getStatusText());
assertNotNull(hcex.getResponseBodyAsString());
});
- while (!future.isDone()) {
- }
+ waitTillDone(future);
}
@Test
@@ -429,8 +430,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertNotNull(hsex.getResponseBodyAsString());
}
});
- while (!future.isDone()) {
- }
+ waitTillDone(future);
}
@Test
@@ -443,8 +443,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertNotNull(hsex.getStatusText());
assertNotNull(hsex.getResponseBodyAsString());
});
- while (!future.isDone()) {
- }
+ waitTillDone(future);
}
@Test
@@ -469,8 +468,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!allowedFuture.isDone()) {
- }
+ waitTillDone(allowedFuture);
}
@Test
@@ -479,8 +477,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
allowedFuture.addCallback(result -> assertEquals("Invalid response",
EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD,HttpMethod.TRACE), result),
ex -> fail(ex.getMessage()));
- while (!allowedFuture.isDone()) {
- }
+ waitTillDone(allowedFuture);
}
@Test
@@ -513,8 +510,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!responseFuture.isDone()) {
- }
+ waitTillDone(responseFuture);
}
@Test
@@ -527,8 +523,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get");
responseFuture.addCallback(result -> assertEquals("Invalid content", helloWorld,
result.getBody()), ex -> fail(ex.getMessage()));
- while (!responseFuture.isDone()) {
- }
+ waitTillDone(responseFuture);
}
@Test
@@ -536,7 +531,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyHeader", "MyValue");
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
- HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
+ HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld, requestHeaders);
Future<ResponseEntity<Void>> resultFuture =
template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
ResponseEntity<Void> result = resultFuture.get();
@@ -550,7 +545,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyHeader", "MyValue");
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
- HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
+ HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld, requestHeaders);
ListenableFuture<ResponseEntity<Void>> resultFuture =
template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
final URI expected =new URI(baseUrl + "/post/1");
@@ -565,8 +560,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
fail(ex.getMessage());
}
});
- while (!resultFuture.isDone()) {
- }
+ waitTillDone(resultFuture);
}
@Test
@@ -574,7 +568,7 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyHeader", "MyValue");
requestHeaders.setContentType(MediaType.TEXT_PLAIN);
- HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
+ HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld, requestHeaders);
ListenableFuture<ResponseEntity<Void>> resultFuture =
template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
final URI expected =new URI(baseUrl + "/post/1");
@@ -582,13 +576,12 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
assertEquals("Invalid location", expected, result.getHeaders().getLocation());
assertFalse(result.hasBody());
}, ex -> fail(ex.getMessage()));
- while (!resultFuture.isDone()) {
- }
+ waitTillDone(resultFuture);
}
@Test
public void multipart() throws Exception {
- MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
+ MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("name 1", "value 1");
parts.add("name 2", "value 2+1");
parts.add("name 2", "value 2+2");
@@ -600,4 +593,73 @@ public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCa
future.get();
}
+ @Test
+ public void getAndInterceptResponse() throws Exception {
+ RequestInterceptor interceptor = new RequestInterceptor();
+ template.setInterceptors(Collections.singletonList(interceptor));
+ ListenableFuture<ResponseEntity<String>> future = template.getForEntity("/get", String.class);
+
+ interceptor.latch.await(5, TimeUnit.SECONDS);
+ assertNotNull(interceptor.response);
+ assertEquals(HttpStatus.OK, interceptor.response.getStatusCode());
+ assertNull(interceptor.exception);
+ assertEquals(helloWorld, future.get().getBody());
+ }
+
+ @Test
+ public void getAndInterceptError() throws Exception {
+ RequestInterceptor interceptor = new RequestInterceptor();
+ template.setInterceptors(Collections.singletonList(interceptor));
+ template.getForEntity("/status/notfound", String.class);
+
+ interceptor.latch.await(5, TimeUnit.SECONDS);
+ assertNotNull(interceptor.response);
+ assertEquals(HttpStatus.NOT_FOUND, interceptor.response.getStatusCode());
+ assertNull(interceptor.exception);
+ }
+
+ private void waitTillDone(ListenableFuture<?> future) {
+ while (!future.isDone()) {
+ }
+ }
+
+
+ private static class RequestInterceptor implements AsyncClientHttpRequestInterceptor {
+
+ private final CountDownLatch latch = new CountDownLatch(1);
+
+ private volatile ClientHttpResponse response;
+
+ private volatile Throwable exception;
+
+ @Override
+ public ListenableFuture<ClientHttpResponse> intercept(HttpRequest request, byte[] body,
+ AsyncClientHttpRequestExecution execution) throws IOException {
+
+ request = new HttpRequestWrapper(request) {
+
+ @Override
+ public URI getURI() {
+ try {
+ return new URI(baseUrl + super.getURI().toString());
+ }
+ catch (URISyntaxException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ };
+
+ ListenableFuture<ClientHttpResponse> future = execution.executeAsync(request, body);
+ future.addCallback(
+ resp -> {
+ response = resp;
+ this.latch.countDown();
+ },
+ ex -> {
+ exception = ex;
+ this.latch.countDown();
+ });
+ return future;
+ }
+ }
}
diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java
index 149340b6..d5f00fc2 100644
--- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java
+++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,11 +20,16 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
+import java.util.ArrayList;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeName;
import org.junit.Test;
+import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
@@ -32,6 +37,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.MappingJacksonValue;
@@ -215,7 +221,7 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase {
bean.setWith2("with");
bean.setWithout("without");
HttpEntity<MySampleBean> entity = new HttpEntity<MySampleBean>(bean, entityHeaders);
- String s = template.postForObject(baseUrl + "/jsonpost", entity, String.class, "post");
+ String s = template.postForObject(baseUrl + "/jsonpost", entity, String.class);
assertTrue(s.contains("\"with1\":\"with\""));
assertTrue(s.contains("\"with2\":\"with\""));
assertTrue(s.contains("\"without\":\"without\""));
@@ -229,7 +235,7 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase {
MappingJacksonValue jacksonValue = new MappingJacksonValue(bean);
jacksonValue.setSerializationView(MyJacksonView1.class);
HttpEntity<MappingJacksonValue> entity = new HttpEntity<MappingJacksonValue>(jacksonValue, entityHeaders);
- String s = template.postForObject(baseUrl + "/jsonpost", entity, String.class, "post");
+ String s = template.postForObject(baseUrl + "/jsonpost", entity, String.class);
assertTrue(s.contains("\"with1\":\"with\""));
assertFalse(s.contains("\"with2\":\"with\""));
assertFalse(s.contains("\"without\":\"without\""));
@@ -243,6 +249,21 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase {
assertEquals("Invalid content", helloWorld, s);
}
+ @Test // SPR-13154
+ public void jsonPostForObjectWithJacksonTypeInfoList() throws URISyntaxException {
+ List<ParentClass> list = new ArrayList<>();
+ list.add(new Foo("foo"));
+ list.add(new Bar("bar"));
+ ParameterizedTypeReference<?> typeReference = new ParameterizedTypeReference<List<ParentClass>>() {};
+ RequestEntity<List<ParentClass>> entity = RequestEntity
+ .post(new URI(baseUrl + "/jsonpost"))
+ .contentType(new MediaType("application", "json", Charset.forName("UTF-8")))
+ .body(list, typeReference.getType());
+ String content = template.exchange(entity, String.class).getBody();
+ assertTrue(content.contains("\"type\":\"foo\""));
+ assertTrue(content.contains("\"type\":\"bar\""));
+ }
+
public interface MyJacksonView1 {};
public interface MyJacksonView2 {};
@@ -290,4 +311,47 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase {
}
}
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
+ public static class ParentClass {
+
+ private String parentProperty;
+
+ public ParentClass() {
+ }
+
+ public ParentClass(String parentProperty) {
+ this.parentProperty = parentProperty;
+ }
+
+ public String getParentProperty() {
+ return parentProperty;
+ }
+
+ public void setParentProperty(String parentProperty) {
+ this.parentProperty = parentProperty;
+ }
+ }
+
+ @JsonTypeName("foo")
+ public static class Foo extends ParentClass {
+
+ public Foo() {
+ }
+
+ public Foo(String parentProperty) {
+ super(parentProperty);
+ }
+ }
+
+ @JsonTypeName("bar")
+ public static class Bar extends ParentClass {
+
+ public Bar() {
+ }
+
+ public Bar(String parentProperty) {
+ super(parentProperty);
+ }
+ }
+
}
diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java
index 1ecfc48e..5674ad55 100644
--- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java
+++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateTests.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -49,6 +49,7 @@ import static org.mockito.BDDMockito.*;
/**
* @author Arjen Poutsma
+ * @author Rossen Stoyanchev
*/
@SuppressWarnings("unchecked")
public class RestTemplateTests {
@@ -135,7 +136,7 @@ public class RestTemplateTests {
given(response.getStatusCode()).willReturn(status);
given(response.getStatusText()).willReturn(status.getReasonPhrase());
- Map<String, String> vars = new HashMap<String, String>(2);
+ Map<String, String> vars = new HashMap<>(2);
vars.put("first", null);
vars.put("last", "foo");
template.execute("http://example.com/{first}-{last}", HttpMethod.GET, null, null, vars);
@@ -278,7 +279,7 @@ public class RestTemplateTests {
given(response.getHeaders()).willReturn(new HttpHeaders());
given(response.getBody()).willReturn(null);
- Map<String, String> uriVariables = new HashMap<String, String>(2);
+ Map<String, String> uriVariables = new HashMap<>(2);
uriVariables.put("hotel", "1");
uriVariables.put("publicpath", "pics/logo.png");
uriVariables.put("scale", "150x150");
@@ -351,7 +352,7 @@ public class RestTemplateTests {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.setContentType(contentType);
- HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
+ HttpEntity<String> entity = new HttpEntity<>(helloWorld, entityHeaders);
URI result = template.postForLocation("http://example.com", entity);
assertEquals("Invalid POST result", expected, result);
@@ -379,7 +380,7 @@ public class RestTemplateTests {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.set("MyHeader", "MyValue");
- HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
+ HttpEntity<String> entity = new HttpEntity<>(helloWorld, entityHeaders);
URI result = template.postForLocation("http://example.com", entity);
assertEquals("Invalid POST result", expected, result);
@@ -622,21 +623,27 @@ public class RestTemplateTests {
verify(response).close();
}
+ // Issue: SPR-9325, SPR-13860
+
@Test
public void ioException() throws Exception {
+ String url = "http://example.com/resource?access_token=123";
+
given(converter.canRead(String.class, null)).willReturn(true);
MediaType mediaType = new MediaType("foo", "bar");
given(converter.getSupportedMediaTypes()).willReturn(Collections.singletonList(mediaType));
- given(requestFactory.createRequest(new URI("http://example.com/resource"), HttpMethod.GET)).willReturn(request);
+ given(requestFactory.createRequest(new URI(url), HttpMethod.GET)).willReturn(request);
given(request.getHeaders()).willReturn(new HttpHeaders());
- given(request.execute()).willThrow(new IOException());
+ given(request.execute()).willThrow(new IOException("Socket failure"));
try {
- template.getForObject("http://example.com/resource", String.class);
+ template.getForObject(url, String.class);
fail("RestClientException expected");
}
catch (ResourceAccessException ex) {
- // expected
+ assertEquals("I/O error on GET request for \"http://example.com/resource\": " +
+ "Socket failure; nested exception is java.io.IOException: Socket failure",
+ ex.getMessage());
}
}
@@ -669,7 +676,7 @@ public class RestTemplateTests {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.set("MyHeader", "MyValue");
- HttpEntity<String> requestEntity = new HttpEntity<String>(body, entityHeaders);
+ HttpEntity<String> requestEntity = new HttpEntity<>(body, entityHeaders);
ResponseEntity<Integer> result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, Integer.class);
assertEquals("Invalid POST result", expected, result.getBody());
assertEquals("Invalid Content-Type", MediaType.TEXT_PLAIN, result.getHeaders().getContentType());
@@ -692,9 +699,9 @@ public class RestTemplateTests {
given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).willReturn(this.request);
HttpHeaders requestHeaders = new HttpHeaders();
given(this.request.getHeaders()).willReturn(requestHeaders);
- given(converter.canWrite(String.class, null)).willReturn(true);
+ given(converter.canWrite(String.class, String.class, null)).willReturn(true);
String requestBody = "Hello World";
- converter.write(requestBody, null, this.request);
+ converter.write(requestBody, String.class, null, this.request);
given(this.request.execute()).willReturn(response);
given(errorHandler.hasError(response)).willReturn(false);
List<Integer> expected = Collections.singletonList(42);
@@ -703,7 +710,7 @@ public class RestTemplateTests {
responseHeaders.setContentLength(10);
given(response.getStatusCode()).willReturn(HttpStatus.OK);
given(response.getHeaders()).willReturn(responseHeaders);
- given(response.getBody()).willReturn(new ByteArrayInputStream(new Integer(42).toString().getBytes()));
+ given(response.getBody()).willReturn(new ByteArrayInputStream(Integer.toString(42).getBytes()));
given(converter.canRead(intList.getType(), null, MediaType.TEXT_PLAIN)).willReturn(true);
given(converter.read(eq(intList.getType()), eq(null), any(HttpInputMessage.class))).willReturn(expected);
given(response.getStatusCode()).willReturn(HttpStatus.OK);
@@ -713,7 +720,7 @@ public class RestTemplateTests {
HttpHeaders entityHeaders = new HttpHeaders();
entityHeaders.set("MyHeader", "MyValue");
- HttpEntity<String> requestEntity = new HttpEntity<String>(requestBody, entityHeaders);
+ HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, entityHeaders);
ResponseEntity<List<Integer>> result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, intList);
assertEquals("Invalid POST result", expected, result.getBody());
assertEquals("Invalid Content-Type", MediaType.TEXT_PLAIN, result.getHeaders().getContentType());
diff --git a/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java b/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java
index ef1afaad..603e2642 100644
--- a/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/request/ServletRequestAttributesTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,8 +78,7 @@ public class ServletRequestAttributesTests {
request.setSession(session);
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
- Object value = session.getAttribute(KEY);
- assertSame(VALUE, value);
+ assertSame(VALUE, session.getAttribute(KEY));
}
@Test
@@ -89,11 +88,11 @@ public class ServletRequestAttributesTests {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setSession(session);
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ assertSame(VALUE, attrs.getAttribute(KEY, RequestAttributes.SCOPE_SESSION));
attrs.requestCompleted();
request.close();
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_SESSION);
- Object value = session.getAttribute(KEY);
- assertSame(VALUE, value);
+ assertSame(VALUE, session.getAttribute(KEY));
}
@Test
@@ -104,8 +103,7 @@ public class ServletRequestAttributesTests {
request.setSession(session);
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
- Object value = session.getAttribute(KEY);
- assertSame(VALUE, value);
+ assertSame(VALUE, session.getAttribute(KEY));
}
@Test
@@ -115,11 +113,11 @@ public class ServletRequestAttributesTests {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setSession(session);
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
+ assertSame(VALUE, attrs.getAttribute(KEY, RequestAttributes.SCOPE_GLOBAL_SESSION));
attrs.requestCompleted();
request.close();
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
- Object value = session.getAttribute(KEY);
- assertSame(VALUE, value);
+ assertSame(VALUE, session.getAttribute(KEY));
}
@Test
diff --git a/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java b/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java
index 3832ae3a..a5a8b07c 100644
--- a/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/request/ServletWebRequestHttpMethodsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.springframework.web.context.request;
+import static org.junit.Assert.*;
+
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@@ -32,8 +34,6 @@ import org.junit.runners.Parameterized.Parameters;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
-import static org.junit.Assert.*;
-
/**
* Parameterized tests for ServletWebRequest
* @author Juergen Hoeller
@@ -145,6 +145,18 @@ public class ServletWebRequestHttpMethodsTests {
}
@Test
+ public void checkNotModifiedETagWithSeparatorChars() {
+ String eTag = "\"Foo, Bar\"";
+ servletRequest.addHeader("If-None-Match", eTag);
+
+ assertTrue(request.checkNotModified(eTag));
+
+ assertEquals(304, servletResponse.getStatus());
+ assertEquals(eTag, servletResponse.getHeader("ETag"));
+ }
+
+
+ @Test
public void checkModifiedETag() {
String currentETag = "\"Foo\"";
String oldEtag = "Bar";
@@ -204,6 +216,7 @@ public class ServletWebRequestHttpMethodsTests {
assertEquals(dateFormat.format(currentDate.getTime()), servletResponse.getHeader("Last-Modified"));
}
+ // SPR-14224
@Test
public void checkNotModifiedETagAndModifiedTimestamp() {
String eTag = "\"Foo\"";
@@ -212,9 +225,9 @@ public class ServletWebRequestHttpMethodsTests {
long oneMinuteAgo = currentEpoch - (1000 * 60);
servletRequest.addHeader("If-Modified-Since", oneMinuteAgo);
- assertFalse(request.checkNotModified(eTag, currentEpoch));
+ assertTrue(request.checkNotModified(eTag, currentEpoch));
- assertEquals(200, servletResponse.getStatus());
+ assertEquals(304, servletResponse.getStatus());
assertEquals(eTag, servletResponse.getHeader("ETag"));
assertEquals(dateFormat.format(currentEpoch), servletResponse.getHeader("Last-Modified"));
}
@@ -293,4 +306,28 @@ public class ServletWebRequestHttpMethodsTests {
assertEquals(dateFormat.format(epochTime), servletResponse.getHeader("Last-Modified"));
}
+ @Test
+ public void checkNotModifiedTimestampConditionalPut() throws Exception {
+ long currentEpoch = currentDate.getTime();
+ long oneMinuteAgo = currentEpoch - (1000 * 60);
+ servletRequest.setMethod("PUT");
+ servletRequest.addHeader("If-UnModified-Since", currentEpoch);
+
+ assertFalse(request.checkNotModified(oneMinuteAgo));
+ assertEquals(200, servletResponse.getStatus());
+ assertEquals(null, servletResponse.getHeader("Last-Modified"));
+ }
+
+ @Test
+ public void checkNotModifiedTimestampConditionalPutConflict() throws Exception {
+ long currentEpoch = currentDate.getTime();
+ long oneMinuteAgo = currentEpoch - (1000 * 60);
+ servletRequest.setMethod("PUT");
+ servletRequest.addHeader("If-UnModified-Since", oneMinuteAgo);
+
+ assertTrue(request.checkNotModified(currentEpoch));
+ assertEquals(412, servletResponse.getStatus());
+ assertEquals(null, servletResponse.getHeader("Last-Modified"));
+ }
+
}
diff --git a/spring-web/src/test/java/org/springframework/web/context/request/SessionScopeTests.java b/spring-web/src/test/java/org/springframework/web/context/request/SessionScopeTests.java
index ab198238..a44318fc 100644
--- a/spring-web/src/test/java/org/springframework/web/context/request/SessionScopeTests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/request/SessionScopeTests.java
@@ -172,6 +172,11 @@ public class SessionScopeTests {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
}
+
+ @Override
+ public boolean requiresDestruction(Object bean) {
+ return true;
+ }
}
@@ -195,6 +200,11 @@ public class SessionScopeTests {
((BeanNameAware) bean).setBeanName(null);
}
}
+
+ @Override
+ public boolean requiresDestruction(Object bean) {
+ return true;
+ }
}
}
diff --git a/spring-web/src/test/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequestTests.java b/spring-web/src/test/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequestTests.java
index 50d84230..2596796e 100644
--- a/spring-web/src/test/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequestTests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/request/async/StandardServletAsyncWebRequestTests.java
@@ -147,7 +147,7 @@ public class StandardServletAsyncWebRequestTests {
}
// SPR-13292
-
+
@Test
public void onCompletionHandlerAfterOnErrorEvent() throws Exception {
Runnable handler = mock(Runnable.class);
diff --git a/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java b/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java
index c763eeec..d4a2ad47 100644
--- a/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/request/async/WebAsyncManagerTests.java
@@ -150,8 +150,9 @@ public class WebAsyncManagerTests {
try {
this.asyncManager.startCallableProcessing(task);
fail("Expected Exception");
- }catch(Exception e) {
- assertEquals(exception, e);
+ }
+ catch (Exception ex) {
+ assertEquals(exception, ex);
}
assertFalse(this.asyncManager.hasConcurrentResult());
@@ -162,7 +163,6 @@ public class WebAsyncManagerTests {
@Test
public void startCallableProcessingPreProcessException() throws Exception {
-
Callable<Object> task = new StubCallable(21);
Exception exception = new Exception();
@@ -183,7 +183,6 @@ public class WebAsyncManagerTests {
@Test
public void startCallableProcessingPostProcessException() throws Exception {
-
Callable<Object> task = new StubCallable(21);
Exception exception = new Exception();
@@ -205,7 +204,6 @@ public class WebAsyncManagerTests {
@Test
public void startCallableProcessingPostProcessContinueAfterException() throws Exception {
-
Callable<Object> task = new StubCallable(21);
Exception exception = new Exception();
@@ -231,7 +229,6 @@ public class WebAsyncManagerTests {
@Test
public void startCallableProcessingWithAsyncTask() throws Exception {
-
AsyncTaskExecutor executor = mock(AsyncTaskExecutor.class);
given(this.asyncWebRequest.getNativeRequest(HttpServletRequest.class)).willReturn(this.servletRequest);
@@ -259,7 +256,6 @@ public class WebAsyncManagerTests {
@Test
public void startDeferredResultProcessing() throws Exception {
-
DeferredResult<String> deferredResult = new DeferredResult<String>(1000L);
String concurrentResult = "abc";
@@ -282,7 +278,6 @@ public class WebAsyncManagerTests {
@Test
public void startDeferredResultProcessingBeforeConcurrentHandlingException() throws Exception {
-
DeferredResult<Integer> deferredResult = new DeferredResult<Integer>();
Exception exception = new Exception();
@@ -295,7 +290,7 @@ public class WebAsyncManagerTests {
this.asyncManager.startDeferredResultProcessing(deferredResult);
fail("Expected Exception");
}
- catch(Exception success) {
+ catch (Exception success) {
assertEquals(exception, success);
}
@@ -328,7 +323,6 @@ public class WebAsyncManagerTests {
@Test
public void startDeferredResultProcessingPostProcessException() throws Exception {
-
DeferredResult<Integer> deferredResult = new DeferredResult<Integer>();
Exception exception = new Exception();
@@ -371,6 +365,7 @@ public class WebAsyncManagerTests {
verify(this.asyncWebRequest).dispatch();
}
+
private final class StubCallable implements Callable<Object> {
private Object value;
@@ -388,6 +383,7 @@ public class WebAsyncManagerTests {
}
}
+
@SuppressWarnings("serial")
private static class SyncTaskExecutor extends SimpleAsyncTaskExecutor {
diff --git a/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java b/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java
index a712e525..dd56ff00 100644
--- a/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java
+++ b/spring-web/src/test/java/org/springframework/web/context/support/Spr8510Tests.java
@@ -49,7 +49,8 @@ public class Spr8510Tests {
try {
cll.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
// assert that an attempt was made to load the correct XML
assertTrue(t.getMessage(), t.getMessage().endsWith(
"Could not open ServletContext resource [/programmatic.xml]"));
@@ -75,7 +76,8 @@ public class Spr8510Tests {
try {
cll.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
// assert that an attempt was made to load the correct XML
assertTrue(t.getMessage(), t.getMessage().endsWith(
"Could not open ServletContext resource [/from-init-param.xml]"));
@@ -98,7 +100,8 @@ public class Spr8510Tests {
try {
cll.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
// assert that an attempt was made to load the correct XML
assertTrue(t.getMessage().endsWith(
"Could not open ServletContext resource [/from-init-param.xml]"));
@@ -125,7 +128,8 @@ public class Spr8510Tests {
try {
cll.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
// assert that an attempt was made to load the correct XML
System.out.println(t.getMessage());
assertTrue(t.getMessage().endsWith(
@@ -150,7 +154,8 @@ public class Spr8510Tests {
try {
cll.contextInitialized(new ServletContextEvent(sc));
fail("expected exception");
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
// assert that an attempt was made to load the correct XML
System.out.println(t.getMessage());
assertTrue(t.getMessage().endsWith(
diff --git a/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java b/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java
index 8d3651c5..32f68af3 100644
--- a/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java
+++ b/spring-web/src/test/java/org/springframework/web/cors/CorsConfigurationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -176,7 +176,7 @@ public class CorsConfigurationTests {
@Test
public void checkMethodAllowed() {
- assertEquals(Arrays.asList(HttpMethod.GET), config.checkHttpMethod(HttpMethod.GET));
+ assertEquals(Arrays.asList(HttpMethod.GET, HttpMethod.HEAD), config.checkHttpMethod(HttpMethod.GET));
config.addAllowedMethod("GET");
assertEquals(Arrays.asList(HttpMethod.GET), config.checkHttpMethod(HttpMethod.GET));
config.addAllowedMethod("POST");
@@ -189,7 +189,7 @@ public class CorsConfigurationTests {
assertNull(config.checkHttpMethod(null));
assertNull(config.checkHttpMethod(HttpMethod.DELETE));
config.setAllowedMethods(new ArrayList<>());
- assertNull(config.checkHttpMethod(HttpMethod.HEAD));
+ assertNull(config.checkHttpMethod(HttpMethod.POST));
}
@Test
diff --git a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java
index 56ab6166..30a93e30 100644
--- a/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java
+++ b/spring-web/src/test/java/org/springframework/web/cors/DefaultCorsProcessorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -171,7 +171,7 @@ public class DefaultCorsProcessorTests {
this.conf.addAllowedOrigin("*");
this.processor.processRequest(this.conf, request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
- assertEquals("GET", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
+ assertEquals("GET,HEAD", response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
}
@Test
diff --git a/spring-web/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java b/spring-web/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java
index 64392f91..5f0006c9 100644
--- a/spring-web/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java
+++ b/spring-web/src/test/java/org/springframework/web/filter/CharacterEncodingFilterTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -145,4 +145,26 @@ public class CharacterEncodingFilterTests {
verify(filterChain).doFilter(request, response);
}
+ // SPR-14240
+ @Test
+ public void setForceEncodingOnRequestOnly() throws Exception {
+ HttpServletRequest request = mock(HttpServletRequest.class);
+ request.setCharacterEncoding(ENCODING);
+ given(request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE)).willReturn(null);
+ given(request.getAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX)).willReturn(null);
+
+ HttpServletResponse response = mock(HttpServletResponse.class);
+ FilterChain filterChain = mock(FilterChain.class);
+
+ CharacterEncodingFilter filter = new CharacterEncodingFilter(ENCODING, true, false);
+ filter.init(new MockFilterConfig(FILTER_NAME));
+ filter.doFilter(request, response, filterChain);
+
+ verify(request).setAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX, Boolean.TRUE);
+ verify(request).removeAttribute(FILTER_NAME + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX);
+ verify(request, times(2)).setCharacterEncoding(ENCODING);
+ verify(response, never()).setCharacterEncoding(ENCODING);
+ verify(filterChain).doFilter(request, response);
+ }
+
}
diff --git a/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java b/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java
new file mode 100644
index 00000000..56d93f8c
--- /dev/null
+++ b/spring-web/src/test/java/org/springframework/web/filter/ForwardedHeaderFilterTests.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.web.filter;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.mock.web.test.MockFilterChain;
+import org.springframework.mock.web.test.MockHttpServletRequest;
+import org.springframework.mock.web.test.MockHttpServletResponse;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for {@link ForwardedHeaderFilter}.
+ * @author Rossen Stoyanchev
+ * @author Eddú Meléndez
+ */
+public class ForwardedHeaderFilterTests {
+
+ private static final String X_FORWARDED_PROTO = "x-forwarded-proto"; // SPR-14372 (case insensitive)
+ private static final String X_FORWARDED_HOST = "x-forwarded-host";
+ private static final String X_FORWARDED_PORT = "x-forwarded-port";
+ private static final String X_FORWARDED_PREFIX = "x-forwarded-prefix";
+
+
+ private final ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
+
+ private MockHttpServletRequest request;
+
+ private MockFilterChain filterChain;
+
+
+ @Before
+ @SuppressWarnings("serial")
+ public void setUp() throws Exception {
+ this.request = new MockHttpServletRequest();
+ this.request.setScheme("http");
+ this.request.setServerName("localhost");
+ this.request.setServerPort(80);
+ this.filterChain = new MockFilterChain(new HttpServlet() {});
+ }
+
+
+ @Test
+ public void contextPathEmpty() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "");
+ assertEquals("", filterAndGetContextPath());
+ }
+
+ @Test
+ public void contextPathWithTrailingSlash() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/foo/bar/");
+ assertEquals("/foo/bar", filterAndGetContextPath());
+ }
+
+ @Test
+ public void contextPathWithTrailingSlashes() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/foo/bar/baz///");
+ assertEquals("/foo/bar/baz", filterAndGetContextPath());
+ }
+
+ @Test
+ public void requestUri() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/");
+ this.request.setContextPath("/app");
+ this.request.setRequestURI("/app/path");
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+
+ assertEquals("", actual.getContextPath());
+ assertEquals("/path", actual.getRequestURI());
+ }
+
+ @Test
+ public void requestUriWithTrailingSlash() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/");
+ this.request.setContextPath("/app");
+ this.request.setRequestURI("/app/path/");
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+
+ assertEquals("", actual.getContextPath());
+ assertEquals("/path/", actual.getRequestURI());
+ }
+ @Test
+ public void requestUriEqualsContextPath() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/");
+ this.request.setContextPath("/app");
+ this.request.setRequestURI("/app");
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+
+ assertEquals("", actual.getContextPath());
+ assertEquals("/", actual.getRequestURI());
+ }
+
+ @Test
+ public void requestUriRootUrl() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/");
+ this.request.setContextPath("/app");
+ this.request.setRequestURI("/app/");
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+
+ assertEquals("", actual.getContextPath());
+ assertEquals("/", actual.getRequestURI());
+ }
+
+ @Test
+ public void caseInsensitiveForwardedPrefix() throws Exception {
+ this.request = new MockHttpServletRequest() {
+
+ // Make it case-sensitive (SPR-14372)
+
+ @Override
+ public String getHeader(String header) {
+ Enumeration<String> names = getHeaderNames();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ if (name.equals(header)) {
+ return super.getHeader(header);
+ }
+ }
+ return null;
+ }
+ };
+ this.request.addHeader(X_FORWARDED_PREFIX, "/prefix");
+ this.request.setRequestURI("/path");
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+
+ assertEquals("/prefix/path", actual.getRequestURI());
+ }
+
+ @Test
+ public void shouldFilter() throws Exception {
+ testShouldFilter("Forwarded");
+ testShouldFilter(X_FORWARDED_HOST);
+ testShouldFilter(X_FORWARDED_PORT);
+ testShouldFilter(X_FORWARDED_PROTO);
+ }
+
+ @Test
+ public void shouldNotFilter() throws Exception {
+ assertTrue(this.filter.shouldNotFilter(new MockHttpServletRequest()));
+ }
+
+ @Test
+ public void forwardedRequest() throws Exception {
+ this.request.setRequestURI("/mvc-showcase");
+ this.request.addHeader(X_FORWARDED_PROTO, "https");
+ this.request.addHeader(X_FORWARDED_HOST, "84.198.58.199");
+ this.request.addHeader(X_FORWARDED_PORT, "443");
+ this.request.addHeader("foo", "bar");
+
+ this.filter.doFilter(this.request, new MockHttpServletResponse(), this.filterChain);
+ HttpServletRequest actual = (HttpServletRequest) this.filterChain.getRequest();
+
+ assertEquals("https://84.198.58.199/mvc-showcase", actual.getRequestURL().toString());
+ assertEquals("https", actual.getScheme());
+ assertEquals("84.198.58.199", actual.getServerName());
+ assertEquals(443, actual.getServerPort());
+ assertTrue(actual.isSecure());
+
+ assertNull(actual.getHeader(X_FORWARDED_PROTO));
+ assertNull(actual.getHeader(X_FORWARDED_HOST));
+ assertNull(actual.getHeader(X_FORWARDED_PORT));
+ assertEquals("bar", actual.getHeader("foo"));
+ }
+
+ @Test
+ public void requestUriWithForwardedPrefix() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/prefix");
+ this.request.setRequestURI("/mvc-showcase");
+
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+ assertEquals("http://localhost/prefix/mvc-showcase", actual.getRequestURL().toString());
+ }
+
+ @Test
+ public void requestUriWithForwardedPrefixTrailingSlash() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/prefix/");
+ this.request.setRequestURI("/mvc-showcase");
+
+ HttpServletRequest actual = filterAndGetWrappedRequest();
+ assertEquals("http://localhost/prefix/mvc-showcase", actual.getRequestURL().toString());
+ }
+
+ @Test
+ public void contextPathWithForwardedPrefix() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/prefix");
+ this.request.setContextPath("/mvc-showcase");
+
+ String actual = filterAndGetContextPath();
+ assertEquals("/prefix", actual);
+ }
+
+ @Test
+ public void contextPathWithForwardedPrefixTrailingSlash() throws Exception {
+ this.request.addHeader(X_FORWARDED_PREFIX, "/prefix/");
+ this.request.setContextPath("/mvc-showcase");
+
+ String actual = filterAndGetContextPath();
+ assertEquals("/prefix", actual);
+ }
+
+ private String filterAndGetContextPath() throws ServletException, IOException {
+ return filterAndGetWrappedRequest().getContextPath();
+ }
+
+ private HttpServletRequest filterAndGetWrappedRequest() throws ServletException, IOException {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ this.filter.doFilterInternal(this.request, response, this.filterChain);
+ return (HttpServletRequest) this.filterChain.getRequest();
+ }
+
+ private void testShouldFilter(String headerName) throws ServletException {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.addHeader(headerName, "1");
+ assertFalse(this.filter.shouldNotFilter(request));
+ }
+
+}
diff --git a/spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java b/spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java
index 0c5af485..893501b2 100644
--- a/spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java
+++ b/spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -74,6 +74,26 @@ public class ShallowEtagHeaderFilterTests {
}
@Test
+ public void filterNoMatchWeakETag() throws Exception {
+ this.filter.setWriteWeakETag(true);
+ final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ final byte[] responseBody = "Hello World".getBytes("UTF-8");
+ FilterChain filterChain = (filterRequest, filterResponse) -> {
+ assertEquals("Invalid request passed", request, filterRequest);
+ ((HttpServletResponse) filterResponse).setStatus(HttpServletResponse.SC_OK);
+ FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
+ };
+ filter.doFilter(request, response, filterChain);
+
+ assertEquals("Invalid status", 200, response.getStatus());
+ assertEquals("Invalid ETag header", "W/\"0b10a8db164e0754105b7a99be72e3fe5\"", response.getHeader("ETag"));
+ assertTrue("Invalid Content-Length header", response.getContentLength() > 0);
+ assertArrayEquals("Invalid content", responseBody, response.getContentAsByteArray());
+ }
+
+ @Test
public void filterMatch() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
String etag = "\"0b10a8db164e0754105b7a99be72e3fe5\"";
@@ -95,6 +115,27 @@ public class ShallowEtagHeaderFilterTests {
}
@Test
+ public void filterMatchWeakEtag() throws Exception {
+ final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
+ String etag = "\"0b10a8db164e0754105b7a99be72e3fe5\"";
+ request.addHeader("If-None-Match", "W/" + etag);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ FilterChain filterChain = (filterRequest, filterResponse) -> {
+ assertEquals("Invalid request passed", request, filterRequest);
+ byte[] responseBody = "Hello World".getBytes("UTF-8");
+ FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
+ filterResponse.setContentLength(responseBody.length);
+ };
+ filter.doFilter(request, response, filterChain);
+
+ assertEquals("Invalid status", 304, response.getStatus());
+ assertEquals("Invalid ETag header", "\"0b10a8db164e0754105b7a99be72e3fe5\"", response.getHeader("ETag"));
+ assertFalse("Response has Content-Length header", response.containsHeader("Content-Length"));
+ assertArrayEquals("Invalid content", new byte[0], response.getContentAsByteArray());
+ }
+
+ @Test
public void filterWriter() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
String etag = "\"0b10a8db164e0754105b7a99be72e3fe5\"";
diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessorTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessorTests.java
index 21fc00e8..2010ba9d 100644
--- a/spring-web/src/test/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessorTests.java
+++ b/spring-web/src/test/java/org/springframework/web/method/annotation/ModelAttributeMethodProcessorTests.java
@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
+import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.tests.sample.beans.TestBean;
import org.springframework.validation.BindException;
@@ -51,56 +52,56 @@ import static org.mockito.BDDMockito.*;
*/
public class ModelAttributeMethodProcessorTests {
+ private NativeWebRequest request;
+
+ private ModelAndViewContainer container;
+
private ModelAttributeMethodProcessor processor;
private MethodParameter paramNamedValidModelAttr;
-
private MethodParameter paramErrors;
-
private MethodParameter paramInt;
-
private MethodParameter paramModelAttr;
-
+ private MethodParameter paramBindingDisabledAttr;
private MethodParameter paramNonSimpleType;
private MethodParameter returnParamNamedModelAttr;
-
private MethodParameter returnParamNonSimpleType;
- private ModelAndViewContainer mavContainer;
-
- private NativeWebRequest webRequest;
@Before
public void setUp() throws Exception {
- processor = new ModelAttributeMethodProcessor(false);
+ this.request = new ServletWebRequest(new MockHttpServletRequest());
+ this.container = new ModelAndViewContainer();
+ this.processor = new ModelAttributeMethodProcessor(false);
Method method = ModelAttributeHandler.class.getDeclaredMethod("modelAttribute",
- TestBean.class, Errors.class, int.class, TestBean.class, TestBean.class);
+ TestBean.class, Errors.class, int.class, TestBean.class,
+ TestBean.class, TestBean.class);
- paramNamedValidModelAttr = new MethodParameter(method, 0);
- paramErrors = new MethodParameter(method, 1);
- paramInt = new MethodParameter(method, 2);
- paramModelAttr = new MethodParameter(method, 3);
- paramNonSimpleType = new MethodParameter(method, 4);
+ this.paramNamedValidModelAttr = new SynthesizingMethodParameter(method, 0);
+ this.paramErrors = new SynthesizingMethodParameter(method, 1);
+ this.paramInt = new SynthesizingMethodParameter(method, 2);
+ this.paramModelAttr = new SynthesizingMethodParameter(method, 3);
+ this.paramBindingDisabledAttr = new SynthesizingMethodParameter(method, 4);
+ this.paramNonSimpleType = new SynthesizingMethodParameter(method, 5);
- returnParamNamedModelAttr = new MethodParameter(getClass().getDeclaredMethod("annotatedReturnValue"), -1);
- returnParamNonSimpleType = new MethodParameter(getClass().getDeclaredMethod("notAnnotatedReturnValue"), -1);
+ method = getClass().getDeclaredMethod("annotatedReturnValue");
+ this.returnParamNamedModelAttr = new MethodParameter(method, -1);
- mavContainer = new ModelAndViewContainer();
-
- webRequest = new ServletWebRequest(new MockHttpServletRequest());
+ method = getClass().getDeclaredMethod("notAnnotatedReturnValue");
+ this.returnParamNonSimpleType = new MethodParameter(method, -1);
}
+
@Test
public void supportedParameters() throws Exception {
- // Only @ModelAttribute arguments
- assertTrue(processor.supportsParameter(paramNamedValidModelAttr));
- assertTrue(processor.supportsParameter(paramModelAttr));
+ assertTrue(this.processor.supportsParameter(this.paramNamedValidModelAttr));
+ assertTrue(this.processor.supportsParameter(this.paramModelAttr));
- assertFalse(processor.supportsParameter(paramErrors));
- assertFalse(processor.supportsParameter(paramInt));
- assertFalse(processor.supportsParameter(paramNonSimpleType));
+ assertFalse(this.processor.supportsParameter(this.paramErrors));
+ assertFalse(this.processor.supportsParameter(this.paramInt));
+ assertFalse(this.processor.supportsParameter(this.paramNonSimpleType));
}
@Test
@@ -108,135 +109,162 @@ public class ModelAttributeMethodProcessorTests {
processor = new ModelAttributeMethodProcessor(true);
// Only non-simple types, even if not annotated
- assertTrue(processor.supportsParameter(paramNamedValidModelAttr));
- assertTrue(processor.supportsParameter(paramErrors));
- assertTrue(processor.supportsParameter(paramModelAttr));
- assertTrue(processor.supportsParameter(paramNonSimpleType));
+ assertTrue(this.processor.supportsParameter(this.paramNamedValidModelAttr));
+ assertTrue(this.processor.supportsParameter(this.paramErrors));
+ assertTrue(this.processor.supportsParameter(this.paramModelAttr));
+ assertTrue(this.processor.supportsParameter(this.paramNonSimpleType));
- assertFalse(processor.supportsParameter(paramInt));
+ assertFalse(this.processor.supportsParameter(this.paramInt));
}
@Test
public void supportedReturnTypes() throws Exception {
processor = new ModelAttributeMethodProcessor(false);
- assertTrue(processor.supportsReturnType(returnParamNamedModelAttr));
- assertFalse(processor.supportsReturnType(returnParamNonSimpleType));
+ assertTrue(this.processor.supportsReturnType(returnParamNamedModelAttr));
+ assertFalse(this.processor.supportsReturnType(returnParamNonSimpleType));
}
@Test
public void supportedReturnTypesInDefaultResolutionMode() throws Exception {
processor = new ModelAttributeMethodProcessor(true);
- assertTrue(processor.supportsReturnType(returnParamNamedModelAttr));
- assertTrue(processor.supportsReturnType(returnParamNonSimpleType));
+ assertTrue(this.processor.supportsReturnType(returnParamNamedModelAttr));
+ assertTrue(this.processor.supportsReturnType(returnParamNonSimpleType));
}
@Test
public void bindExceptionRequired() throws Exception {
- assertTrue(processor.isBindExceptionRequired(null, paramNonSimpleType));
+ assertTrue(this.processor.isBindExceptionRequired(null, this.paramNonSimpleType));
+ assertFalse(this.processor.isBindExceptionRequired(null, this.paramNamedValidModelAttr));
}
@Test
- public void bindExceptionNotRequired() throws Exception {
- assertFalse(processor.isBindExceptionRequired(null, paramNamedValidModelAttr));
+ public void resolveArgumentFromModel() throws Exception {
+ testGetAttributeFromModel("attrName", this.paramNamedValidModelAttr);
+ testGetAttributeFromModel("testBean", this.paramModelAttr);
+ testGetAttributeFromModel("testBean", this.paramNonSimpleType);
}
@Test
- public void resovleArgumentFromModel() throws Exception {
- getAttributeFromModel("attrName", paramNamedValidModelAttr);
- getAttributeFromModel("testBean", paramModelAttr);
- getAttributeFromModel("testBean", paramNonSimpleType);
+ public void resovleArgumentViaDefaultConstructor() throws Exception {
+ WebDataBinder dataBinder = new WebRequestDataBinder(null);
+ WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
+ given(factory.createBinder(anyObject(), notNull(), eq("attrName"))).willReturn(dataBinder);
+
+ this.processor.resolveArgument(this.paramNamedValidModelAttr, this.container, this.request, factory);
+ verify(factory).createBinder(anyObject(), notNull(), eq("attrName"));
}
- private void getAttributeFromModel(String expectedAttributeName, MethodParameter param) throws Exception {
+ @Test
+ public void resolveArgumentValidation() throws Exception {
+ String name = "attrName";
Object target = new TestBean();
- mavContainer.addAttribute(expectedAttributeName, target);
+ this.container.addAttribute(name, target);
- WebDataBinder dataBinder = new WebRequestDataBinder(target);
+ StubRequestDataBinder dataBinder = new StubRequestDataBinder(target, name);
WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
- given(factory.createBinder(webRequest, target, expectedAttributeName)).willReturn(dataBinder);
+ given(factory.createBinder(this.request, target, name)).willReturn(dataBinder);
- processor.resolveArgument(param, mavContainer, webRequest, factory);
- verify(factory).createBinder(webRequest, target, expectedAttributeName);
+ this.processor.resolveArgument(this.paramNamedValidModelAttr, this.container, this.request, factory);
+
+ assertTrue(dataBinder.isBindInvoked());
+ assertTrue(dataBinder.isValidateInvoked());
}
@Test
- public void resovleArgumentViaDefaultConstructor() throws Exception {
- WebDataBinder dataBinder = new WebRequestDataBinder(null);
+ public void resolveArgumentBindingDisabledPreviously() throws Exception {
+ String name = "attrName";
+ Object target = new TestBean();
+ this.container.addAttribute(name, target);
+
+ // Declare binding disabled (e.g. via @ModelAttribute method)
+ this.container.setBindingDisabled(name);
+ StubRequestDataBinder dataBinder = new StubRequestDataBinder(target, name);
WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
- given(factory.createBinder((NativeWebRequest) anyObject(), notNull(), eq("attrName"))).willReturn(dataBinder);
+ given(factory.createBinder(this.request, target, name)).willReturn(dataBinder);
- processor.resolveArgument(paramNamedValidModelAttr, mavContainer, webRequest, factory);
+ this.processor.resolveArgument(this.paramNamedValidModelAttr, this.container, this.request, factory);
- verify(factory).createBinder((NativeWebRequest) anyObject(), notNull(), eq("attrName"));
+ assertFalse(dataBinder.isBindInvoked());
+ assertTrue(dataBinder.isValidateInvoked());
}
@Test
- public void resolveArgumentValidation() throws Exception {
- String name = "attrName";
+ public void resolveArgumentBindingDisabled() throws Exception {
+ String name = "noBindAttr";
Object target = new TestBean();
- mavContainer.addAttribute(name, target);
+ this.container.addAttribute(name, target);
StubRequestDataBinder dataBinder = new StubRequestDataBinder(target, name);
- WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
- given(binderFactory.createBinder(webRequest, target, name)).willReturn(dataBinder);
+ WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
+ given(factory.createBinder(this.request, target, name)).willReturn(dataBinder);
- processor.resolveArgument(paramNamedValidModelAttr, mavContainer, webRequest, binderFactory);
+ this.processor.resolveArgument(this.paramBindingDisabledAttr, this.container, this.request, factory);
- assertTrue(dataBinder.isBindInvoked());
+ assertFalse(dataBinder.isBindInvoked());
assertTrue(dataBinder.isValidateInvoked());
}
@Test(expected = BindException.class)
- public void resovleArgumentBindException() throws Exception {
+ public void resolveArgumentBindException() throws Exception {
String name = "testBean";
Object target = new TestBean();
- mavContainer.getModel().addAttribute(target);
+ this.container.getModel().addAttribute(target);
StubRequestDataBinder dataBinder = new StubRequestDataBinder(target, name);
dataBinder.getBindingResult().reject("error");
-
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
- given(binderFactory.createBinder(webRequest, target, name)).willReturn(dataBinder);
+ given(binderFactory.createBinder(this.request, target, name)).willReturn(dataBinder);
- processor.resolveArgument(paramNonSimpleType, mavContainer, webRequest, binderFactory);
- verify(binderFactory).createBinder(webRequest, target, name);
+ this.processor.resolveArgument(this.paramNonSimpleType, this.container, this.request, binderFactory);
+ verify(binderFactory).createBinder(this.request, target, name);
}
@Test // SPR-9378
public void resolveArgumentOrdering() throws Exception {
String name = "testBean";
Object testBean = new TestBean(name);
- mavContainer.addAttribute(name, testBean);
- mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, testBean);
+ this.container.addAttribute(name, testBean);
+ this.container.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, testBean);
Object anotherTestBean = new TestBean();
- mavContainer.addAttribute("anotherTestBean", anotherTestBean);
+ this.container.addAttribute("anotherTestBean", anotherTestBean);
StubRequestDataBinder dataBinder = new StubRequestDataBinder(testBean, name);
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
- given(binderFactory.createBinder(webRequest, testBean, name)).willReturn(dataBinder);
+ given(binderFactory.createBinder(this.request, testBean, name)).willReturn(dataBinder);
- processor.resolveArgument(paramModelAttr, mavContainer, webRequest, binderFactory);
+ this.processor.resolveArgument(this.paramModelAttr, this.container, this.request, binderFactory);
- assertSame("Resolved attribute should be updated to be last in the order",
- testBean, mavContainer.getModel().values().toArray()[1]);
- assertSame("BindingResult of resolved attribute should be last in the order",
- dataBinder.getBindingResult(), mavContainer.getModel().values().toArray()[2]);
+ Object[] values = this.container.getModel().values().toArray();
+ assertSame("Resolved attribute should be updated to be last", testBean, values[1]);
+ assertSame("BindingResult of resolved attr should be last", dataBinder.getBindingResult(), values[2]);
}
@Test
public void handleAnnotatedReturnValue() throws Exception {
- processor.handleReturnValue("expected", returnParamNamedModelAttr, mavContainer, webRequest);
- assertEquals("expected", mavContainer.getModel().get("modelAttrName"));
+ this.processor.handleReturnValue("expected", this.returnParamNamedModelAttr, this.container, this.request);
+ assertEquals("expected", this.container.getModel().get("modelAttrName"));
}
@Test
public void handleNotAnnotatedReturnValue() throws Exception {
TestBean testBean = new TestBean("expected");
- processor.handleReturnValue(testBean, returnParamNonSimpleType, mavContainer, webRequest);
+ this.processor.handleReturnValue(testBean, this.returnParamNonSimpleType, this.container, this.request);
+ assertSame(testBean, this.container.getModel().get("testBean"));
+ }
+
- assertSame(testBean, mavContainer.getModel().get("testBean"));
+ private void testGetAttributeFromModel(String expectedAttrName, MethodParameter param) throws Exception {
+ Object target = new TestBean();
+ this.container.addAttribute(expectedAttrName, target);
+
+ WebDataBinder dataBinder = new WebRequestDataBinder(target);
+ WebDataBinderFactory factory = mock(WebDataBinderFactory.class);
+ given(factory.createBinder(this.request, target, expectedAttrName)).willReturn(dataBinder);
+
+ this.processor.resolveArgument(param, this.container, this.request, factory);
+ verify(factory).createBinder(this.request, target, expectedAttrName);
}
@@ -246,6 +274,7 @@ public class ModelAttributeMethodProcessorTests {
private boolean validateInvoked;
+
public StubRequestDataBinder(Object target, String objectName) {
super(target, objectName);
}
@@ -285,13 +314,18 @@ public class ModelAttributeMethodProcessorTests {
private static class ModelAttributeHandler {
@SuppressWarnings("unused")
- public void modelAttribute(@ModelAttribute("attrName") @Valid TestBean annotatedAttr, Errors errors,
- int intArg, @ModelAttribute TestBean defaultNameAttr, TestBean notAnnotatedAttr) {
+ public void modelAttribute(
+ @ModelAttribute("attrName") @Valid TestBean annotatedAttr,
+ Errors errors,
+ int intArg,
+ @ModelAttribute TestBean defaultNameAttr,
+ @ModelAttribute(name="noBindAttr", binding=false) @Valid TestBean noBindAttr,
+ TestBean notAnnotatedAttr) {
}
}
- @ModelAttribute("modelAttrName")
+ @ModelAttribute("modelAttrName") @SuppressWarnings("unused")
private String annotatedReturnValue() {
return null;
}
diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java
index e0a3c69f..24c61825 100644
--- a/spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java
+++ b/spring-web/src/test/java/org/springframework/web/method/annotation/ModelFactoryTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,12 @@
package org.springframework.web.method.annotation;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-
import java.lang.reflect.Method;
-import java.util.Arrays;
+import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
+
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.ui.Model;
@@ -43,10 +36,19 @@ import org.springframework.web.bind.support.SessionAttributeStore;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
+import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.mock;
+
/**
* Text fixture for {@link ModelFactory} tests.
@@ -55,103 +57,116 @@ import org.springframework.web.method.support.ModelAndViewContainer;
*/
public class ModelFactoryTests {
- private TestController controller = new TestController();
+ private NativeWebRequest webRequest;
- private InvocableHandlerMethod handleMethod;
+ private SessionAttributesHandler attributeHandler;
- private InvocableHandlerMethod handleSessionAttrMethod;
+ private SessionAttributeStore attributeStore;
- private SessionAttributesHandler sessionAttrsHandler;
+ private TestController controller = new TestController();
- private SessionAttributeStore sessionAttributeStore;
-
- private NativeWebRequest webRequest;
+ private ModelAndViewContainer mavContainer;
@Before
public void setUp() throws Exception {
- this.controller = new TestController();
-
- Method method = TestController.class.getDeclaredMethod("handle");
- this.handleMethod = new InvocableHandlerMethod(this.controller, method);
-
- method = TestController.class.getDeclaredMethod("handleSessionAttr", String.class);
- this.handleSessionAttrMethod = new InvocableHandlerMethod(this.controller, method);
-
- this.sessionAttributeStore = new DefaultSessionAttributeStore();
- this.sessionAttrsHandler = new SessionAttributesHandler(TestController.class, this.sessionAttributeStore);
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
+ this.attributeStore = new DefaultSessionAttributeStore();
+ this.attributeHandler = new SessionAttributesHandler(TestController.class, this.attributeStore);
+ this.controller = new TestController();
+ this.mavContainer = new ModelAndViewContainer();
}
@Test
public void modelAttributeMethod() throws Exception {
ModelFactory modelFactory = createModelFactory("modelAttr", Model.class);
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleMethod);
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
- assertEquals(Boolean.TRUE, mavContainer.getModel().get("modelAttr"));
+ assertEquals(Boolean.TRUE, this.mavContainer.getModel().get("modelAttr"));
}
@Test
public void modelAttributeMethodWithExplicitName() throws Exception {
ModelFactory modelFactory = createModelFactory("modelAttrWithName");
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleMethod);
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
- assertEquals(Boolean.TRUE, mavContainer.getModel().get("name"));
+ assertEquals(Boolean.TRUE, this.mavContainer.getModel().get("name"));
}
@Test
public void modelAttributeMethodWithNameByConvention() throws Exception {
ModelFactory modelFactory = createModelFactory("modelAttrConvention");
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleMethod);
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
- assertEquals(Boolean.TRUE, mavContainer.getModel().get("boolean"));
+ assertEquals(Boolean.TRUE, this.mavContainer.getModel().get("boolean"));
}
@Test
public void modelAttributeMethodWithNullReturnValue() throws Exception {
ModelFactory modelFactory = createModelFactory("nullModelAttr");
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleMethod);
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
- assertTrue(mavContainer.containsAttribute("name"));
- assertNull(mavContainer.getModel().get("name"));
+ assertTrue(this.mavContainer.containsAttribute("name"));
+ assertNull(this.mavContainer.getModel().get("name"));
}
@Test
- public void sessionAttribute() throws Exception {
- this.sessionAttributeStore.storeAttribute(this.webRequest, "sessionAttr", "sessionAttrValue");
+ public void modelAttributeWithBindingDisabled() throws Exception {
+ ModelFactory modelFactory = createModelFactory("modelAttrWithBindingDisabled");
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
+
+ assertTrue(this.mavContainer.containsAttribute("foo"));
+ assertTrue(this.mavContainer.isBindingDisabled("foo"));
+ }
+
+ @Test
+ public void modelAttributeFromSessionWithBindingDisabled() throws Exception {
+ Foo foo = new Foo();
+ this.attributeStore.storeAttribute(this.webRequest, "foo", foo);
- // Resolve successfully handler session attribute once
- assertTrue(sessionAttrsHandler.isHandlerSessionAttribute("sessionAttr", null));
+ ModelFactory modelFactory = createModelFactory("modelAttrWithBindingDisabled");
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
+
+ assertTrue(this.mavContainer.containsAttribute("foo"));
+ assertSame(foo, this.mavContainer.getModel().get("foo"));
+ assertTrue(this.mavContainer.isBindingDisabled("foo"));
+ }
+
+ @Test
+ public void sessionAttribute() throws Exception {
+ this.attributeStore.storeAttribute(this.webRequest, "sessionAttr", "sessionAttrValue");
ModelFactory modelFactory = createModelFactory("modelAttr", Model.class);
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleMethod);
+ HandlerMethod handlerMethod = createHandlerMethod("handle");
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
- assertEquals("sessionAttrValue", mavContainer.getModel().get("sessionAttr"));
+ assertEquals("sessionAttrValue", this.mavContainer.getModel().get("sessionAttr"));
}
@Test
public void sessionAttributeNotPresent() throws Exception {
- ModelFactory modelFactory = new ModelFactory(null, null, this.sessionAttrsHandler);
-
+ ModelFactory modelFactory = new ModelFactory(null, null, this.attributeHandler);
+ HandlerMethod handlerMethod = createHandlerMethod("handleSessionAttr", String.class);
try {
- modelFactory.initModel(this.webRequest, new ModelAndViewContainer(), this.handleSessionAttrMethod);
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
fail("Expected HttpSessionRequiredException");
}
catch (HttpSessionRequiredException e) {
// expected
}
- this.sessionAttributeStore.storeAttribute(this.webRequest, "sessionAttr", "sessionAttrValue");
- ModelAndViewContainer mavContainer = new ModelAndViewContainer();
- modelFactory.initModel(this.webRequest, mavContainer, this.handleSessionAttrMethod);
+ // Now add attribute and try again
+ this.attributeStore.storeAttribute(this.webRequest, "sessionAttr", "sessionAttrValue");
- assertEquals("sessionAttrValue", mavContainer.getModel().get("sessionAttr"));
+ modelFactory.initModel(this.webRequest, this.mavContainer, handlerMethod);
+ assertEquals("sessionAttrValue", this.mavContainer.getModel().get("sessionAttr"));
}
@Test
@@ -165,11 +180,12 @@ public class ModelFactoryTests {
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
given(binderFactory.createBinder(this.webRequest, command, commandName)).willReturn(dataBinder);
- ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.sessionAttrsHandler);
+ ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.attributeHandler);
modelFactory.updateModel(this.webRequest, container);
assertEquals(command, container.getModel().get(commandName));
- assertSame(dataBinder.getBindingResult(), container.getModel().get(bindingResultKey(commandName)));
+ String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + commandName;
+ assertSame(dataBinder.getBindingResult(), container.getModel().get(bindingResultKey));
assertEquals(2, container.getModel().size());
}
@@ -184,11 +200,11 @@ public class ModelFactoryTests {
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
given(binderFactory.createBinder(this.webRequest, attribute, attributeName)).willReturn(dataBinder);
- ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.sessionAttrsHandler);
+ ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.attributeHandler);
modelFactory.updateModel(this.webRequest, container);
assertEquals(attribute, container.getModel().get(attributeName));
- assertEquals(attribute, this.sessionAttributeStore.retrieveAttribute(this.webRequest, attributeName));
+ assertEquals(attribute, this.attributeStore.retrieveAttribute(this.webRequest, attributeName));
}
@Test
@@ -198,9 +214,7 @@ public class ModelFactoryTests {
ModelAndViewContainer container = new ModelAndViewContainer();
container.addAttribute(attributeName, attribute);
- // Store and resolve once (to be "remembered")
- this.sessionAttributeStore.storeAttribute(this.webRequest, attributeName, attribute);
- this.sessionAttrsHandler.isHandlerSessionAttribute(attributeName, null);
+ this.attributeStore.storeAttribute(this.webRequest, attributeName, attribute);
WebDataBinder dataBinder = new WebDataBinder(attribute, attributeName);
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
@@ -208,11 +222,11 @@ public class ModelFactoryTests {
container.getSessionStatus().setComplete();
- ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.sessionAttrsHandler);
+ ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.attributeHandler);
modelFactory.updateModel(this.webRequest, container);
assertEquals(attribute, container.getModel().get(attributeName));
- assertNull(this.sessionAttributeStore.retrieveAttribute(this.webRequest, attributeName));
+ assertNull(this.attributeStore.retrieveAttribute(this.webRequest, attributeName));
}
// SPR-12542
@@ -233,34 +247,34 @@ public class ModelFactoryTests {
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
given(binderFactory.createBinder(this.webRequest, attribute, attributeName)).willReturn(dataBinder);
- ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.sessionAttrsHandler);
+ ModelFactory modelFactory = new ModelFactory(null, binderFactory, this.attributeHandler);
modelFactory.updateModel(this.webRequest, container);
assertEquals(queryParam, container.getModel().get(queryParamName));
assertEquals(1, container.getModel().size());
- assertEquals(attribute, this.sessionAttributeStore.retrieveAttribute(this.webRequest, attributeName));
+ assertEquals(attribute, this.attributeStore.retrieveAttribute(this.webRequest, attributeName));
}
- private String bindingResultKey(String key) {
- return BindingResult.MODEL_KEY_PREFIX + key;
- }
-
- private ModelFactory createModelFactory(String methodName, Class<?>... parameterTypes) throws Exception{
- Method method = TestController.class.getMethod(methodName, parameterTypes);
+ private ModelFactory createModelFactory(String methodName, Class<?>... parameterTypes) throws Exception {
+ HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
+ resolvers.addResolver(new ModelMethodProcessor());
- HandlerMethodArgumentResolverComposite argResolvers = new HandlerMethodArgumentResolverComposite();
- argResolvers.addResolver(new ModelMethodProcessor());
+ InvocableHandlerMethod modelMethod = createHandlerMethod(methodName, parameterTypes);
+ modelMethod.setHandlerMethodArgumentResolvers(resolvers);
+ modelMethod.setDataBinderFactory(null);
+ modelMethod.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
- InvocableHandlerMethod handlerMethod = new InvocableHandlerMethod(this.controller, method);
- handlerMethod.setHandlerMethodArgumentResolvers(argResolvers);
- handlerMethod.setDataBinderFactory(null);
- handlerMethod.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
+ return new ModelFactory(Collections.singletonList(modelMethod), null, this.attributeHandler);
+ }
- return new ModelFactory(Arrays.asList(handlerMethod), null, this.sessionAttrsHandler);
+ private InvocableHandlerMethod createHandlerMethod(String methodName, Class<?>... paramTypes) throws Exception {
+ Method method = this.controller.getClass().getMethod(methodName, paramTypes);
+ return new InvocableHandlerMethod(this.controller, method);
}
- @SessionAttributes("sessionAttr") @SuppressWarnings("unused")
+
+ @SessionAttributes({"sessionAttr", "foo"}) @SuppressWarnings("unused")
private static class TestController {
@ModelAttribute
@@ -283,6 +297,11 @@ public class ModelFactoryTests {
return null;
}
+ @ModelAttribute(name="foo", binding=false)
+ public Foo modelAttrWithBindingDisabled() {
+ return new Foo();
+ }
+
public void handle() {
}
@@ -290,4 +309,7 @@ public class ModelFactoryTests {
}
}
+ private static class Foo {
+ }
+
}
diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java
index b484e2ff..a453abb0 100644
--- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java
+++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,9 @@
package org.springframework.web.method.annotation;
import java.lang.reflect.Method;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
import java.util.Map;
import org.junit.After;
@@ -25,10 +28,14 @@ import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
+import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
+import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
+import org.springframework.web.bind.support.DefaultDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletWebRequest;
@@ -50,7 +57,11 @@ public class RequestHeaderMethodArgumentResolverTests {
private MethodParameter paramNamedValueStringArray;
private MethodParameter paramSystemProperty;
private MethodParameter paramContextPath;
+ private MethodParameter paramResolvedNameWithExpression;
+ private MethodParameter paramResolvedNameWithPlaceholder;
private MethodParameter paramNamedValueMap;
+ private MethodParameter paramDate;
+ private MethodParameter paramInstant;
private MockHttpServletRequest servletRequest;
@@ -64,12 +75,16 @@ public class RequestHeaderMethodArgumentResolverTests {
context.refresh();
resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory());
- Method method = getClass().getMethod("params", String.class, String[].class, String.class, String.class, Map.class);
+ Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 0);
paramNamedValueStringArray = new SynthesizingMethodParameter(method, 1);
paramSystemProperty = new SynthesizingMethodParameter(method, 2);
paramContextPath = new SynthesizingMethodParameter(method, 3);
- paramNamedValueMap = new SynthesizingMethodParameter(method, 4);
+ paramResolvedNameWithExpression = new SynthesizingMethodParameter(method, 4);
+ paramResolvedNameWithPlaceholder = new SynthesizingMethodParameter(method, 5);
+ paramNamedValueMap = new SynthesizingMethodParameter(method, 6);
+ paramDate = new SynthesizingMethodParameter(method, 7);
+ paramInstant = new SynthesizingMethodParameter(method, 8);
servletRequest = new MockHttpServletRequest();
webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse());
@@ -97,45 +112,77 @@ public class RequestHeaderMethodArgumentResolverTests {
servletRequest.addHeader("name", expected);
Object result = resolver.resolveArgument(paramNamedDefaultValueStringHeader, null, webRequest, null);
-
assertTrue(result instanceof String);
- assertEquals("Invalid result", expected, result);
+ assertEquals(expected, result);
}
@Test
public void resolveStringArrayArgument() throws Exception {
- String[] expected = new String[]{"foo", "bar"};
+ String[] expected = new String[] {"foo", "bar"};
servletRequest.addHeader("name", expected);
Object result = resolver.resolveArgument(paramNamedValueStringArray, null, webRequest, null);
-
assertTrue(result instanceof String[]);
- assertArrayEquals("Invalid result", expected, (String[]) result);
+ assertArrayEquals(expected, (String[]) result);
}
@Test
public void resolveDefaultValue() throws Exception {
Object result = resolver.resolveArgument(paramNamedDefaultValueStringHeader, null, webRequest, null);
-
assertTrue(result instanceof String);
- assertEquals("Invalid result", "bar", result);
+ assertEquals("bar", result);
}
@Test
public void resolveDefaultValueFromSystemProperty() throws Exception {
System.setProperty("systemProperty", "bar");
- Object result = resolver.resolveArgument(paramSystemProperty, null, webRequest, null);
- System.clearProperty("systemProperty");
+ try {
+ Object result = resolver.resolveArgument(paramSystemProperty, null, webRequest, null);
+ assertTrue(result instanceof String);
+ assertEquals("bar", result);
+ }
+ finally {
+ System.clearProperty("systemProperty");
+ }
+ }
- assertTrue(result instanceof String);
- assertEquals("bar", result);
+ @Test
+ public void resolveNameFromSystemPropertyThroughExpression() throws Exception {
+ String expected = "foo";
+ servletRequest.addHeader("bar", expected);
+
+ System.setProperty("systemProperty", "bar");
+ try {
+ Object result = resolver.resolveArgument(paramResolvedNameWithExpression, null, webRequest, null);
+ assertTrue(result instanceof String);
+ assertEquals(expected, result);
+ }
+ finally {
+ System.clearProperty("systemProperty");
+ }
+ }
+
+ @Test
+ public void resolveNameFromSystemPropertyThroughPlaceholder() throws Exception {
+ String expected = "foo";
+ servletRequest.addHeader("bar", expected);
+
+ System.setProperty("systemProperty", "bar");
+ try {
+ Object result = resolver.resolveArgument(paramResolvedNameWithPlaceholder, null, webRequest, null);
+ assertTrue(result instanceof String);
+ assertEquals(expected, result);
+ }
+ finally {
+ System.clearProperty("systemProperty");
+ }
}
@Test
public void resolveDefaultValueFromRequest() throws Exception {
servletRequest.setContextPath("/bar");
- Object result = resolver.resolveArgument(paramContextPath, null, webRequest, null);
+ Object result = resolver.resolveArgument(paramContextPath, null, webRequest, null);
assertTrue(result instanceof String);
assertEquals("/bar", result);
}
@@ -145,12 +192,46 @@ public class RequestHeaderMethodArgumentResolverTests {
resolver.resolveArgument(paramNamedValueStringArray, null, webRequest, null);
}
+ @Test
+ @SuppressWarnings("deprecation")
+ public void dateConversion() throws Exception {
+ String rfc1123val = "Thu, 21 Apr 2016 17:11:08 +0100";
+ servletRequest.addHeader("name", rfc1123val);
+
+ ConfigurableWebBindingInitializer bindingInitializer = new ConfigurableWebBindingInitializer();
+ bindingInitializer.setConversionService(new DefaultFormattingConversionService());
+ Object result = resolver.resolveArgument(paramDate, null, webRequest,
+ new DefaultDataBinderFactory(bindingInitializer));
+
+ assertTrue(result instanceof Date);
+ assertEquals(new Date(rfc1123val), result);
+ }
+
+ @Test
+ public void instantConversion() throws Exception {
+ String rfc1123val = "Thu, 21 Apr 2016 17:11:08 +0100";
+ servletRequest.addHeader("name", rfc1123val);
+
+ ConfigurableWebBindingInitializer bindingInitializer = new ConfigurableWebBindingInitializer();
+ bindingInitializer.setConversionService(new DefaultFormattingConversionService());
+ Object result = resolver.resolveArgument(paramInstant, null, webRequest,
+ new DefaultDataBinderFactory(bindingInitializer));
+
+ assertTrue(result instanceof Instant);
+ assertEquals(Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(rfc1123val)), result);
+ }
+
- public void params(@RequestHeader(name = "name", defaultValue = "bar") String param1,
- @RequestHeader("name") String[] param2,
- @RequestHeader(name = "name", defaultValue="#{systemProperties.systemProperty}") String param3,
- @RequestHeader(name = "name", defaultValue="#{request.contextPath}") String param4,
- @RequestHeader("name") Map<?, ?> unsupported) {
+ public void params(
+ @RequestHeader(name = "name", defaultValue = "bar") String param1,
+ @RequestHeader("name") String[] param2,
+ @RequestHeader(name = "name", defaultValue="#{systemProperties.systemProperty}") String param3,
+ @RequestHeader(name = "name", defaultValue="#{request.contextPath}") String param4,
+ @RequestHeader("#{systemProperties.systemProperty}") String param5,
+ @RequestHeader("${systemProperty}") String param6,
+ @RequestHeader("name") Map<?, ?> unsupported,
+ @RequestHeader("name") Date dateParam,
+ @RequestHeader("name") Instant instantParam) {
}
}
diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
index 00b61b5f..f77ce2bc 100644
--- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
+++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java
@@ -37,6 +37,7 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.mock.web.test.MockMultipartFile;
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
import org.springframework.mock.web.test.MockPart;
+import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.RequestParam;
@@ -49,6 +50,7 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.support.MissingServletRequestPartException;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@@ -82,6 +84,7 @@ public class RequestParamMethodArgumentResolverTests {
private MethodParameter paramRequired;
private MethodParameter paramNotRequired;
private MethodParameter paramOptional;
+ private MethodParameter multipartFileOptional;
private NativeWebRequest webRequest;
@@ -92,12 +95,7 @@ public class RequestParamMethodArgumentResolverTests {
public void setUp() throws Exception {
resolver = new RequestParamMethodArgumentResolver(null, true);
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
-
- Method method = getClass().getMethod("params", String.class, String[].class,
- Map.class, MultipartFile.class, List.class, MultipartFile[].class,
- Part.class, List.class, Part[].class, Map.class,
- String.class, MultipartFile.class, List.class, Part.class,
- MultipartFile.class, String.class, String.class, Optional.class);
+ Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
@@ -121,6 +119,7 @@ public class RequestParamMethodArgumentResolverTests {
paramRequired = new SynthesizingMethodParameter(method, 15);
paramNotRequired = new SynthesizingMethodParameter(method, 16);
paramOptional = new SynthesizingMethodParameter(method, 17);
+ multipartFileOptional = new SynthesizingMethodParameter(method, 18);
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
@@ -130,19 +129,25 @@ public class RequestParamMethodArgumentResolverTests {
@Test
public void supportsParameter() {
resolver = new RequestParamMethodArgumentResolver(null, true);
- assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueString));
- assertTrue("String array parameter not supported", resolver.supportsParameter(paramNamedStringArray));
- assertTrue("Named map not parameter supported", resolver.supportsParameter(paramNamedMap));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
- assertTrue("List<MultipartFile> parameter not supported", resolver.supportsParameter(paramMultipartFileList));
- assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
- assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
- assertTrue("List<Part> parameter not supported", resolver.supportsParameter(paramPartList));
- assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
- assertFalse("non-@RequestParam parameter supported", resolver.supportsParameter(paramMap));
- assertTrue("Simple type params supported w/o annotations", resolver.supportsParameter(paramStringNotAnnot));
- assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
- assertTrue("Part parameter not supported", resolver.supportsParameter(paramPartNotAnnot));
+ assertTrue(resolver.supportsParameter(paramNamedDefaultValueString));
+ assertTrue(resolver.supportsParameter(paramNamedStringArray));
+ assertTrue(resolver.supportsParameter(paramNamedMap));
+ assertTrue(resolver.supportsParameter(paramMultipartFile));
+ assertTrue(resolver.supportsParameter(paramMultipartFileList));
+ assertTrue(resolver.supportsParameter(paramMultipartFileArray));
+ assertTrue(resolver.supportsParameter(paramPart));
+ assertTrue(resolver.supportsParameter(paramPartList));
+ assertTrue(resolver.supportsParameter(paramPartArray));
+ assertFalse(resolver.supportsParameter(paramMap));
+ assertTrue(resolver.supportsParameter(paramStringNotAnnot));
+ assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot));
+ assertTrue(resolver.supportsParameter(paramMultipartFileListNotAnnot));
+ assertTrue(resolver.supportsParameter(paramPartNotAnnot));
+ assertFalse(resolver.supportsParameter(paramRequestPartAnnot));
+ assertTrue(resolver.supportsParameter(paramRequired));
+ assertTrue(resolver.supportsParameter(paramNotRequired));
+ assertTrue(resolver.supportsParameter(paramOptional));
+ assertTrue(resolver.supportsParameter(multipartFileOptional));
resolver = new RequestParamMethodArgumentResolver(null, false);
assertFalse(resolver.supportsParameter(paramStringNotAnnot));
@@ -188,6 +193,7 @@ public class RequestParamMethodArgumentResolverTests {
MultipartFile expected2 = new MockMultipartFile("mfilelist", "Hello World 2".getBytes());
request.addFile(expected1);
request.addFile(expected2);
+ request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
@@ -202,6 +208,7 @@ public class RequestParamMethodArgumentResolverTests {
MultipartFile expected2 = new MockMultipartFile("mfilearray", "Hello World 2".getBytes());
request.addFile(expected1);
request.addFile(expected2);
+ request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramMultipartFileArray, null, webRequest, null);
@@ -222,7 +229,6 @@ public class RequestParamMethodArgumentResolverTests {
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
-
assertTrue(result instanceof Part);
assertEquals("Invalid result", expected, result);
}
@@ -230,12 +236,13 @@ public class RequestParamMethodArgumentResolverTests {
@Test
public void resolvePartList() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
- MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
- MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
request.setMethod("POST");
request.setContentType("multipart/form-data");
+ MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
+ MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
request.addPart(expected1);
request.addPart(expected2);
+ request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
@@ -252,6 +259,7 @@ public class RequestParamMethodArgumentResolverTests {
request.setContentType("multipart/form-data");
request.addPart(expected1);
request.addPart(expected2);
+ request.addPart(new MockPart("other", "Hello World 3".getBytes()));
webRequest = new ServletWebRequest(request);
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
@@ -307,12 +315,19 @@ public class RequestParamMethodArgumentResolverTests {
assertEquals(expected, ((List<?>) actual).get(0));
}
- @Test(expected = IllegalArgumentException.class)
+ @Test(expected = MultipartException.class)
+ public void noMultipartContent() throws Exception {
+ request.setMethod("POST");
+ resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
+ fail("Expected exception: no multipart content");
+ }
+
+ @Test(expected = MissingServletRequestPartException.class)
public void missingMultipartFile() throws Exception {
request.setMethod("POST");
request.setContentType("multipart/form-data");
resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
- fail("Expected exception: request is not MultiPartHttpServletRequest but param is MultipartFile");
+ fail("Expected exception: no such part found");
}
@Test
@@ -422,8 +437,45 @@ public class RequestParamMethodArgumentResolverTests {
assertEquals(123, ((Optional) result).get());
}
+ @Test
+ public void resolveOptionalMultipartFile() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
+
+ MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
+ MultipartFile expected = new MockMultipartFile("mfile", "Hello World".getBytes());
+ request.addFile(expected);
+ webRequest = new ServletWebRequest(request);
+
+ Object result = resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory);
+ assertTrue(result instanceof Optional);
+ assertEquals("Invalid result", expected, ((Optional<?>) result).get());
+ }
+
+ @Test
+ public void missingOptionalMultipartFile() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
+
+ request.setMethod("POST");
+ request.setContentType("multipart/form-data");
+ assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
+ }
+
+ @Test
+ public void optionalMultipartFileWithoutMultipartRequest() throws Exception {
+ ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
+ initializer.setConversionService(new DefaultConversionService());
+ WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
+
+ assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
+ }
+
- public void params(@RequestParam(name = "name", defaultValue = "bar") String param1,
+ public void handle(
+ @RequestParam(name = "name", defaultValue = "bar") String param1,
@RequestParam("name") String[] param2,
@RequestParam("name") Map<?, ?> param3,
@RequestParam("mfile") MultipartFile param4,
@@ -440,7 +492,8 @@ public class RequestParamMethodArgumentResolverTests {
@RequestPart MultipartFile requestPartAnnot,
@RequestParam("name") String paramRequired,
@RequestParam(name = "name", required = false) String paramNotRequired,
- @RequestParam("name") Optional<Integer> paramOptional) {
+ @RequestParam("name") Optional<Integer> paramOptional,
+ @RequestParam("mfile") Optional<MultipartFile> multipartFileOptional) {
}
}
diff --git a/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java b/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java
index 1642351e..09f3700a 100644
--- a/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java
+++ b/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,74 +15,135 @@
*/
package org.springframework.web.util;
-import static org.junit.Assert.assertEquals;
-
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
-import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
/**
* Unit tests for {@link DefaultUriTemplateHandler}.
+ *
* @author Rossen Stoyanchev
*/
public class DefaultUriTemplateHandlerTests {
- private DefaultUriTemplateHandler handler;
-
-
- @Before
- public void setUp() throws Exception {
- this.handler = new DefaultUriTemplateHandler();
- }
+ private final DefaultUriTemplateHandler handler = new DefaultUriTemplateHandler();
@Test
- public void baseUrl() throws Exception {
+ public void baseUrlWithoutPath() throws Exception {
this.handler.setBaseUrl("http://localhost:8080");
URI actual = this.handler.expand("/myapiresource");
- URI expected = new URI("http://localhost:8080/myapiresource");
- assertEquals(expected, actual);
+ assertEquals("http://localhost:8080/myapiresource", actual.toString());
}
@Test
- public void baseUrlWithPartialPath() throws Exception {
+ public void baseUrlWithPath() throws Exception {
this.handler.setBaseUrl("http://localhost:8080/context");
URI actual = this.handler.expand("/myapiresource");
- URI expected = new URI("http://localhost:8080/context/myapiresource");
- assertEquals(expected, actual);
+ assertEquals("http://localhost:8080/context/myapiresource", actual.toString());
+ }
+
+ @Test // SPR-14147
+ public void defaultUriVariables() throws Exception {
+ Map<String, String> defaultVars = new HashMap<>(2);
+ defaultVars.put("host", "api.example.com");
+ defaultVars.put("port", "443");
+ this.handler.setDefaultUriVariables(defaultVars);
+
+ Map<String, Object> vars = new HashMap<>(1);
+ vars.put("id", 123L);
+
+ String template = "https://{host}:{port}/v42/customers/{id}";
+ URI actual = this.handler.expand(template, vars);
+
+ assertEquals("https://api.example.com:443/v42/customers/123", actual.toString());
}
@Test
- public void expandWithFullPath() throws Exception {
- Map<String, String> vars = new HashMap<String, String>(2);
+ public void parsePathIsOff() throws Exception {
+ this.handler.setParsePath(false);
+ Map<String, String> vars = new HashMap<>(2);
vars.put("hotel", "1");
vars.put("publicpath", "pics/logo.png");
String template = "http://example.com/hotels/{hotel}/pic/{publicpath}";
-
URI actual = this.handler.expand(template, vars);
- URI expected = new URI("http://example.com/hotels/1/pic/pics/logo.png");
- assertEquals(expected, actual);
+ assertEquals("http://example.com/hotels/1/pic/pics/logo.png", actual.toString());
}
@Test
- public void expandWithFullPathAndParsePathEnabled() throws Exception {
- Map<String, String> vars = new HashMap<String, String>(2);
+ public void parsePathIsOn() throws Exception {
+ this.handler.setParsePath(true);
+ Map<String, String> vars = new HashMap<>(2);
vars.put("hotel", "1");
vars.put("publicpath", "pics/logo.png");
vars.put("scale", "150x150");
String template = "http://example.com/hotels/{hotel}/pic/{publicpath}/size/{scale}";
+ URI actual = this.handler.expand(template, vars);
- this.handler.setParsePath(true);
+ assertEquals("http://example.com/hotels/1/pic/pics%2Flogo.png/size/150x150", actual.toString());
+ }
+
+ @Test
+ public void strictEncodingIsOffWithMap() throws Exception {
+ this.handler.setStrictEncoding(false);
+ Map<String, String> vars = new HashMap<>(2);
+ vars.put("userId", "john;doe");
+ String template = "http://www.example.com/user/{userId}/dashboard";
+ URI actual = this.handler.expand(template, vars);
+
+ assertEquals("http://www.example.com/user/john;doe/dashboard", actual.toString());
+ }
+
+ @Test
+ public void strictEncodingOffWithArray() throws Exception {
+ this.handler.setStrictEncoding(false);
+ String template = "http://www.example.com/user/{userId}/dashboard";
+ URI actual = this.handler.expand(template, "john;doe");
+
+ assertEquals("http://www.example.com/user/john;doe/dashboard", actual.toString());
+ }
+
+ @Test
+ public void strictEncodingOnWithMap() throws Exception {
+ this.handler.setStrictEncoding(true);
+ Map<String, String> vars = new HashMap<>(2);
+ vars.put("userId", "john;doe");
+ String template = "http://www.example.com/user/{userId}/dashboard";
+ URI actual = this.handler.expand(template, vars);
+
+ assertEquals("http://www.example.com/user/john%3Bdoe/dashboard", actual.toString());
+ }
+
+ @Test
+ public void strictEncodingOnWithArray() throws Exception {
+ this.handler.setStrictEncoding(true);
+ String template = "http://www.example.com/user/{userId}/dashboard";
+ URI actual = this.handler.expand(template, "john;doe");
+
+ assertEquals("http://www.example.com/user/john%3Bdoe/dashboard", actual.toString());
+ }
+
+ @Test // SPR-14147
+ public void strictEncodingAndDefaultUriVariables() throws Exception {
+ Map<String, String> defaultVars = new HashMap<>(1);
+ defaultVars.put("host", "www.example.com");
+ this.handler.setDefaultUriVariables(defaultVars);
+ this.handler.setStrictEncoding(true);
+
+ Map<String, Object> vars = new HashMap<>(1);
+ vars.put("userId", "john;doe");
+
+ String template = "http://{host}/user/{userId}/dashboard";
URI actual = this.handler.expand(template, vars);
- URI expected = new URI("http://example.com/hotels/1/pic/pics%2Flogo.png/size/150x150");
- assertEquals(expected, actual);
+ assertEquals("http://www.example.com/user/john%3Bdoe/dashboard", actual.toString());
}
}
diff --git a/spring-web/src/test/java/org/springframework/web/util/Log4jWebConfigurerTests.java b/spring-web/src/test/java/org/springframework/web/util/Log4jWebConfigurerTests.java
index 5001f9fb..c32405e4 100644
--- a/spring-web/src/test/java/org/springframework/web/util/Log4jWebConfigurerTests.java
+++ b/spring-web/src/test/java/org/springframework/web/util/Log4jWebConfigurerTests.java
@@ -101,7 +101,8 @@ public class Log4jWebConfigurerTests {
try {
assertLogOutput();
- } finally {
+ }
+ finally {
Log4jWebConfigurer.shutdownLogging(sc);
}
assertTrue(MockLog4jAppender.closeCalled);
@@ -132,7 +133,8 @@ public class Log4jWebConfigurerTests {
try {
assertLogOutput();
- } finally {
+ }
+ finally {
listener.contextDestroyed(new ServletContextEvent(sc));
}
assertTrue(MockLog4jAppender.closeCalled);
diff --git a/spring-web/src/test/java/org/springframework/web/util/UriTemplateTests.java b/spring-web/src/test/java/org/springframework/web/util/UriTemplateTests.java
index a047af03..99c642f0 100644
--- a/spring-web/src/test/java/org/springframework/web/util/UriTemplateTests.java
+++ b/spring-web/src/test/java/org/springframework/web/util/UriTemplateTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,116 +30,126 @@ import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
* @author Juergen Hoeller
+ * @author Rossen Stoyanchev
*/
public class UriTemplateTests {
@Test
public void getVariableNames() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
List<String> variableNames = template.getVariableNames();
assertEquals("Invalid variable names", Arrays.asList("hotel", "booking"), variableNames);
}
@Test
public void expandVarArgs() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
URI result = template.expand("1", "42");
- assertEquals("Invalid expanded template", new URI("http://example.com/hotels/1/bookings/42"), result);
+ assertEquals("Invalid expanded template", new URI("/hotels/1/bookings/42"), result);
+ }
+
+ // SPR-9712
+
+ @Test
+ public void expandVarArgsWithArrayValue() throws Exception {
+ UriTemplate template = new UriTemplate("/sum?numbers={numbers}");
+ URI result = template.expand(new int[] {1, 2, 3});
+ assertEquals(new URI("/sum?numbers=1,2,3"), result);
}
@Test(expected = IllegalArgumentException.class)
public void expandVarArgsNotEnoughVariables() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
template.expand("1");
}
@Test
public void expandMap() throws Exception {
- Map<String, String> uriVariables = new HashMap<String, String>(2);
+ Map<String, String> uriVariables = new HashMap<>(2);
uriVariables.put("booking", "42");
uriVariables.put("hotel", "1");
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
URI result = template.expand(uriVariables);
- assertEquals("Invalid expanded template", new URI("http://example.com/hotels/1/bookings/42"), result);
+ assertEquals("Invalid expanded template", new URI("/hotels/1/bookings/42"), result);
}
@Test
public void expandMapDuplicateVariables() throws Exception {
UriTemplate template = new UriTemplate("/order/{c}/{c}/{c}");
- assertEquals("Invalid variable names", Arrays.asList("c", "c", "c"), template.getVariableNames());
+ assertEquals(Arrays.asList("c", "c", "c"), template.getVariableNames());
URI result = template.expand(Collections.singletonMap("c", "cheeseburger"));
- assertEquals("Invalid expanded template", new URI("/order/cheeseburger/cheeseburger/cheeseburger"), result);
+ assertEquals(new URI("/order/cheeseburger/cheeseburger/cheeseburger"), result);
}
@Test
public void expandMapNonString() throws Exception {
- Map<String, Integer> uriVariables = new HashMap<String, Integer>(2);
+ Map<String, Integer> uriVariables = new HashMap<>(2);
uriVariables.put("booking", 42);
uriVariables.put("hotel", 1);
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
URI result = template.expand(uriVariables);
- assertEquals("Invalid expanded template", new URI("http://example.com/hotels/1/bookings/42"), result);
+ assertEquals("Invalid expanded template", new URI("/hotels/1/bookings/42"), result);
}
@Test
public void expandMapEncoded() throws Exception {
Map<String, String> uriVariables = Collections.singletonMap("hotel", "Z\u00fcrich");
- UriTemplate template = new UriTemplate("http://example.com/hotel list/{hotel}");
+ UriTemplate template = new UriTemplate("/hotel list/{hotel}");
URI result = template.expand(uriVariables);
- assertEquals("Invalid expanded template", new URI("http://example.com/hotel%20list/Z%C3%BCrich"), result);
+ assertEquals("Invalid expanded template", new URI("/hotel%20list/Z%C3%BCrich"), result);
}
@Test(expected = IllegalArgumentException.class)
public void expandMapUnboundVariables() throws Exception {
- Map<String, String> uriVariables = new HashMap<String, String>(2);
+ Map<String, String> uriVariables = new HashMap<>(2);
uriVariables.put("booking", "42");
uriVariables.put("bar", "1");
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
template.expand(uriVariables);
}
@Test
public void expandEncoded() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotel list/{hotel}");
+ UriTemplate template = new UriTemplate("/hotel list/{hotel}");
URI result = template.expand("Z\u00fcrich");
- assertEquals("Invalid expanded template", new URI("http://example.com/hotel%20list/Z%C3%BCrich"), result);
+ assertEquals("Invalid expanded template", new URI("/hotel%20list/Z%C3%BCrich"), result);
}
@Test
public void matches() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
- assertTrue("UriTemplate does not match", template.matches("http://example.com/hotels/1/bookings/42"));
- assertFalse("UriTemplate matches", template.matches("http://example.com/hotels/bookings"));
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
+ assertTrue("UriTemplate does not match", template.matches("/hotels/1/bookings/42"));
+ assertFalse("UriTemplate matches", template.matches("/hotels/bookings"));
assertFalse("UriTemplate matches", template.matches(""));
assertFalse("UriTemplate matches", template.matches(null));
}
@Test
public void matchesCustomRegex() throws Exception {
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel:\\d+}");
- assertTrue("UriTemplate does not match", template.matches("http://example.com/hotels/42"));
- assertFalse("UriTemplate matches", template.matches("http://example.com/hotels/foo"));
+ UriTemplate template = new UriTemplate("/hotels/{hotel:\\d+}");
+ assertTrue("UriTemplate does not match", template.matches("/hotels/42"));
+ assertFalse("UriTemplate matches", template.matches("/hotels/foo"));
}
@Test
public void match() throws Exception {
- Map<String, String> expected = new HashMap<String, String>(2);
+ Map<String, String> expected = new HashMap<>(2);
expected.put("booking", "42");
expected.put("hotel", "1");
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel}/bookings/{booking}");
- Map<String, String> result = template.match("http://example.com/hotels/1/bookings/42");
+ UriTemplate template = new UriTemplate("/hotels/{hotel}/bookings/{booking}");
+ Map<String, String> result = template.match("/hotels/1/bookings/42");
assertEquals("Invalid match", expected, result);
}
@Test
public void matchCustomRegex() throws Exception {
- Map<String, String> expected = new HashMap<String, String>(2);
+ Map<String, String> expected = new HashMap<>(2);
expected.put("booking", "42");
expected.put("hotel", "1");
- UriTemplate template = new UriTemplate("http://example.com/hotels/{hotel:\\d}/bookings/{booking:\\d+}");
- Map<String, String> result = template.match("http://example.com/hotels/1/bookings/42");
+ UriTemplate template = new UriTemplate("/hotels/{hotel:\\d}/bookings/{booking:\\d+}");
+ Map<String, String> result = template.match("/hotels/1/bookings/42");
assertEquals("Invalid match", expected, result);
}
@@ -164,7 +174,7 @@ public class UriTemplateTests {
public void matchMultipleInOneSegment() throws Exception {
UriTemplate template = new UriTemplate("/{foo}-{bar}");
Map<String, String> result = template.match("/12-34");
- Map<String, String> expected = new HashMap<String, String>(2);
+ Map<String, String> expected = new HashMap<>(2);
expected.put("foo", "12");
expected.put("bar", "34");
assertEquals("Invalid match", expected, result);
diff --git a/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java b/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java
index 6480c5fa..2227674a 100644
--- a/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java
+++ b/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
+ * @author Juergen Hoeller
*/
public class UriUtilsTests {
@@ -104,4 +105,22 @@ public class UriUtilsTests {
UriUtils.decode("foo%2", ENC);
}
+ @Test
+ public void extractFileExtension() {
+ assertEquals("html", UriUtils.extractFileExtension("index.html"));
+ assertEquals("html", UriUtils.extractFileExtension("/index.html"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/a"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/path/a"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/path/a.do"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=a"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a.do"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a#/path/a"));
+ assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a.do#/path/a.do"));
+ assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html?param=/path/a.do"));
+ assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html;r=22?param=/path/a.do"));
+ assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html;r=22;s=33?param=/path/a.do"));
+ }
+
}