Skip to content

Commit 689e7b7

Browse files
committed
Introduced ResponseEntity, for access to the response status code
1 parent 636e2f0 commit 689e7b7

File tree

13 files changed

+438
-360
lines changed

13 files changed

+438
-360
lines changed

org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@
6161
import org.springframework.http.HttpOutputMessage;
6262
import org.springframework.http.HttpStatus;
6363
import org.springframework.http.MediaType;
64+
import org.springframework.http.ResponseEntity;
6465
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
6566
import org.springframework.http.converter.FormHttpMessageConverter;
6667
import org.springframework.http.converter.HttpMessageConverter;
6768
import org.springframework.http.converter.StringHttpMessageConverter;
6869
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
6970
import org.springframework.http.server.ServerHttpRequest;
71+
import org.springframework.http.server.ServerHttpResponse;
7072
import org.springframework.http.server.ServletServerHttpRequest;
7173
import org.springframework.http.server.ServletServerHttpResponse;
7274
import org.springframework.ui.ExtendedModelMap;
@@ -895,6 +897,9 @@ private void handleHttpEntityResponse(HttpEntity<?> responseEntity, ServletWebRe
895897
}
896898
HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
897899
HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
900+
if (responseEntity instanceof ResponseEntity && outputMessage instanceof ServerHttpResponse) {
901+
((ServerHttpResponse)outputMessage).setStatusCode(((ResponseEntity) responseEntity).getStatusCode());
902+
}
898903
HttpHeaders entityHeaders = responseEntity.getHeaders();
899904
if (!entityHeaders.isEmpty()) {
900905
outputMessage.getHeaders().putAll(entityHeaders);

org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/annotation/ServletAnnotationControllerTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.springframework.http.HttpOutputMessage;
7676
import org.springframework.http.HttpStatus;
7777
import org.springframework.http.MediaType;
78+
import org.springframework.http.ResponseEntity;
7879
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
7980
import org.springframework.http.converter.HttpMessageConverter;
8081
import org.springframework.http.converter.HttpMessageNotReadableException;
@@ -1201,7 +1202,7 @@ public void httpEntity() throws ServletException, IOException {
12011202
request.addHeader("MyRequestHeader", "MyValue");
12021203
MockHttpServletResponse response = new MockHttpServletResponse();
12031204
servlet.service(request, response);
1204-
assertEquals(200, response.getStatus());
1205+
assertEquals(201, response.getStatus());
12051206
assertEquals(requestBody, response.getContentAsString());
12061207
assertEquals("MyValue", response.getHeader("MyResponseHeader"));
12071208
}
@@ -2598,15 +2599,15 @@ public void templatePath(Writer writer) throws IOException {
25982599
public static class HttpEntityController {
25992600

26002601
@RequestMapping("/handle")
2601-
public HttpEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException {
2602+
public ResponseEntity<String> handle(HttpEntity<byte[]> requestEntity) throws UnsupportedEncodingException {
26022603
assertNotNull(requestEntity);
26032604
assertEquals("MyValue", requestEntity.getHeaders().getFirst("MyRequestHeader"));
26042605
String requestBody = new String(requestEntity.getBody(), "UTF-8");
26052606
assertEquals("Hello World", requestBody);
26062607

26072608
HttpHeaders responseHeaders = new HttpHeaders();
26082609
responseHeaders.set("MyResponseHeader", "MyValue");
2609-
return new HttpEntity<String>(requestBody, responseHeaders);
2610+
return new ResponseEntity<String>(requestBody, responseHeaders, HttpStatus.CREATED);
26102611
}
26112612
}
26122613

org.springframework.web/src/main/java/org/springframework/http/HttpEntity.java

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package org.springframework.http;
1818

19-
import java.util.Map;
20-
21-
import org.springframework.util.LinkedMultiValueMap;
2219
import org.springframework.util.MultiValueMap;
2320

2421
/**
@@ -35,6 +32,15 @@
3532
* String body = entity.getBody();
3633
* MediaType contentType = entity.getHeaders().getContentType();
3734
* </pre>
35+
* Can also be used in Spring MVC, as a return value from a @Controller method:
36+
* <pre>
37+
* &#64;RequestMapping("/handle")
38+
* public HttpEntity&ltString&gt handle() {
39+
* HttpHeaders responseHeaders = new HttpHeaders();
40+
* responseHeaders.set("MyResponseHeader", "MyValue");
41+
* return new HttpEntity<String>("Hello World", responseHeaders);
42+
* }
43+
* </pre>
3844
*
3945
* @author Arjen Poutsma
4046
* @since 3.0.2
@@ -59,23 +65,15 @@ public class HttpEntity<T> {
5965
* Create a new, empty {@code HttpEntity}.
6066
*/
6167
private HttpEntity() {
62-
this(null, (MultiValueMap<String, String>) null);
68+
this(null, null);
6369
}
6470

6571
/**
6672
* Create a new {@code HttpEntity} with the given body and no headers.
6773
* @param body the entity body
6874
*/
6975
public HttpEntity(T body) {
70-
this(body, (MultiValueMap<String, String>) null);
71-
}
72-
73-
/**
74-
* Create a new {@code HttpEntity} with the given headers and no body.
75-
* @param headers the entity headers
76-
*/
77-
public HttpEntity(Map<String, String> headers) {
78-
this(null, toMultiValueMap(headers));
76+
this(body, null);
7977
}
8078

8179
/**
@@ -86,24 +84,6 @@ public HttpEntity(MultiValueMap<String, String> headers) {
8684
this(null, headers);
8785
}
8886

89-
/**
90-
* Create a new {@code HttpEntity} with the given body and {@code Content-Type} header value.
91-
* @param body the entity body
92-
* @param contentType the value of the {@code Content-Type header}
93-
*/
94-
public HttpEntity(T body, MediaType contentType) {
95-
this(body, toMultiValueMap(contentType));
96-
}
97-
98-
/**
99-
* Create a new {@code HttpEntity} with the given body and headers.
100-
* @param body the entity body
101-
* @param headers the entity headers
102-
*/
103-
public HttpEntity(T body, Map<String, String> headers) {
104-
this(body, toMultiValueMap(headers));
105-
}
106-
10787
/**
10888
* Create a new {@code HttpEntity} with the given body and headers.
10989
* @param body the entity body
@@ -140,27 +120,4 @@ public boolean hasBody() {
140120
return (this.body != null);
141121
}
142122

143-
144-
private static MultiValueMap<String, String> toMultiValueMap(Map<String, String> map) {
145-
if (map == null) {
146-
return null;
147-
}
148-
else {
149-
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(map.size());
150-
result.setAll(map);
151-
return result;
152-
}
153-
}
154-
155-
private static MultiValueMap<String, String> toMultiValueMap(MediaType contentType) {
156-
if (contentType == null) {
157-
return null;
158-
}
159-
else {
160-
HttpHeaders result = new HttpHeaders();
161-
result.setContentType(contentType);
162-
return result;
163-
}
164-
}
165-
166123
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2002-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.http;
18+
19+
import org.springframework.util.MultiValueMap;
20+
21+
/**
22+
* Extension of {@link HttpEntity} that adds a {@link HttpStatus} status code.
23+
*
24+
* @author Arjen Poutsma
25+
* @since 3.0.2
26+
* @see #getStatusCode()
27+
*/
28+
public class ResponseEntity<T> extends HttpEntity<T> {
29+
30+
private final HttpStatus statusCode;
31+
32+
/**
33+
* Create a new {@code ResponseEntity} with the given body and status code, and no headers.
34+
* @param body the entity body
35+
* @param statusCode the status code
36+
*/
37+
public ResponseEntity(T body, HttpStatus statusCode) {
38+
super(body);
39+
this.statusCode = statusCode;
40+
}
41+
42+
/**
43+
* Create a new {@code HttpEntity} with the given headers and status code, and no body.
44+
* @param headers the entity headers
45+
* @param statusCode the status code
46+
*/
47+
public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus statusCode) {
48+
super(headers);
49+
this.statusCode = statusCode;
50+
}
51+
52+
/**
53+
* Create a new {@code HttpEntity} with the given body, headers, and status code.
54+
* @param body the entity body
55+
* @param headers the entity headers
56+
* @param statusCode the status code
57+
*/
58+
public ResponseEntity(T body, MultiValueMap<String, String> headers, HttpStatus statusCode) {
59+
super(body, headers);
60+
this.statusCode = statusCode;
61+
}
62+
63+
/**
64+
* Return the HTTP status code of the response.
65+
* @return the HTTP status as an HttpStatus enum value
66+
*/
67+
public HttpStatus getStatusCode() {
68+
return statusCode;
69+
}
70+
}

org.springframework.web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@
151151
* to the response stream using
152152
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
153153
* converters}.
154-
* <li>A {@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} object
154+
* <li>A {@link org.springframework.http.HttpEntity HttpEntity&lt;?&gt;} or
155+
* {@link org.springframework.http.ResponseEntity ResponseEntity&lt;?&gt;} object
155156
* to access to the Servlet reponse HTTP headers and contents. The entity body will
156157
* be converted to the response stream using
157158
* {@linkplain org.springframework.http.converter.HttpMessageConverter message

org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.http.HttpEntity;
2424
import org.springframework.http.HttpHeaders;
2525
import org.springframework.http.HttpMethod;
26+
import org.springframework.http.ResponseEntity;
2627

2728
/**
2829
* Interface specifying a basic set of RESTful operations. Implemented by {@link RestTemplate}.
@@ -71,37 +72,37 @@ public interface RestOperations {
7172

7273
/**
7374
* Retrieve an entity by doing a GET on the specified URL.
74-
* The response is converted and stored in an {@link HttpEntity}.
75+
* The response is converted and stored in an {@link ResponseEntity}.
7576
* <p>URI Template variables are expanded using the given URI variables, if any.
7677
* @param url the URL
7778
* @param responseType the type of the return value
7879
* @param uriVariables the variables to expand the template
7980
* @return the entity
8081
* @since 3.0.2
8182
*/
82-
<T> HttpEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
83+
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
8384

8485
/**
8586
* Retrieve a representation by doing a GET on the URI template.
86-
* The response is converted and stored in an {@link HttpEntity}.
87+
* The response is converted and stored in an {@link ResponseEntity}.
8788
* <p>URI Template variables are expanded using the given map.
8889
* @param url the URL
8990
* @param responseType the type of the return value
9091
* @param uriVariables the map containing variables for the URI template
9192
* @return the converted object
9293
* @since 3.0.2
9394
*/
94-
<T> HttpEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
95+
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
9596

9697
/**
9798
* Retrieve a representation by doing a GET on the URL .
98-
* The response is converted and stored in an {@link HttpEntity}.
99+
* The response is converted and stored in an {@link ResponseEntity}.
99100
* @param url the URL
100101
* @param responseType the type of the return value
101102
* @return the converted object
102103
* @since 3.0.2
103104
*/
104-
<T> HttpEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
105+
<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
105106

106107
// HEAD
107108

@@ -219,7 +220,7 @@ <T> T postForObject(String url, Object request, Class<T> responseType, Map<Strin
219220

220221
/**
221222
* Create a new resource by POSTing the given object to the URI template,
222-
* and returns the response as {@link HttpEntity}.
223+
* and returns the response as {@link ResponseEntity}.
223224
* <p>URI Template variables are expanded using the given URI variables, if any.
224225
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
225226
* add additional HTTP headers to the request.
@@ -230,7 +231,7 @@ <T> T postForObject(String url, Object request, Class<T> responseType, Map<Strin
230231
* @see HttpEntity
231232
* @since 3.0.2
232233
*/
233-
<T> HttpEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
234+
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
234235
throws RestClientException;
235236

236237
/**
@@ -251,7 +252,7 @@ <T> HttpEntity<T> postForEntity(String url, Object request, Class<T> responseTyp
251252

252253
/**
253254
* Create a new resource by POSTing the given object to the URL,
254-
* and returns the response as {@link HttpEntity}.
255+
* and returns the response as {@link ResponseEntity}.
255256
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
256257
* add additional HTTP headers to the request.
257258
* @param url the URL
@@ -260,7 +261,7 @@ <T> HttpEntity<T> postForEntity(String url, Object request, Class<T> responseTyp
260261
* @see HttpEntity
261262
* @since 3.0.2
262263
*/
263-
<T> HttpEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
264+
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
264265

265266
// PUT
266267

@@ -354,7 +355,7 @@ <T> HttpEntity<T> postForEntity(String url, Object request, Class<T> responseTyp
354355

355356
/**
356357
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
357-
* returns the response as {@link HttpEntity}.
358+
* returns the response as {@link ResponseEntity}.
358359
* <p>URI Template variables are expanded using the given URI variables, if any.
359360
* @param url the URL
360361
* @param method the HTTP method (GET, POST, etc)
@@ -364,12 +365,12 @@ <T> HttpEntity<T> postForEntity(String url, Object request, Class<T> responseTyp
364365
* @return the response as entity
365366
* @since 3.0.2
366367
*/
367-
<T> HttpEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
368+
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
368369
Class<T> responseType, Object... uriVariables) throws RestClientException;
369370

370371
/**
371372
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
372-
* returns the response as {@link HttpEntity}.
373+
* returns the response as {@link ResponseEntity}.
373374
* <p>URI Template variables are expanded using the given URI variables, if any.
374375
* @param url the URL
375376
* @param method the HTTP method (GET, POST, etc)
@@ -379,20 +380,20 @@ <T> HttpEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestE
379380
* @return the response as entity
380381
* @since 3.0.2
381382
*/
382-
<T> HttpEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
383+
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
383384
Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
384385

385386
/**
386387
* Execute the HTTP method to the given URI template, writing the given request entity to the request, and
387-
* returns the response as {@link HttpEntity}.
388+
* returns the response as {@link ResponseEntity}.
388389
* @param url the URL
389390
* @param method the HTTP method (GET, POST, etc)
390391
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
391392
* @param responseType the type of the return value
392393
* @return the response as entity
393394
* @since 3.0.2
394395
*/
395-
<T> HttpEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
396+
<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
396397
Class<T> responseType) throws RestClientException;
397398

398399
// general execution

0 commit comments

Comments
 (0)