From b77698ec67e6edb65b59b979f7519fdfb6294628 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 1 Apr 2010 10:08:51 +0000 Subject: [PATCH] Introduced ResponseEntity, for access to the response status code git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3210 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../AnnotationMethodHandlerAdapter.java | 5 + .../ServletAnnotationControllerTests.java | 7 +- .../org/springframework/http/HttpEntity.java | 65 +-- .../springframework/http/ResponseEntity.java | 70 +++ .../web/bind/annotation/RequestMapping.java | 3 +- .../web/client/RestOperations.java | 33 +- .../web/client/RestTemplate.java | 57 +-- .../springframework/http/HttpEntityTests.java | 32 +- .../FormHttpMessageConverterTests.java | 5 +- .../client/RestTemplateIntegrationTests.java | 11 +- .../web/client/RestTemplateTests.java | 29 +- org.springframework.web/web.iml | 467 +++++++++--------- spring-framework-reference/src/mvc.xml | 14 +- 13 files changed, 438 insertions(+), 360 deletions(-) create mode 100644 org.springframework.web/src/main/java/org/springframework/http/ResponseEntity.java diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java index 1f30a41c760..be26087f72b 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java @@ -61,12 +61,14 @@ import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.xml.SourceHttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.ui.ExtendedModelMap; @@ -895,6 +897,9 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator } HttpInputMessage inputMessage = createHttpInputMessage(webRequest); HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest); + if (responseEntity instanceof ResponseEntity && outputMessage instanceof ServerHttpResponse) { + ((ServerHttpResponse)outputMessage).setStatusCode(((ResponseEntity) responseEntity).getStatusCode()); + } HttpHeaders entityHeaders = responseEntity.getHeaders(); if (!entityHeaders.isEmpty()) { outputMessage.getHeaders().putAll(entityHeaders); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java index 2481ef8eb4f..726c6161939 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java @@ -75,6 +75,7 @@ import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -1201,7 +1202,7 @@ public class ServletAnnotationControllerTests { request.addHeader("MyRequestHeader", "MyValue"); MockHttpServletResponse response = new MockHttpServletResponse(); servlet.service(request, response); - assertEquals(200, response.getStatus()); + assertEquals(201, response.getStatus()); assertEquals(requestBody, response.getContentAsString()); assertEquals("MyValue", response.getHeader("MyResponseHeader")); } @@ -2598,7 +2599,7 @@ public class ServletAnnotationControllerTests { public static class HttpEntityController { @RequestMapping("/handle") - public HttpEntity handle(HttpEntity requestEntity) throws UnsupportedEncodingException { + public ResponseEntity handle(HttpEntity requestEntity) throws UnsupportedEncodingException { assertNotNull(requestEntity); assertEquals("MyValue", requestEntity.getHeaders().getFirst("MyRequestHeader")); String requestBody = new String(requestEntity.getBody(), "UTF-8"); @@ -2606,7 +2607,7 @@ public class ServletAnnotationControllerTests { HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set("MyResponseHeader", "MyValue"); - return new HttpEntity(requestBody, responseHeaders); + return new ResponseEntity(requestBody, responseHeaders, HttpStatus.CREATED); } } diff --git a/org.springframework.web/src/main/java/org/springframework/http/HttpEntity.java b/org.springframework.web/src/main/java/org/springframework/http/HttpEntity.java index 683c2b38711..f76be436e0a 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/HttpEntity.java +++ b/org.springframework.web/src/main/java/org/springframework/http/HttpEntity.java @@ -16,9 +16,6 @@ package org.springframework.http; -import java.util.Map; - -import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** @@ -35,6 +32,15 @@ import org.springframework.util.MultiValueMap; * String body = entity.getBody(); * MediaType contentType = entity.getHeaders().getContentType(); * + * Can also be used in Spring MVC, as a return value from a @Controller method: + *
+ * @RequestMapping("/handle")
+ * public HttpEntity<String> handle() {
+ *   HttpHeaders responseHeaders = new HttpHeaders();
+ *   responseHeaders.set("MyResponseHeader", "MyValue");
+ *   return new HttpEntity("Hello World", responseHeaders);
+ * }
+ * 
* * @author Arjen Poutsma * @since 3.0.2 @@ -59,7 +65,7 @@ public class HttpEntity { * Create a new, empty {@code HttpEntity}. */ private HttpEntity() { - this(null, (MultiValueMap) null); + this(null, null); } /** @@ -67,15 +73,7 @@ public class HttpEntity { * @param body the entity body */ public HttpEntity(T body) { - this(body, (MultiValueMap) null); - } - - /** - * Create a new {@code HttpEntity} with the given headers and no body. - * @param headers the entity headers - */ - public HttpEntity(Map headers) { - this(null, toMultiValueMap(headers)); + this(body, null); } /** @@ -86,24 +84,6 @@ public class HttpEntity { this(null, headers); } - /** - * Create a new {@code HttpEntity} with the given body and {@code Content-Type} header value. - * @param body the entity body - * @param contentType the value of the {@code Content-Type header} - */ - public HttpEntity(T body, MediaType contentType) { - this(body, toMultiValueMap(contentType)); - } - - /** - * Create a new {@code HttpEntity} with the given body and headers. - * @param body the entity body - * @param headers the entity headers - */ - public HttpEntity(T body, Map headers) { - this(body, toMultiValueMap(headers)); - } - /** * Create a new {@code HttpEntity} with the given body and headers. * @param body the entity body @@ -140,27 +120,4 @@ public class HttpEntity { return (this.body != null); } - - private static MultiValueMap toMultiValueMap(Map map) { - if (map == null) { - return null; - } - else { - MultiValueMap result = new LinkedMultiValueMap(map.size()); - result.setAll(map); - return result; - } - } - - private static MultiValueMap toMultiValueMap(MediaType contentType) { - if (contentType == null) { - return null; - } - else { - HttpHeaders result = new HttpHeaders(); - result.setContentType(contentType); - return result; - } - } - } diff --git a/org.springframework.web/src/main/java/org/springframework/http/ResponseEntity.java b/org.springframework.web/src/main/java/org/springframework/http/ResponseEntity.java new file mode 100644 index 00000000000..3bbf2295df7 --- /dev/null +++ b/org.springframework.web/src/main/java/org/springframework/http/ResponseEntity.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2010 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.http; + +import org.springframework.util.MultiValueMap; + +/** + * Extension of {@link HttpEntity} that adds a {@link HttpStatus} status code. + * + * @author Arjen Poutsma + * @since 3.0.2 + * @see #getStatusCode() + */ +public class ResponseEntity extends HttpEntity { + + private final HttpStatus statusCode; + + /** + * Create a new {@code ResponseEntity} with the given body and status code, and no headers. + * @param body the entity body + * @param statusCode the status code + */ + public ResponseEntity(T body, HttpStatus statusCode) { + super(body); + this.statusCode = statusCode; + } + + /** + * Create a new {@code HttpEntity} with the given headers and status code, and no body. + * @param headers the entity headers + * @param statusCode the status code + */ + public ResponseEntity(MultiValueMap headers, HttpStatus statusCode) { + super(headers); + this.statusCode = statusCode; + } + + /** + * Create a new {@code HttpEntity} with the given body, headers, and status code. + * @param body the entity body + * @param headers the entity headers + * @param statusCode the status code + */ + public ResponseEntity(T body, MultiValueMap headers, HttpStatus statusCode) { + super(body, headers); + this.statusCode = statusCode; + } + + /** + * Return the HTTP status code of the response. + * @return the HTTP status as an HttpStatus enum value + */ + public HttpStatus getStatusCode() { + return statusCode; + } +} diff --git a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java index 674cf7031b6..da5ec5f43eb 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java +++ b/org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java @@ -151,7 +151,8 @@ import java.lang.annotation.Target; * to the response stream using * {@linkplain org.springframework.http.converter.HttpMessageConverter message * converters}. - *
  • A {@link org.springframework.http.HttpEntity HttpEntity<?>} object + *
  • A {@link org.springframework.http.HttpEntity HttpEntity<?>} or + * {@link org.springframework.http.ResponseEntity ResponseEntity<?>} object * to access to the Servlet reponse HTTP headers and contents. The entity body will * be converted to the response stream using * {@linkplain org.springframework.http.converter.HttpMessageConverter message diff --git a/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java b/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java index be97e6be9e1..e067f77fbaf 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java +++ b/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java @@ -23,6 +23,7 @@ import java.util.Set; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; /** * Interface specifying a basic set of RESTful operations. Implemented by {@link RestTemplate}. @@ -71,7 +72,7 @@ public interface RestOperations { /** * Retrieve an entity by doing a GET on the specified URL. - * The response is converted and stored in an {@link HttpEntity}. + * The response is converted and stored in an {@link ResponseEntity}. *

    URI Template variables are expanded using the given URI variables, if any. * @param url the URL * @param responseType the type of the return value @@ -79,11 +80,11 @@ public interface RestOperations { * @return the entity * @since 3.0.2 */ - HttpEntity getForEntity(String url, Class responseType, Object... uriVariables) throws RestClientException; + ResponseEntity getForEntity(String url, Class responseType, Object... uriVariables) throws RestClientException; /** * Retrieve a representation by doing a GET on the URI template. - * The response is converted and stored in an {@link HttpEntity}. + * The response is converted and stored in an {@link ResponseEntity}. *

    URI Template variables are expanded using the given map. * @param url the URL * @param responseType the type of the return value @@ -91,17 +92,17 @@ public interface RestOperations { * @return the converted object * @since 3.0.2 */ - HttpEntity getForEntity(String url, Class responseType, Map uriVariables) throws RestClientException; + ResponseEntity getForEntity(String url, Class responseType, Map uriVariables) throws RestClientException; /** * Retrieve a representation by doing a GET on the URL . - * The response is converted and stored in an {@link HttpEntity}. + * The response is converted and stored in an {@link ResponseEntity}. * @param url the URL * @param responseType the type of the return value * @return the converted object * @since 3.0.2 */ - HttpEntity getForEntity(URI url, Class responseType) throws RestClientException; + ResponseEntity getForEntity(URI url, Class responseType) throws RestClientException; // HEAD @@ -219,7 +220,7 @@ public interface RestOperations { /** * Create a new resource by POSTing the given object to the URI template, - * and returns the response as {@link HttpEntity}. + * and returns the response as {@link ResponseEntity}. *

    URI Template variables are expanded using the given URI variables, if any. *

    The {@code request} parameter can be a {@link HttpEntity} in order to * add additional HTTP headers to the request. @@ -230,7 +231,7 @@ public interface RestOperations { * @see HttpEntity * @since 3.0.2 */ - HttpEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables) + ResponseEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables) throws RestClientException; /** @@ -251,7 +252,7 @@ public interface RestOperations { /** * Create a new resource by POSTing the given object to the URL, - * and returns the response as {@link HttpEntity}. + * and returns the response as {@link ResponseEntity}. *

    The {@code request} parameter can be a {@link HttpEntity} in order to * add additional HTTP headers to the request. * @param url the URL @@ -260,7 +261,7 @@ public interface RestOperations { * @see HttpEntity * @since 3.0.2 */ - HttpEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException; + ResponseEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException; // PUT @@ -354,7 +355,7 @@ public interface RestOperations { /** * Execute the HTTP method to the given URI template, writing the given request entity to the request, and - * returns the response as {@link HttpEntity}. + * returns the response as {@link ResponseEntity}. *

    URI Template variables are expanded using the given URI variables, if any. * @param url the URL * @param method the HTTP method (GET, POST, etc) @@ -364,12 +365,12 @@ public interface RestOperations { * @return the response as entity * @since 3.0.2 */ - HttpEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, + ResponseEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, Class responseType, Object... uriVariables) throws RestClientException; /** * Execute the HTTP method to the given URI template, writing the given request entity to the request, and - * returns the response as {@link HttpEntity}. + * returns the response as {@link ResponseEntity}. *

    URI Template variables are expanded using the given URI variables, if any. * @param url the URL * @param method the HTTP method (GET, POST, etc) @@ -379,12 +380,12 @@ public interface RestOperations { * @return the response as entity * @since 3.0.2 */ - HttpEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, + ResponseEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, Class responseType, Map uriVariables) throws RestClientException; /** * Execute the HTTP method to the given URI template, writing the given request entity to the request, and - * returns the response as {@link HttpEntity}. + * returns the response as {@link ResponseEntity}. * @param url the URL * @param method the HTTP method (GET, POST, etc) * @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null} @@ -392,7 +393,7 @@ public interface RestOperations { * @return the response as entity * @since 3.0.2 */ - HttpEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, + ResponseEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, Class responseType) throws RestClientException; // general execution diff --git a/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java b/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java index ceb2444e6fc..d6490067901 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -29,6 +29,7 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; @@ -212,26 +213,26 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return execute(url, HttpMethod.GET, requestCallback, responseExtractor); } - public HttpEntity getForEntity(String url, Class responseType, Object... urlVariables) + public ResponseEntity getForEntity(String url, Class responseType, Object... urlVariables) throws RestClientException { AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables); } - public HttpEntity getForEntity(String url, Class responseType, Map urlVariables) + public ResponseEntity getForEntity(String url, Class responseType, Map urlVariables) throws RestClientException { AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables); } - public HttpEntity getForEntity(URI url, Class responseType) throws RestClientException { + public ResponseEntity getForEntity(URI url, Class responseType) throws RestClientException { AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback(responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor); } @@ -293,11 +294,11 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return execute(url, HttpMethod.POST, requestCallback, responseExtractor); } - public HttpEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables) + public ResponseEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(request, responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); } @@ -307,15 +308,15 @@ public class RestTemplate extends HttpAccessor implements RestOperations { Map uriVariables) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(request, responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); } - public HttpEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException { + public ResponseEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(request, responseType); - HttpEntityResponseExtractor responseExtractor = - new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = + new ResponseEntityResponseExtractor(responseType); return execute(url, HttpMethod.POST, requestCallback, responseExtractor); } @@ -369,24 +370,24 @@ public class RestTemplate extends HttpAccessor implements RestOperations { // exchange - public HttpEntity exchange(String url, HttpMethod method, + public ResponseEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, Class responseType, Object... uriVariables) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(requestEntity, responseType); - HttpEntityResponseExtractor responseExtractor = new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = new ResponseEntityResponseExtractor(responseType); return execute(url, method, requestCallback, responseExtractor, uriVariables); } - public HttpEntity exchange(String url, HttpMethod method, + public ResponseEntity exchange(String url, HttpMethod method, HttpEntity requestEntity, Class responseType, Map uriVariables) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(requestEntity, responseType); - HttpEntityResponseExtractor responseExtractor = new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = new ResponseEntityResponseExtractor(responseType); return execute(url, method, requestCallback, responseExtractor, uriVariables); } - public HttpEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, + public ResponseEntity exchange(URI url, HttpMethod method, HttpEntity requestEntity, Class responseType) throws RestClientException { HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(requestEntity, responseType); - HttpEntityResponseExtractor responseExtractor = new HttpEntityResponseExtractor(responseType); + ResponseEntityResponseExtractor responseExtractor = new ResponseEntityResponseExtractor(responseType); return execute(url, method, requestCallback, responseExtractor); } @@ -601,11 +602,11 @@ public class RestTemplate extends HttpAccessor implements RestOperations { /** * Response extractor for {@link HttpEntity}. */ - private class HttpEntityResponseExtractor implements ResponseExtractor> { + private class ResponseEntityResponseExtractor implements ResponseExtractor> { private final HttpMessageConverterExtractor delegate; - public HttpEntityResponseExtractor(Class responseType) { + public ResponseEntityResponseExtractor(Class responseType) { if (responseType != null) { this.delegate = new HttpMessageConverterExtractor(responseType, getMessageConverters(), logger); } else { @@ -613,13 +614,13 @@ public class RestTemplate extends HttpAccessor implements RestOperations { } } - public HttpEntity extractData(ClientHttpResponse response) throws IOException { + public ResponseEntity extractData(ClientHttpResponse response) throws IOException { if (delegate != null) { T body = delegate.extractData(response); - return new HttpEntity(body, response.getHeaders()); + return new ResponseEntity(body, response.getHeaders(), response.getStatusCode()); } else { - return new HttpEntity(response.getHeaders()); + return new ResponseEntity(response.getHeaders(), response.getStatusCode()); } } } diff --git a/org.springframework.web/src/test/java/org/springframework/http/HttpEntityTests.java b/org.springframework.web/src/test/java/org/springframework/http/HttpEntityTests.java index 66dc4024226..a769027a009 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/HttpEntityTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/HttpEntityTests.java @@ -16,9 +16,6 @@ package org.springframework.http; -import java.util.LinkedHashMap; -import java.util.Map; - import static org.junit.Assert.*; import org.junit.Test; @@ -39,10 +36,13 @@ public class HttpEntityTests { } @Test - public void contentType() { - MediaType contentType = MediaType.TEXT_PLAIN; - HttpEntity entity = new HttpEntity("foo", contentType); - assertEquals(contentType, entity.getHeaders().getContentType()); + public void httpHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.TEXT_PLAIN); + String body = "foo"; + HttpEntity entity = new HttpEntity(body, headers); + assertEquals(body, entity.getBody()); + assertEquals(MediaType.TEXT_PLAIN, entity.getHeaders().getContentType()); assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type")); } @@ -50,18 +50,24 @@ public class HttpEntityTests { public void multiValueMap() { MultiValueMap map = new LinkedMultiValueMap(); map.set("Content-Type", "text/plain"); - HttpEntity entity = new HttpEntity("foo", map); + String body = "foo"; + HttpEntity entity = new HttpEntity(body, map); + assertEquals(body, entity.getBody()); assertEquals(MediaType.TEXT_PLAIN, entity.getHeaders().getContentType()); assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type")); } - + @Test - public void map() { - Map map = new LinkedHashMap(); - map.put("Content-Type", "text/plain"); - HttpEntity entity = new HttpEntity("foo", map); + public void responseEntity() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.TEXT_PLAIN); + String body = "foo"; + ResponseEntity entity = new ResponseEntity(body, headers, HttpStatus.OK); + assertEquals(body, entity.getBody()); assertEquals(MediaType.TEXT_PLAIN, entity.getHeaders().getContentType()); assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type")); + assertEquals("text/plain", entity.getHeaders().getFirst("Content-Type")); + } } diff --git a/org.springframework.web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java b/org.springframework.web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java index 55dd963447e..0c9c5d9abd4 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/converter/FormHttpMessageConverterTests.java @@ -37,6 +37,7 @@ import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.MockHttpInputMessage; import org.springframework.http.MockHttpOutputMessage; @@ -109,7 +110,9 @@ public class FormHttpMessageConverterTests { Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg"); parts.add("logo", logo); Source xml = new StreamSource(new StringReader("")); - HttpEntity entity = new HttpEntity(xml, MediaType.TEXT_XML); + HttpHeaders entityHeaders = new HttpHeaders(); + entityHeaders.setContentType(MediaType.TEXT_XML); + HttpEntity entity = new HttpEntity(xml, entityHeaders); parts.add("xml", entity); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); diff --git a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java index ae4a8370d98..78fa26c6f04 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java @@ -52,7 +52,9 @@ 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.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.http.client.CommonsClientHttpRequestFactory; import org.springframework.util.FileCopyUtils; import org.springframework.util.LinkedMultiValueMap; @@ -109,10 +111,11 @@ public class RestTemplateIntegrationTests { @Test public void getEntity() { - HttpEntity entity = template.getForEntity(URI + "/{method}", String.class, "get"); + ResponseEntity entity = template.getForEntity(URI + "/{method}", String.class, "get"); assertEquals("Invalid content", helloWorld, entity.getBody()); assertFalse("No headers", entity.getHeaders().isEmpty()); assertEquals("Invalid content-type", contentType, entity.getHeaders().getContentType()); + assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode()); } @Test @@ -129,7 +132,9 @@ public class RestTemplateIntegrationTests { @Test public void postForLocationEntity() throws URISyntaxException { - HttpEntity entity = new HttpEntity(helloWorld, new MediaType("text", "plain", Charset.forName("ISO-8859-15"))); + HttpHeaders entityHeaders = new HttpHeaders(); + entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15"))); + HttpEntity entity = new HttpEntity(helloWorld, entityHeaders); URI location = template.postForLocation(URI + "/{method}", entity, "post"); assertEquals("Invalid location", new URI(URI + "/post/1"), location); } @@ -183,7 +188,7 @@ public class RestTemplateIntegrationTests { HttpHeaders requestHeaders = new HttpHeaders(); requestHeaders.set("MyHeader", "MyValue"); HttpEntity requestEntity = new HttpEntity(requestHeaders); - HttpEntity response = + ResponseEntity response = template.exchange(URI + "/{method}", HttpMethod.GET, requestEntity, String.class, "get"); assertEquals("Invalid content", helloWorld, response.getBody()); } diff --git a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateTests.java b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateTests.java index aa3217777c0..0f83e8b8e22 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateTests.java @@ -33,6 +33,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.ResponseEntity; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; @@ -194,14 +195,16 @@ public class RestTemplateTests { expect(converter.canRead(String.class, textPlain)).andReturn(true); String expected = "Hello World"; expect(converter.read(String.class, response)).andReturn(expected); + expect(response.getStatusCode()).andReturn(HttpStatus.OK); response.close(); replayMocks(); - HttpEntity result = template.getForEntity("http://example.com", String.class); + ResponseEntity result = template.getForEntity("http://example.com", String.class); assertEquals("Invalid GET result", expected, result.getBody()); assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept")); assertEquals("Invalid Content-Type header", textPlain, result.getHeaders().getContentType()); + assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode()); verifyMocks(); } @@ -265,7 +268,9 @@ public class RestTemplateTests { replayMocks(); - HttpEntity entity = new HttpEntity(helloWorld, contentType); + HttpHeaders entityHeaders = new HttpHeaders(); + entityHeaders.setContentType(contentType); + HttpEntity entity = new HttpEntity(helloWorld, entityHeaders); URI result = template.postForLocation("http://example.com", entity); assertEquals("Invalid POST result", expected, result); @@ -291,7 +296,9 @@ public class RestTemplateTests { replayMocks(); - HttpEntity entity = new HttpEntity(helloWorld, Collections.singletonMap("MyHeader", "MyValue")); + HttpHeaders entityHeaders = new HttpHeaders(); + entityHeaders.set("MyHeader", "MyValue"); + HttpEntity entity = new HttpEntity(helloWorld, entityHeaders); URI result = template.postForLocation("http://example.com", entity); assertEquals("Invalid POST result", expected, result); @@ -387,14 +394,16 @@ public class RestTemplateTests { Integer expected = 42; expect(converter.canRead(Integer.class, textPlain)).andReturn(true); expect(converter.read(Integer.class, response)).andReturn(expected); + expect(response.getStatusCode()).andReturn(HttpStatus.OK); response.close(); replayMocks(); - HttpEntity result = template.postForEntity("http://example.com", request, Integer.class); + ResponseEntity result = template.postForEntity("http://example.com", request, Integer.class); assertEquals("Invalid POST result", expected, result.getBody()); assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType()); assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept")); + assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode()); verifyMocks(); } @@ -439,13 +448,15 @@ public class RestTemplateTests { expect(response.getHeaders()).andReturn(responseHeaders).times(2); expect(converter.canRead(Integer.class, textPlain)).andReturn(true); expect(converter.read(Integer.class, response)).andReturn(null); + expect(response.getStatusCode()).andReturn(HttpStatus.OK); response.close(); replayMocks(); - HttpEntity result = template.postForEntity("http://example.com", null, Integer.class); + ResponseEntity result = template.postForEntity("http://example.com", null, Integer.class); assertFalse("Invalid POST result", result.hasBody()); assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType()); assertEquals("Invalid content length", 0, requestHeaders.getContentLength()); + assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode()); verifyMocks(); } @@ -557,16 +568,20 @@ public class RestTemplateTests { Integer expected = 42; expect(converter.canRead(Integer.class, textPlain)).andReturn(true); expect(converter.read(Integer.class, response)).andReturn(expected); + expect(response.getStatusCode()).andReturn(HttpStatus.OK); response.close(); replayMocks(); - HttpEntity requestEntity = new HttpEntity(body, Collections.singletonMap("MyHeader", "MyValue")); - HttpEntity result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, Integer.class); + HttpHeaders entityHeaders = new HttpHeaders(); + entityHeaders.set("MyHeader", "MyValue"); + HttpEntity requestEntity = new HttpEntity(body, entityHeaders); + ResponseEntity result = template.exchange("http://example.com", HttpMethod.POST, requestEntity, Integer.class); assertEquals("Invalid POST result", expected, result.getBody()); assertEquals("Invalid Content-Type", textPlain, result.getHeaders().getContentType()); assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept")); assertEquals("Invalid custom header", "MyValue", requestHeaders.getFirst("MyHeader")); + assertEquals("Invalid status code", HttpStatus.OK, result.getStatusCode()); verifyMocks(); } diff --git a/org.springframework.web/web.iml b/org.springframework.web/web.iml index ebd7a059f0f..7f310042ad5 100644 --- a/org.springframework.web/web.iml +++ b/org.springframework.web/web.iml @@ -1,228 +1,239 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-framework-reference/src/mvc.xml b/spring-framework-reference/src/mvc.xml index 8203a1d1265..b2d4b77c9da 100644 --- a/spring-framework-reference/src/mvc.xml +++ b/spring-framework-reference/src/mvc.xml @@ -1154,7 +1154,8 @@ public class RelativePathUriTemplateController { - A HttpEntity<?>} object + A HttpEntity<?> or + ResponseEntity<?> object to access to the Servlet reponse HTTP headers and contents. The entity body will be converted to the response stream using HttpMessageConverters. See The HttpEntity is similar to @RequestBody and @ResponseBody. Besides getting - access to the request and response body, the HttpEntity + access to the request and response body, HttpEntity + (and the response-specific subclass ResponseEntity) also allows access to the request and response headers, like so: @RequestMapping("/something") -public HttpEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException { +public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException { String requestHeader = requestEntity.getHeaders().getFirst("MyRequestHeader")); byte[] requestBody = requestEntity.getBody(); // do something with request header and body HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set("MyResponseHeader", "MyValue"); - return new HttpEntity<String>("Hello World", responseHeaders); + return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED); } The above example gets the value of the "MyRequestHeader" request header, and reads the body as a byte array. It adds the "MyResponseHeader" - to the response, and writes Hello World to the response - stream. + to the response, writes Hello World to the response + stream, and sets the response status code to 201 (Created). As with @RequestBody and @ResponseBody, Spring