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.
27
27
import org .apache .http .NoHttpResponseException ;
28
28
import org .apache .http .StatusLine ;
29
29
import org .apache .http .client .HttpClient ;
30
+ import org .apache .http .client .config .RequestConfig ;
30
31
import org .apache .http .client .methods .HttpPost ;
32
+ import org .apache .http .config .Registry ;
33
+ import org .apache .http .config .RegistryBuilder ;
34
+ import org .apache .http .conn .socket .ConnectionSocketFactory ;
35
+ import org .apache .http .conn .socket .PlainConnectionSocketFactory ;
36
+ import org .apache .http .conn .ssl .SSLConnectionSocketFactory ;
31
37
import org .apache .http .entity .ByteArrayEntity ;
38
+ import org .apache .http .impl .client .HttpClientBuilder ;
39
+ import org .apache .http .impl .conn .PoolingHttpClientConnectionManager ;
32
40
33
41
import org .springframework .context .i18n .LocaleContext ;
34
42
import org .springframework .context .i18n .LocaleContextHolder ;
45
53
* instance, potentially with authentication, HTTP connection pooling, etc.
46
54
* Also designed for easy subclassing, providing specific template methods.
47
55
*
48
- * <p>As of Spring 3.2 , this request executor requires Apache HttpComponents 4.2 or higher.
56
+ * <p>As of Spring 4.1 , this request executor requires Apache HttpComponents 4.3 or higher.
49
57
*
50
58
* @author Juergen Hoeller
51
59
* @since 3.1
52
60
* @see org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor
53
61
*/
54
- @ SuppressWarnings ("deprecation" )
55
62
public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor {
56
63
57
64
private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100 ;
@@ -61,24 +68,26 @@ public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvoke
61
68
private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000 );
62
69
63
70
private HttpClient httpClient ;
71
+ private int connectionTimeout = 0 ;
72
+ private int readTimeout = DEFAULT_READ_TIMEOUT_MILLISECONDS ;
64
73
65
74
66
75
/**
67
76
* Create a new instance of the HttpComponentsHttpInvokerRequestExecutor with a default
68
77
* {@link HttpClient} that uses a default {@code org.apache.http.impl.conn.PoolingClientConnectionManager}.
69
78
*/
70
79
public HttpComponentsHttpInvokerRequestExecutor () {
71
- org .apache .http .conn .scheme .SchemeRegistry schemeRegistry = new org .apache .http .conn .scheme .SchemeRegistry ();
72
- schemeRegistry .register (new org .apache .http .conn .scheme .Scheme ("http" , 80 , org .apache .http .conn .scheme .PlainSocketFactory .getSocketFactory ()));
73
- schemeRegistry .register (new org .apache .http .conn .scheme .Scheme ("https" , 443 , org .apache .http .conn .ssl .SSLSocketFactory .getSocketFactory ()));
80
+ Registry <ConnectionSocketFactory > schemeRegistry = RegistryBuilder .<ConnectionSocketFactory >create ()
81
+ .register ("http" , PlainConnectionSocketFactory .getSocketFactory ())
82
+ .register ("https" , SSLConnectionSocketFactory .getSocketFactory ())
83
+ .build ();
74
84
75
- org . apache . http . impl . conn . PoolingClientConnectionManager connectionManager =
76
- new org . apache . http . impl . conn . PoolingClientConnectionManager (schemeRegistry );
85
+ PoolingHttpClientConnectionManager connectionManager
86
+ = new PoolingHttpClientConnectionManager (schemeRegistry );
77
87
connectionManager .setMaxTotal (DEFAULT_MAX_TOTAL_CONNECTIONS );
78
88
connectionManager .setDefaultMaxPerRoute (DEFAULT_MAX_CONNECTIONS_PER_ROUTE );
79
89
80
- this .httpClient = new org .apache .http .impl .client .DefaultHttpClient (connectionManager );
81
- setReadTimeout (DEFAULT_READ_TIMEOUT_MILLISECONDS );
90
+ this .httpClient = HttpClientBuilder .create ().setConnectionManager (connectionManager ).build ();
82
91
}
83
92
84
93
/**
@@ -112,7 +121,30 @@ public HttpClient getHttpClient() {
112
121
*/
113
122
public void setConnectTimeout (int timeout ) {
114
123
Assert .isTrue (timeout >= 0 , "Timeout must be a non-negative value" );
115
- getHttpClient ().getParams ().setIntParameter (org .apache .http .params .CoreConnectionPNames .CONNECTION_TIMEOUT , timeout );
124
+ this .connectionTimeout = timeout ;
125
+ setLegacyConnectionTimeout (getHttpClient (), timeout );
126
+ }
127
+
128
+ /**
129
+ * Apply the specified connection timeout to deprecated {@link HttpClient}
130
+ * implementations.
131
+ * <p>As of HttpClient 4.3, default parameters have to be exposed through a
132
+ * {@link RequestConfig} instance instead of setting the parameters on the
133
+ * client. Unfortunately, this behavior is not backward-compatible and older
134
+ * {@link HttpClient} implementations will ignore the {@link RequestConfig}
135
+ * object set in the context.
136
+ * <p>If the specified client is an older implementation, we set the custom
137
+ * connection timeout through the deprecated API. Otherwise, we just return
138
+ * as it is set through {@link RequestConfig} with newer clients.
139
+ * @param client the client to configure
140
+ * @param timeout the custom connection timeout
141
+ */
142
+ @ SuppressWarnings ("deprecation" )
143
+ private void setLegacyConnectionTimeout (HttpClient client , int timeout ) {
144
+ if (org .apache .http .impl .client .AbstractHttpClient .class .isInstance (client )) {
145
+ client .getParams ().setIntParameter (
146
+ org .apache .http .params .CoreConnectionPNames .CONNECTION_TIMEOUT , timeout );
147
+ }
116
148
}
117
149
118
150
/**
@@ -123,9 +155,24 @@ public void setConnectTimeout(int timeout) {
123
155
*/
124
156
public void setReadTimeout (int timeout ) {
125
157
Assert .isTrue (timeout >= 0 , "Timeout must be a non-negative value" );
126
- getHttpClient ().getParams ().setIntParameter (org .apache .http .params .CoreConnectionPNames .SO_TIMEOUT , timeout );
158
+ this .readTimeout = timeout ;
159
+ setLegacySocketTimeout (getHttpClient (), timeout );
127
160
}
128
161
162
+ /**
163
+ * Apply the specified socket timeout to deprecated {@link HttpClient}
164
+ * implementations. See {@link #setLegacyConnectionTimeout}.
165
+ * @param client the client to configure
166
+ * @param timeout the custom socket timeout
167
+ * @see #setLegacyConnectionTimeout
168
+ */
169
+ @ SuppressWarnings ("deprecation" )
170
+ private void setLegacySocketTimeout (HttpClient client , int timeout ) {
171
+ if (org .apache .http .impl .client .AbstractHttpClient .class .isInstance (client )) {
172
+ client .getParams ().setIntParameter (
173
+ org .apache .http .params .CoreConnectionPNames .SO_TIMEOUT , timeout );
174
+ }
175
+ }
129
176
130
177
/**
131
178
* Execute the given request through the HttpClient.
@@ -166,6 +213,7 @@ protected RemoteInvocationResult doExecuteRequest(
166
213
*/
167
214
protected HttpPost createHttpPost (HttpInvokerClientConfiguration config ) throws IOException {
168
215
HttpPost httpPost = new HttpPost (config .getServiceUrl ());
216
+ httpPost .setConfig (createRequestConfig (config , httpPost ));
169
217
LocaleContext localeContext = LocaleContextHolder .getLocaleContext ();
170
218
if (localeContext != null ) {
171
219
Locale locale = localeContext .getLocale ();
@@ -179,6 +227,25 @@ protected HttpPost createHttpPost(HttpInvokerClientConfiguration config) throws
179
227
return httpPost ;
180
228
}
181
229
230
+ /**
231
+ * Create a {@link RequestConfig} for the given configuration and {@link HttpPost}.
232
+ * @param config the HTTP invoker configuration that specifies the
233
+ * target service
234
+ * @param httpPost the HttpPost instance
235
+ * @return the RequestConfig to use for that HttpPost
236
+ */
237
+ protected RequestConfig createRequestConfig (HttpInvokerClientConfiguration config , HttpPost httpPost ) {
238
+ if (this .connectionTimeout > 0 || this .readTimeout > 0 ) {
239
+ return RequestConfig .custom ()
240
+ .setConnectTimeout (this .connectionTimeout )
241
+ .setSocketTimeout (this .readTimeout )
242
+ .build ();
243
+ }
244
+ else {
245
+ return RequestConfig .DEFAULT ;
246
+ }
247
+ }
248
+
182
249
/**
183
250
* Set the given serialized remote invocation as request body.
184
251
* <p>The default implementation simply sets the serialized invocation as the
0 commit comments