1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.client;
18
19 import java.net.URI;
20 import java.nio.charset.Charset;
21 import java.util.EnumSet;
22 import java.util.Set;
23 import java.util.concurrent.Future;
24
25 import org.junit.Before;
26 import org.junit.Test;
27
28 import org.springframework.core.io.ClassPathResource;
29 import org.springframework.core.io.Resource;
30 import org.springframework.http.HttpEntity;
31 import org.springframework.http.HttpHeaders;
32 import org.springframework.http.HttpMethod;
33 import org.springframework.http.HttpStatus;
34 import org.springframework.http.MediaType;
35 import org.springframework.http.ResponseEntity;
36 import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
37 import org.springframework.util.LinkedMultiValueMap;
38 import org.springframework.util.MultiValueMap;
39 import org.springframework.util.concurrent.ListenableFuture;
40 import org.springframework.util.concurrent.ListenableFutureCallback;
41
42 import static org.junit.Assert.*;
43
44
45
46
47
48 public class AsyncRestTemplateIntegrationTests extends AbstractJettyServerTestCase {
49
50 private AsyncRestTemplate template;
51
52
53 @Before
54 public void createTemplate() {
55 template = new AsyncRestTemplate(new HttpComponentsAsyncClientHttpRequestFactory());
56 }
57
58
59 @Test
60 public void getEntity() throws Exception {
61 Future<ResponseEntity<String>> futureEntity =
62 template.getForEntity(baseUrl + "/{method}", String.class, "get");
63 ResponseEntity<String> entity = futureEntity.get();
64 assertEquals("Invalid content", helloWorld, entity.getBody());
65 assertFalse("No headers", entity.getHeaders().isEmpty());
66 assertEquals("Invalid content-type", textContentType, entity.getHeaders().getContentType());
67 assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode());
68 }
69
70 @Test
71 public void multipleFutureGets() throws Exception {
72 Future<ResponseEntity<String>> futureEntity =
73 template.getForEntity(baseUrl + "/{method}", String.class, "get");
74 futureEntity.get();
75 futureEntity.get();
76 }
77
78 @Test
79 public void getEntityCallback() throws Exception {
80 ListenableFuture<ResponseEntity<String>> futureEntity =
81 template.getForEntity(baseUrl + "/{method}", String.class, "get");
82 futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
83 @Override
84 public void onSuccess(ResponseEntity<String> entity) {
85 assertEquals("Invalid content", helloWorld, entity.getBody());
86 assertFalse("No headers", entity.getHeaders().isEmpty());
87 assertEquals("Invalid content-type", textContentType, entity.getHeaders().getContentType());
88 assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode());
89 }
90 @Override
91 public void onFailure(Throwable ex) {
92 fail(ex.getMessage());
93 }
94 });
95
96 while (!futureEntity.isDone()) {
97 }
98 }
99
100 @Test
101 public void getEntityCallbackWithLambdas() throws Exception {
102 ListenableFuture<ResponseEntity<String>> futureEntity =
103 template.getForEntity(baseUrl + "/{method}", String.class, "get");
104 futureEntity.addCallback((entity) -> {
105 assertEquals("Invalid content", helloWorld, entity.getBody());
106 assertFalse("No headers", entity.getHeaders().isEmpty());
107 assertEquals("Invalid content-type", textContentType, entity.getHeaders().getContentType());
108 assertEquals("Invalid status code", HttpStatus.OK, entity.getStatusCode());
109 }, ex -> fail(ex.getMessage()));
110
111 while (!futureEntity.isDone()) {
112 }
113 }
114
115 @Test
116 public void getNoResponse() throws Exception {
117 Future<ResponseEntity<String>> futureEntity = template.getForEntity(baseUrl + "/get/nothing", String.class);
118 ResponseEntity<String> entity = futureEntity.get();
119 assertNull("Invalid content", entity.getBody());
120 }
121
122
123 @Test
124 public void getNoContentTypeHeader() throws Exception {
125 Future<ResponseEntity<byte[]>> futureEntity = template.getForEntity(baseUrl + "/get/nocontenttype", byte[].class);
126 ResponseEntity<byte[]> responseEntity = futureEntity.get();
127 assertArrayEquals("Invalid content", helloWorld.getBytes("UTF-8"), responseEntity.getBody());
128 }
129
130
131 @Test
132 public void getNoContent() throws Exception {
133 Future<ResponseEntity<String>> responseFuture = template.getForEntity(baseUrl + "/status/nocontent", String.class);
134 ResponseEntity<String> entity = responseFuture.get();
135 assertEquals("Invalid response code", HttpStatus.NO_CONTENT, entity.getStatusCode());
136 assertNull("Invalid content", entity.getBody());
137 }
138
139 @Test
140 public void getNotModified() throws Exception {
141 Future<ResponseEntity<String>> responseFuture = template.getForEntity(baseUrl + "/status/notmodified", String.class);
142 ResponseEntity<String> entity = responseFuture.get();
143 assertEquals("Invalid response code", HttpStatus.NOT_MODIFIED, entity.getStatusCode());
144 assertNull("Invalid content", entity.getBody());
145 }
146
147 @Test
148 public void headForHeaders() throws Exception {
149 Future<HttpHeaders> headersFuture = template.headForHeaders(baseUrl + "/get");
150 HttpHeaders headers = headersFuture.get();
151 assertTrue("No Content-Type header", headers.containsKey("Content-Type"));
152 }
153
154 @Test
155 public void headForHeadersCallback() throws Exception {
156 ListenableFuture<HttpHeaders> headersFuture = template.headForHeaders(baseUrl + "/get");
157 headersFuture.addCallback(new ListenableFutureCallback<HttpHeaders>() {
158 @Override
159 public void onSuccess(HttpHeaders result) {
160 assertTrue("No Content-Type header", result.containsKey("Content-Type"));
161 }
162 @Override
163 public void onFailure(Throwable ex) {
164 fail(ex.getMessage());
165 }
166 });
167 while (!headersFuture.isDone()) {
168 }
169 }
170
171 @Test
172 public void headForHeadersCallbackWithLambdas() throws Exception {
173 ListenableFuture<HttpHeaders> headersFuture = template.headForHeaders(baseUrl + "/get");
174 headersFuture.addCallback(result -> assertTrue("No Content-Type header",
175 result.containsKey("Content-Type")), ex -> fail(ex.getMessage()));
176 while (!headersFuture.isDone()) {
177 }
178 }
179
180 @Test
181 public void postForLocation() throws Exception {
182 HttpHeaders entityHeaders = new HttpHeaders();
183 entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
184 HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
185 Future<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
186 URI location = locationFuture.get();
187 assertEquals("Invalid location", new URI(baseUrl + "/post/1"), location);
188 }
189
190 @Test
191 public void postForLocationCallback() throws Exception {
192 HttpHeaders entityHeaders = new HttpHeaders();
193 entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
194 HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
195 final URI expected = new URI(baseUrl + "/post/1");
196 ListenableFuture<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
197 locationFuture.addCallback(new ListenableFutureCallback<URI>() {
198 @Override
199 public void onSuccess(URI result) {
200 assertEquals("Invalid location", expected, result);
201 }
202 @Override
203 public void onFailure(Throwable ex) {
204 fail(ex.getMessage());
205 }
206 });
207 while (!locationFuture.isDone()) {
208 }
209 }
210
211 @Test
212 public void postForLocationCallbackWithLambdas() throws Exception {
213 HttpHeaders entityHeaders = new HttpHeaders();
214 entityHeaders.setContentType(new MediaType("text", "plain", Charset.forName("ISO-8859-15")));
215 HttpEntity<String> entity = new HttpEntity<String>(helloWorld, entityHeaders);
216 final URI expected = new URI(baseUrl + "/post/1");
217 ListenableFuture<URI> locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post");
218 locationFuture.addCallback(result -> assertEquals("Invalid location", expected, result),
219 ex -> fail(ex.getMessage()));
220 while (!locationFuture.isDone()) {
221 }
222 }
223
224 @Test
225 public void postForEntity() throws Exception {
226 HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
227 Future<ResponseEntity<String>> responseEntityFuture =
228 template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post");
229 ResponseEntity<String> responseEntity = responseEntityFuture.get();
230 assertEquals("Invalid content", helloWorld, responseEntity.getBody());
231 }
232
233 @Test
234 public void postForEntityCallback() throws Exception {
235 HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
236 ListenableFuture<ResponseEntity<String>> responseEntityFuture =
237 template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post");
238 responseEntityFuture.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
239 @Override
240 public void onSuccess(ResponseEntity<String> result) {
241 assertEquals("Invalid content", helloWorld, result.getBody());
242 }
243 @Override
244 public void onFailure(Throwable ex) {
245 fail(ex.getMessage());
246 }
247 });
248 while (!responseEntityFuture.isDone()) {
249 }
250 }
251
252 @Test
253 public void postForEntityCallbackWithLambdas() throws Exception {
254 HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
255 ListenableFuture<ResponseEntity<String>> responseEntityFuture =
256 template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post");
257 responseEntityFuture.addCallback(result -> assertEquals("Invalid content", helloWorld, result.getBody()),
258 ex -> fail(ex.getMessage()));
259 while (!responseEntityFuture.isDone()) {
260 }
261 }
262
263 @Test
264 public void put() throws Exception {
265 HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
266 Future<?> responseEntityFuture = template.put(baseUrl + "/{method}", requestEntity, "put");
267 responseEntityFuture.get();
268 }
269
270 @Test
271 public void putCallback() throws Exception {
272 HttpEntity<String> requestEntity = new HttpEntity<>(helloWorld);
273 ListenableFuture<?> responseEntityFuture = template.put(baseUrl + "/{method}", requestEntity, "put");
274 responseEntityFuture.addCallback(new ListenableFutureCallback<Object>() {
275 @Override
276 public void onSuccess(Object result) {
277 assertNull(result);
278 }
279 @Override
280 public void onFailure(Throwable ex) {
281 fail(ex.getMessage());
282 }
283 });
284 while (!responseEntityFuture.isDone()) {
285 }
286 }
287
288 @Test
289 public void delete() throws Exception {
290 Future<?> deletedFuture = template.delete(new URI(baseUrl + "/delete"));
291 deletedFuture.get();
292 }
293
294 @Test
295 public void deleteCallback() throws Exception {
296 ListenableFuture<?> deletedFuture = template.delete(new URI(baseUrl + "/delete"));
297 deletedFuture.addCallback(new ListenableFutureCallback<Object>() {
298 @Override
299 public void onSuccess(Object result) {
300 assertNull(result);
301 }
302 @Override
303 public void onFailure(Throwable ex) {
304 fail(ex.getMessage());
305 }
306 });
307 while (!deletedFuture.isDone()) {
308 }
309 }
310
311 @Test
312 public void deleteCallbackWithLambdas() throws Exception {
313 ListenableFuture<?> deletedFuture = template.delete(new URI(baseUrl + "/delete"));
314 deletedFuture.addCallback(result -> assertNull(result), ex -> fail(ex.getMessage()));
315 while (!deletedFuture.isDone()) {
316 }
317 }
318
319 @Test
320 public void notFound() throws Exception {
321 try {
322 Future<?> future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null);
323 future.get();
324 fail("HttpClientErrorException expected");
325 }
326 catch (HttpClientErrorException ex) {
327 assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode());
328 assertNotNull(ex.getStatusText());
329 assertNotNull(ex.getResponseBodyAsString());
330 }
331 }
332
333 @Test
334 public void notFoundCallback() throws Exception {
335 ListenableFuture<?> future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null);
336 future.addCallback(new ListenableFutureCallback<Object>() {
337 @Override
338 public void onSuccess(Object result) {
339 fail("onSuccess not expected");
340 }
341 @Override
342 public void onFailure(Throwable t) {
343 assertTrue(t instanceof HttpClientErrorException);
344 HttpClientErrorException ex = (HttpClientErrorException) t;
345 assertEquals(HttpStatus.NOT_FOUND, ex.getStatusCode());
346 assertNotNull(ex.getStatusText());
347 assertNotNull(ex.getResponseBodyAsString());
348 }
349 });
350 while (!future.isDone()) {
351 }
352 }
353
354 @Test
355 public void notFoundCallbackWithLambdas() throws Exception {
356 ListenableFuture<?> future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null);
357 future.addCallback(result -> fail("onSuccess not expected"), ex -> {
358 assertTrue(ex instanceof HttpClientErrorException);
359 HttpClientErrorException hcex = (HttpClientErrorException) ex;
360 assertEquals(HttpStatus.NOT_FOUND, hcex.getStatusCode());
361 assertNotNull(hcex.getStatusText());
362 assertNotNull(hcex.getResponseBodyAsString());
363 });
364 while (!future.isDone()) {
365 }
366 }
367
368 @Test
369 public void serverError() throws Exception {
370 try {
371 Future<Void> future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null);
372 future.get();
373 fail("HttpServerErrorException expected");
374 }
375 catch (HttpServerErrorException ex) {
376 assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, ex.getStatusCode());
377 assertNotNull(ex.getStatusText());
378 assertNotNull(ex.getResponseBodyAsString());
379 }
380 }
381
382 @Test
383 public void serverErrorCallback() throws Exception {
384 ListenableFuture<Void> future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null);
385 future.addCallback(new ListenableFutureCallback<Void>() {
386 @Override
387 public void onSuccess(Void result) {
388 fail("onSuccess not expected");
389 }
390 @Override
391 public void onFailure(Throwable ex) {
392 assertTrue(ex instanceof HttpServerErrorException);
393 HttpServerErrorException hsex = (HttpServerErrorException) ex;
394 assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, hsex.getStatusCode());
395 assertNotNull(hsex.getStatusText());
396 assertNotNull(hsex.getResponseBodyAsString());
397 }
398 });
399 while (!future.isDone()) {
400 }
401 }
402
403 @Test
404 public void serverErrorCallbackWithLambdas() throws Exception {
405 ListenableFuture<Void> future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null);
406 future.addCallback(result -> fail("onSuccess not expected"), ex -> {
407 assertTrue(ex instanceof HttpServerErrorException);
408 HttpServerErrorException hsex = (HttpServerErrorException) ex;
409 assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, hsex.getStatusCode());
410 assertNotNull(hsex.getStatusText());
411 assertNotNull(hsex.getResponseBodyAsString());
412 });
413 while (!future.isDone()) {
414 }
415 }
416
417 @Test
418 public void optionsForAllow() throws Exception {
419 Future<Set<HttpMethod>> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get"));
420 Set<HttpMethod> allowed = allowedFuture.get();
421 assertEquals("Invalid response",
422 EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE), allowed);
423 }
424
425 @Test
426 public void optionsForAllowCallback() throws Exception {
427 ListenableFuture<Set<HttpMethod>> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get"));
428 allowedFuture.addCallback(new ListenableFutureCallback<Set<HttpMethod>>() {
429 @Override
430 public void onSuccess(Set<HttpMethod> result) {
431 assertEquals("Invalid response", EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS,
432 HttpMethod.HEAD, HttpMethod.TRACE), result);
433 }
434 @Override
435 public void onFailure(Throwable ex) {
436 fail(ex.getMessage());
437 }
438 });
439 while (!allowedFuture.isDone()) {
440 }
441 }
442
443 @Test
444 public void optionsForAllowCallbackWithLambdas() throws Exception{
445 ListenableFuture<Set<HttpMethod>> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get"));
446 allowedFuture.addCallback(result -> assertEquals("Invalid response",
447 EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD,HttpMethod.TRACE), result),
448 ex -> fail(ex.getMessage()));
449 while (!allowedFuture.isDone()) {
450 }
451 }
452
453 @Test
454 @SuppressWarnings({ "unchecked", "rawtypes" })
455 public void exchangeGet() throws Exception {
456 HttpHeaders requestHeaders = new HttpHeaders();
457 requestHeaders.set("MyHeader", "MyValue");
458 HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
459 Future<ResponseEntity<String>> responseFuture =
460 template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get");
461 ResponseEntity<String> response = responseFuture.get();
462 assertEquals("Invalid content", helloWorld, response.getBody());
463 }
464
465 @Test
466 @SuppressWarnings({ "unchecked", "rawtypes" })
467 public void exchangeGetCallback() throws Exception {
468 HttpHeaders requestHeaders = new HttpHeaders();
469 requestHeaders.set("MyHeader", "MyValue");
470 HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
471 ListenableFuture<ResponseEntity<String>> responseFuture =
472 template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get");
473 responseFuture.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
474 @Override
475 public void onSuccess(ResponseEntity<String> result) {
476 assertEquals("Invalid content", helloWorld, result.getBody());
477 }
478 @Override
479 public void onFailure(Throwable ex) {
480 fail(ex.getMessage());
481 }
482 });
483 while (!responseFuture.isDone()) {
484 }
485 }
486
487 @Test
488 @SuppressWarnings({ "unchecked", "rawtypes" })
489 public void exchangeGetCallbackWithLambdas() throws Exception {
490 HttpHeaders requestHeaders = new HttpHeaders();
491 requestHeaders.set("MyHeader", "MyValue");
492 HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
493 ListenableFuture<ResponseEntity<String>> responseFuture =
494 template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get");
495 responseFuture.addCallback(result -> assertEquals("Invalid content", helloWorld,
496 result.getBody()), ex -> fail(ex.getMessage()));
497 while (!responseFuture.isDone()) {
498 }
499 }
500
501 @Test
502 public void exchangePost() throws Exception {
503 HttpHeaders requestHeaders = new HttpHeaders();
504 requestHeaders.set("MyHeader", "MyValue");
505 requestHeaders.setContentType(MediaType.TEXT_PLAIN);
506 HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
507 Future<ResponseEntity<Void>> resultFuture =
508 template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
509 ResponseEntity<Void> result = resultFuture.get();
510 assertEquals("Invalid location", new URI(baseUrl + "/post/1"),
511 result.getHeaders().getLocation());
512 assertFalse(result.hasBody());
513 }
514
515 @Test
516 public void exchangePostCallback() throws Exception {
517 HttpHeaders requestHeaders = new HttpHeaders();
518 requestHeaders.set("MyHeader", "MyValue");
519 requestHeaders.setContentType(MediaType.TEXT_PLAIN);
520 HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
521 ListenableFuture<ResponseEntity<Void>> resultFuture =
522 template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
523 final URI expected =new URI(baseUrl + "/post/1");
524 resultFuture.addCallback(new ListenableFutureCallback<ResponseEntity<Void>>() {
525 @Override
526 public void onSuccess(ResponseEntity<Void> result) {
527 assertEquals("Invalid location", expected, result.getHeaders().getLocation());
528 assertFalse(result.hasBody());
529 }
530 @Override
531 public void onFailure(Throwable ex) {
532 fail(ex.getMessage());
533 }
534 });
535 while (!resultFuture.isDone()) {
536 }
537 }
538
539 @Test
540 public void exchangePostCallbackWithLambdas() throws Exception {
541 HttpHeaders requestHeaders = new HttpHeaders();
542 requestHeaders.set("MyHeader", "MyValue");
543 requestHeaders.setContentType(MediaType.TEXT_PLAIN);
544 HttpEntity<String> requestEntity = new HttpEntity<String>(helloWorld, requestHeaders);
545 ListenableFuture<ResponseEntity<Void>> resultFuture =
546 template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post");
547 final URI expected =new URI(baseUrl + "/post/1");
548 resultFuture.addCallback(result -> {
549 assertEquals("Invalid location", expected, result.getHeaders().getLocation());
550 assertFalse(result.hasBody());
551 }, ex -> fail(ex.getMessage()));
552 while (!resultFuture.isDone()) {
553 }
554 }
555
556 @Test
557 public void multipart() throws Exception {
558 MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
559 parts.add("name 1", "value 1");
560 parts.add("name 2", "value 2+1");
561 parts.add("name 2", "value 2+2");
562 Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
563 parts.add("logo", logo);
564
565 HttpEntity<MultiValueMap<String, Object>> requestBody = new HttpEntity<>(parts);
566 Future<URI> future = template.postForLocation(baseUrl + "/multipart", requestBody);
567 future.get();
568 }
569
570 }