1
1
/*
2
- * Copyright 2002-2013 the original author or authors.
2
+ * Copyright 2002-2014 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
23
23
import java .util .List ;
24
24
import java .util .Map ;
25
25
import java .util .Set ;
26
+ import javax .xml .transform .Source ;
26
27
27
28
import org .springframework .core .ParameterizedTypeReference ;
28
29
import org .springframework .http .HttpEntity ;
79
80
* {@link #getForObject(String, Class, Map)}), and are capable of substituting any {@linkplain UriTemplate URI templates}
80
81
* in that URL using either a {@code String} variable arguments array, or a {@code Map<String, String>}.
81
82
* The string varargs variant expands the given template variables in order, so that
82
- * <pre>
83
+ * <pre class="code" >
83
84
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42",
84
85
* "21");
85
86
* </pre>
86
87
* will perform a GET on {@code http://example.com/hotels/42/bookings/21}. The map variant expands the template based
87
88
* on variable name, and is therefore more useful when using many variables, or when a single variable is used multiple
88
89
* times. For example:
89
- * <pre>
90
+ * <pre class="code" >
90
91
* Map<String, String> vars = Collections.singletonMap("hotel", "42");
91
92
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
92
93
* </pre>
95
96
* expanded URI multiple times.
96
97
*
97
98
* <p>Furthermore, the {@code String}-argument methods assume that the URL String is unencoded. This means that
98
- * <pre>
99
+ * <pre class="code" >
99
100
* restTemplate.getForObject("http://example.com/hotel list");
100
101
* </pre>
101
102
* will perform a GET on {@code http://example.com/hotel%20list}. As a result, any URL passed that is already encoded
114
115
* requestFactory} and {@link #setErrorHandler(ResponseErrorHandler) errorHandler} bean properties.
115
116
*
116
117
* @author Arjen Poutsma
118
+ * @author Brian Clozel
117
119
* @since 3.0
118
120
* @see HttpMessageConverter
119
121
* @see RequestCallback
@@ -137,21 +139,22 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
137
139
ClassUtils .isPresent ("org.codehaus.jackson.JsonGenerator" , RestTemplate .class .getClassLoader ());
138
140
139
141
140
- private final ResponseExtractor <HttpHeaders > headersExtractor = new HeadersExtractor ();
141
-
142
- private List <HttpMessageConverter <?>> messageConverters = new ArrayList <HttpMessageConverter <?>>();
142
+ private final List <HttpMessageConverter <?>> messageConverters = new ArrayList <HttpMessageConverter <?>>();
143
143
144
144
private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler ();
145
145
146
+ private final ResponseExtractor <HttpHeaders > headersExtractor = new HeadersExtractor ();
147
+
146
148
147
149
/**
148
150
* Create a new instance of the {@link RestTemplate} using default settings.
151
+ * Default {@link HttpMessageConverter}s are initialized.
149
152
*/
150
153
public RestTemplate () {
151
154
this .messageConverters .add (new ByteArrayHttpMessageConverter ());
152
155
this .messageConverters .add (new StringHttpMessageConverter ());
153
156
this .messageConverters .add (new ResourceHttpMessageConverter ());
154
- this .messageConverters .add (new SourceHttpMessageConverter ());
157
+ this .messageConverters .add (new SourceHttpMessageConverter < Source > ());
155
158
this .messageConverters .add (new AllEncompassingFormHttpMessageConverter ());
156
159
if (romePresent ) {
157
160
this .messageConverters .add (new AtomFeedHttpMessageConverter ());
@@ -179,14 +182,26 @@ public RestTemplate(ClientHttpRequestFactory requestFactory) {
179
182
setRequestFactory (requestFactory );
180
183
}
181
184
185
+ /**
186
+ * Create a new instance of the {@link RestTemplate} using the given list of
187
+ * {@link HttpMessageConverter} to use
188
+ * @param messageConverters the list of {@link HttpMessageConverter} to use
189
+ * @since 3.2.7
190
+ */
191
+ public RestTemplate (List <HttpMessageConverter <?>> messageConverters ) {
192
+ Assert .notEmpty (messageConverters , "'messageConverters' must not be empty" );
193
+ this .messageConverters .addAll (messageConverters );
194
+ }
195
+
182
196
183
197
/**
184
198
* Set the message body converters to use.
185
199
* <p>These converters are used to convert from and to HTTP requests and responses.
186
200
*/
187
201
public void setMessageConverters (List <HttpMessageConverter <?>> messageConverters ) {
188
202
Assert .notEmpty (messageConverters , "'messageConverters' must not be empty" );
189
- this .messageConverters = messageConverters ;
203
+ this .messageConverters .clear ();
204
+ this .messageConverters .addAll (messageConverters );
190
205
}
191
206
192
207
/**
@@ -238,6 +253,7 @@ public <T> T getForObject(URI url, Class<T> responseType) throws RestClientExcep
238
253
239
254
public <T > ResponseEntity <T > getForEntity (String url , Class <T > responseType , Object ... urlVariables )
240
255
throws RestClientException {
256
+
241
257
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback (responseType );
242
258
ResponseEntityResponseExtractor <T > responseExtractor =
243
259
new ResponseEntityResponseExtractor <T >(responseType );
@@ -246,6 +262,7 @@ public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Obj
246
262
247
263
public <T > ResponseEntity <T > getForEntity (String url , Class <T > responseType , Map <String , ?> urlVariables )
248
264
throws RestClientException {
265
+
249
266
AcceptHeaderRequestCallback requestCallback = new AcceptHeaderRequestCallback (responseType );
250
267
ResponseEntityResponseExtractor <T > responseExtractor =
251
268
new ResponseEntityResponseExtractor <T >(responseType );
@@ -283,6 +300,7 @@ public URI postForLocation(String url, Object request, Object... urlVariables) t
283
300
284
301
public URI postForLocation (String url , Object request , Map <String , ?> urlVariables )
285
302
throws RestClientException {
303
+
286
304
HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback (request );
287
305
HttpHeaders headers = execute (url , HttpMethod .POST , requestCallback , this .headersExtractor , urlVariables );
288
306
return headers .getLocation ();
@@ -296,6 +314,7 @@ public URI postForLocation(URI url, Object request) throws RestClientException {
296
314
297
315
public <T > T postForObject (String url , Object request , Class <T > responseType , Object ... uriVariables )
298
316
throws RestClientException {
317
+
299
318
HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback (request , responseType );
300
319
HttpMessageConverterExtractor <T > responseExtractor =
301
320
new HttpMessageConverterExtractor <T >(responseType , getMessageConverters (), logger );
@@ -304,6 +323,7 @@ public <T> T postForObject(String url, Object request, Class<T> responseType, Ob
304
323
305
324
public <T > T postForObject (String url , Object request , Class <T > responseType , Map <String , ?> uriVariables )
306
325
throws RestClientException {
326
+
307
327
HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback (request , responseType );
308
328
HttpMessageConverterExtractor <T > responseExtractor =
309
329
new HttpMessageConverterExtractor <T >(responseType , getMessageConverters (), logger );
@@ -466,8 +486,9 @@ public <T> T execute(URI url, HttpMethod method, RequestCallback requestCallback
466
486
}
467
487
468
488
/**
469
- * Execute the given method on the provided URI. The {@link ClientHttpRequest} is processed using the {@link
470
- * RequestCallback}; the response with the {@link ResponseExtractor}.
489
+ * Execute the given method on the provided URI.
490
+ * <p>The {@link ClientHttpRequest} is processed using the {@link RequestCallback};
491
+ * the response with the {@link ResponseExtractor}.
471
492
* @param url the fully-expanded URL to connect to
472
493
* @param method the HTTP method to execute (GET, POST, etc.)
473
494
* @param requestCallback object that prepares the request (can be {@code null})
@@ -501,7 +522,7 @@ protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCal
501
522
}
502
523
catch (IOException ex ) {
503
524
throw new ResourceAccessException ("I/O error on " + method .name () +
504
- " request for \" " + url + "\" :" + ex .getMessage (), ex );
525
+ " request for \" " + url + "\" : " + ex .getMessage (), ex );
505
526
}
506
527
finally {
507
528
if (response != null ) {
@@ -513,9 +534,8 @@ protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCal
513
534
private void logResponseStatus (HttpMethod method , URI url , ClientHttpResponse response ) {
514
535
if (logger .isDebugEnabled ()) {
515
536
try {
516
- logger .debug (
517
- method .name () + " request for \" " + url + "\" resulted in " + response .getStatusCode () + " (" +
518
- response .getStatusText () + ")" );
537
+ logger .debug (method .name () + " request for \" " + url + "\" resulted in " +
538
+ response .getStatusCode () + " (" + response .getStatusText () + ")" );
519
539
}
520
540
catch (IOException e ) {
521
541
// ignore
@@ -526,9 +546,8 @@ private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse re
526
546
private void handleResponseError (HttpMethod method , URI url , ClientHttpResponse response ) throws IOException {
527
547
if (logger .isWarnEnabled ()) {
528
548
try {
529
- logger .warn (
530
- method .name () + " request for \" " + url + "\" resulted in " + response .getStatusCode () + " (" +
531
- response .getStatusText () + "); invoking error handler" );
549
+ logger .warn (method .name () + " request for \" " + url + "\" resulted in " +
550
+ response .getStatusCode () + " (" + response .getStatusText () + "); invoking error handler" );
532
551
}
533
552
catch (IOException e ) {
534
553
// ignore
@@ -554,7 +573,7 @@ public void doWithRequest(ClientHttpRequest request) throws IOException {
554
573
if (responseType != null ) {
555
574
Class <?> responseClass = null ;
556
575
if (responseType instanceof Class ) {
557
- responseClass = (Class ) responseType ;
576
+ responseClass = (Class <?> ) responseType ;
558
577
}
559
578
560
579
List <MediaType > allSupportedMediaTypes = new ArrayList <MediaType >();
@@ -566,7 +585,7 @@ public void doWithRequest(ClientHttpRequest request) throws IOException {
566
585
}
567
586
else if (converter instanceof GenericHttpMessageConverter ) {
568
587
569
- GenericHttpMessageConverter genericConverter = (GenericHttpMessageConverter ) converter ;
588
+ GenericHttpMessageConverter <?> genericConverter = (GenericHttpMessageConverter <?> ) converter ;
570
589
if (genericConverter .canRead (responseType , null , null )) {
571
590
allSupportedMediaTypes .addAll (getSupportedMediaTypes (converter ));
572
591
}
@@ -604,7 +623,7 @@ private List<MediaType> getSupportedMediaTypes(HttpMessageConverter<?> messageCo
604
623
*/
605
624
private class HttpEntityRequestCallback extends AcceptHeaderRequestCallback {
606
625
607
- private final HttpEntity requestEntity ;
626
+ private final HttpEntity <?> requestEntity ;
608
627
609
628
private HttpEntityRequestCallback (Object requestBody ) {
610
629
this (requestBody , null );
@@ -614,10 +633,10 @@ private HttpEntityRequestCallback(Object requestBody) {
614
633
private HttpEntityRequestCallback (Object requestBody , Type responseType ) {
615
634
super (responseType );
616
635
if (requestBody instanceof HttpEntity ) {
617
- this .requestEntity = (HttpEntity ) requestBody ;
636
+ this .requestEntity = (HttpEntity <?> ) requestBody ;
618
637
}
619
638
else if (requestBody != null ) {
620
- this .requestEntity = new HttpEntity (requestBody );
639
+ this .requestEntity = new HttpEntity < Object > (requestBody );
621
640
}
622
641
else {
623
642
this .requestEntity = HttpEntity .EMPTY ;
@@ -643,7 +662,7 @@ public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
643
662
Class <?> requestType = requestBody .getClass ();
644
663
HttpHeaders requestHeaders = requestEntity .getHeaders ();
645
664
MediaType requestContentType = requestHeaders .getContentType ();
646
- for (HttpMessageConverter messageConverter : getMessageConverters ()) {
665
+ for (HttpMessageConverter <?> messageConverter : getMessageConverters ()) {
647
666
if (messageConverter .canWrite (requestType , requestContentType )) {
648
667
if (!requestHeaders .isEmpty ()) {
649
668
httpRequest .getHeaders ().putAll (requestHeaders );
@@ -658,7 +677,8 @@ public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
658
677
}
659
678
660
679
}
661
- messageConverter .write (requestBody , requestContentType , httpRequest );
680
+ ((HttpMessageConverter <Object >) messageConverter ).write (
681
+ requestBody , requestContentType , httpRequest );
662
682
return ;
663
683
}
664
684
}
@@ -683,7 +703,8 @@ private class ResponseEntityResponseExtractor<T> implements ResponseExtractor<Re
683
703
public ResponseEntityResponseExtractor (Type responseType ) {
684
704
if (responseType != null && !Void .class .equals (responseType )) {
685
705
this .delegate = new HttpMessageConverterExtractor <T >(responseType , getMessageConverters (), logger );
686
- } else {
706
+ }
707
+ else {
687
708
this .delegate = null ;
688
709
}
689
710
}
0 commit comments