Enhance the http client configuration to make it customizable
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1392033 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
29c8382537
commit
c526245f6d
6 changed files with 157 additions and 54 deletions
|
|
@ -122,52 +122,55 @@ public class JsonRpcInvoker implements Invoker, DataExchangeSemantics {
|
|||
|
||||
response = httpClient.execute(post);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||
//success
|
||||
try {
|
||||
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
||||
//success
|
||||
|
||||
entity = response.getEntity();
|
||||
String entityResponse = EntityUtils.toString(entity);
|
||||
entity.consumeContent();
|
||||
if (!db.equals(JSONDataBinding.NAME)) {
|
||||
ObjectNode jsonResponse = (ObjectNode)JacksonHelper.MAPPER.readTree(entityResponse);
|
||||
entity = response.getEntity();
|
||||
String entityResponse = EntityUtils.toString(entity);
|
||||
// entity.consumeContent();
|
||||
if (!db.equals(JSONDataBinding.NAME)) {
|
||||
ObjectNode jsonResponse = (ObjectNode)JacksonHelper.MAPPER.readTree(entityResponse);
|
||||
|
||||
if (jsonResponse.has("error") && jsonResponse.get("error") != NullNode.instance) {
|
||||
processException(jsonResponse);
|
||||
}
|
||||
DataType<List<DataType>> outputType = operation.getOutputType();
|
||||
DataType returnType =
|
||||
(outputType != null && !outputType.getLogical().isEmpty()) ? outputType.getLogical().get(0)
|
||||
: null;
|
||||
if (jsonResponse.has("error") && jsonResponse.get("error") != NullNode.instance) {
|
||||
processException(jsonResponse);
|
||||
}
|
||||
DataType<List<DataType>> outputType = operation.getOutputType();
|
||||
DataType returnType =
|
||||
(outputType != null && !outputType.getLogical().isEmpty()) ? outputType.getLogical().get(0)
|
||||
: null;
|
||||
|
||||
if (returnType == null) {
|
||||
msg.setBody(null);
|
||||
return msg;
|
||||
if (returnType == null) {
|
||||
msg.setBody(null);
|
||||
return msg;
|
||||
}
|
||||
|
||||
//check requestId
|
||||
if (!requestId.equalsIgnoreCase(jsonResponse.get("id").getTextValue())) {
|
||||
throw new ServiceRuntimeException("Invalid response id:" + requestId);
|
||||
}
|
||||
|
||||
JsonNode rawResult = jsonResponse.get("result");
|
||||
|
||||
Class<?> returnClass = returnType.getPhysical();
|
||||
Type genericReturnType = returnType.getGenericType();
|
||||
|
||||
ObjectMapper mapper = createObjectMapper(returnClass);
|
||||
String json = mapper.writeValueAsString(rawResult);
|
||||
|
||||
Object body = mapper.readValue(json, TypeFactory.type(genericReturnType));
|
||||
|
||||
msg.setBody(body);
|
||||
} else {
|
||||
msg.setBody(entityResponse);
|
||||
}
|
||||
|
||||
//check requestId
|
||||
if (!requestId.equalsIgnoreCase(jsonResponse.get("id").getTextValue())) {
|
||||
throw new ServiceRuntimeException("Invalid response id:" + requestId);
|
||||
}
|
||||
|
||||
JsonNode rawResult = jsonResponse.get("result");
|
||||
|
||||
Class<?> returnClass = returnType.getPhysical();
|
||||
Type genericReturnType = returnType.getGenericType();
|
||||
|
||||
ObjectMapper mapper = createObjectMapper(returnClass);
|
||||
String json = mapper.writeValueAsString(rawResult);
|
||||
|
||||
Object body = mapper.readValue(json, TypeFactory.type(genericReturnType));
|
||||
|
||||
msg.setBody(body);
|
||||
} else {
|
||||
msg.setBody(entityResponse);
|
||||
throw new ServiceRuntimeException("Abnormal HTTP response: " + response.getStatusLine().toString());
|
||||
}
|
||||
|
||||
} else {
|
||||
} finally {
|
||||
// Consume the content so the connection can be released
|
||||
response.getEntity().consumeContent();
|
||||
throw new ServiceRuntimeException("Abnormal HTTP response: " + response.getStatusLine().toString());
|
||||
EntityUtils.consumeQuietly(response.getEntity());
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.apache.tuscany.sca.binding.rest.provider;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
|
@ -38,7 +39,6 @@ import javax.ws.rs.DELETE;
|
|||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HEAD;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.MatrixParam;
|
||||
import javax.ws.rs.OPTIONS;
|
||||
|
|
@ -55,6 +55,7 @@ import javax.ws.rs.core.MediaType;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.tuscany.sca.assembly.EndpointReference;
|
||||
import org.apache.tuscany.sca.assembly.WireFormat;
|
||||
import org.apache.tuscany.sca.binding.rest.RESTBinding;
|
||||
|
|
@ -71,6 +72,8 @@ import org.apache.wink.client.ApacheHttpClientConfig;
|
|||
import org.apache.wink.client.ClientConfig;
|
||||
import org.apache.wink.client.Resource;
|
||||
import org.apache.wink.client.RestClient;
|
||||
import org.apache.wink.client.ClientWebException;
|
||||
import org.apache.wink.client.ClientResponse;
|
||||
import org.apache.wink.client.handlers.BasicAuthSecurityHandler;
|
||||
|
||||
/**
|
||||
|
|
@ -85,7 +88,11 @@ public class RESTBindingInvoker implements Invoker {
|
|||
private String httpMethod;
|
||||
private Class<?> responseType;
|
||||
|
||||
public RESTBindingInvoker(ExtensionPointRegistry registry, EndpointReference endpointReference, RESTBinding binding, Operation operation, HttpClient httpClient) {
|
||||
public RESTBindingInvoker(ExtensionPointRegistry registry,
|
||||
EndpointReference endpointReference,
|
||||
RESTBinding binding,
|
||||
Operation operation,
|
||||
HttpClient httpClient) {
|
||||
super();
|
||||
this.registry = registry;
|
||||
this.endpointReference = endpointReference;
|
||||
|
|
@ -134,10 +141,10 @@ public class RESTBindingInvoker implements Invoker {
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
config.readTimeout(binding.getReadTimeout());
|
||||
RestClient client = new RestClient(config);
|
||||
|
||||
|
||||
// Default to GET for RPC
|
||||
httpMethod = HttpMethod.GET;
|
||||
|
||||
|
|
@ -224,10 +231,10 @@ public class RESTBindingInvoker implements Invoker {
|
|||
cookieParams.put(cookieParam.value(), args[i]);
|
||||
}
|
||||
|
||||
if(getAnnotation(annotations, Context.class) != null) {
|
||||
if (getAnnotation(annotations, Context.class) != null) {
|
||||
isEntity = false;
|
||||
}
|
||||
|
||||
|
||||
if (isEntity) {
|
||||
entity = args[i];
|
||||
}
|
||||
|
|
@ -271,8 +278,22 @@ public class RESTBindingInvoker implements Invoker {
|
|||
}
|
||||
}
|
||||
|
||||
Object result = resource.invoke(httpMethod, responseType, entity);
|
||||
msg.setBody(result);
|
||||
try {
|
||||
Object result = resource.invoke(httpMethod, responseType, entity);
|
||||
msg.setBody(result);
|
||||
} catch (ClientWebException e) {
|
||||
ClientResponse clientResponse = e.getResponse();
|
||||
// Consume the entity
|
||||
String error = clientResponse.getEntity(String.class);
|
||||
StringEntity stringEntity;
|
||||
try {
|
||||
stringEntity = error == null ? null : new StringEntity(error);
|
||||
clientResponse.setEntity(stringEntity);
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
// Ignore
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
org.apache.tuscany.sca.host.http.client.HttpClientFactory;soTimeout = 30000,connectionTimeout = 60000,staleCheckingEnabled = false,timeToLive = 30,maxPerRoute = 16,maxTotal = 256,sslHostVerificationEnabled = false
|
||||
|
|
@ -46,7 +46,8 @@ Import-Package: org.apache.tuscany.sca.assembly;version="2.0.0",
|
|||
org.apache.tuscany.sca.provider;version="2.0.0",
|
||||
org.apache.tuscany.sca.runtime;version="2.0.0",
|
||||
org.apache.tuscany.sca.work;version="2.0.0",
|
||||
org.oasisopen.sca;version="2.0.0"
|
||||
org.oasisopen.sca;version="2.0.0",
|
||||
org.oasisopen.sca.annotation;version="2.0.0"
|
||||
Bundle-SymbolicName: org.apache.tuscany.sca.core.spi
|
||||
Bundle-DocURL: http://www.apache.org/
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ Import-Package: javax.servlet,
|
|||
org.apache.http.conn.params;resolution:=optional,
|
||||
org.apache.http.conn.scheme;resolution:=optional,
|
||||
org.apache.http.conn.ssl;resolution:=optional,
|
||||
org.apache.http.impl;resolution:=optional,
|
||||
org.apache.http.impl.client;resolution:=optional,
|
||||
org.apache.http.impl.conn;resolution:=optional,
|
||||
org.apache.http.impl.conn.tsccm;resolution:=optional,
|
||||
|
|
|
|||
|
|
@ -19,10 +19,17 @@
|
|||
|
||||
package org.apache.tuscany.sca.host.http.client;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.http.ConnectionReuseStrategy;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ConnectionKeepAliveStrategy;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLInitializationException;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.impl.NoConnectionReuseStrategy;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.conn.PoolingClientConnectionManager;
|
||||
import org.apache.http.impl.conn.SchemeRegistryFactory;
|
||||
|
|
@ -30,6 +37,7 @@ import org.apache.http.params.BasicHttpParams;
|
|||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.params.HttpProtocolParams;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
|
||||
import org.apache.tuscany.sca.core.LifeCycleListener;
|
||||
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
|
||||
|
|
@ -38,6 +46,13 @@ import org.apache.tuscany.sca.core.UtilityExtensionPoint;
|
|||
* @version $Rev$ $Date$
|
||||
*/
|
||||
public class HttpClientFactory implements LifeCycleListener {
|
||||
private int soTimeout = 30000;
|
||||
private int connectionTimeout = 60000;
|
||||
private boolean staleCheckingEnabled = false;
|
||||
private long timeToLive = 60; // seconds
|
||||
private int maxPerRoute = 256;
|
||||
private int maxTotal = 1024;
|
||||
private boolean sslHostVerificationEnabled = false;
|
||||
|
||||
private HttpClient httpClient;
|
||||
|
||||
|
|
@ -46,12 +61,50 @@ public class HttpClientFactory implements LifeCycleListener {
|
|||
return utilities.getUtility(HttpClientFactory.class);
|
||||
}
|
||||
|
||||
public HttpClientFactory() {
|
||||
|
||||
}
|
||||
|
||||
public HttpClientFactory(ExtensionPointRegistry registry, Map<String, String> attributes) {
|
||||
if (attributes != null) {
|
||||
String val = attributes.get("soTimeout");
|
||||
if (val != null) {
|
||||
this.soTimeout = Integer.parseInt(val);
|
||||
}
|
||||
val = attributes.get("connectionTimeout");
|
||||
if (val != null) {
|
||||
this.connectionTimeout = Integer.parseInt(val);
|
||||
}
|
||||
val = attributes.get("staleCheckingEnabled");
|
||||
if (val != null) {
|
||||
this.staleCheckingEnabled = Boolean.parseBoolean(val);
|
||||
}
|
||||
val = attributes.get("timeToLive");
|
||||
if (val != null) {
|
||||
this.timeToLive = Long.parseLong(val);
|
||||
}
|
||||
val = attributes.get("sslHostVerificationEnabled");
|
||||
if (val != null) {
|
||||
this.sslHostVerificationEnabled = Boolean.parseBoolean(val);
|
||||
}
|
||||
val = attributes.get("maxTotal");
|
||||
if (val != null) {
|
||||
this.maxTotal = Integer.parseInt(val);
|
||||
}
|
||||
val = attributes.get("maxPerRoute");
|
||||
if (val != null) {
|
||||
this.maxPerRoute = Integer.parseInt(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HttpClient createHttpClient() {
|
||||
HttpParams defaultParameters = new BasicHttpParams();
|
||||
|
||||
HttpProtocolParams.setContentCharset(defaultParameters, "UTF-8");
|
||||
HttpConnectionParams.setConnectionTimeout(defaultParameters, 60000);
|
||||
HttpConnectionParams.setSoTimeout(defaultParameters, 60000);
|
||||
HttpConnectionParams.setConnectionTimeout(defaultParameters, connectionTimeout);
|
||||
HttpConnectionParams.setSoTimeout(defaultParameters, soTimeout);
|
||||
HttpConnectionParams.setStaleCheckingEnabled(defaultParameters, staleCheckingEnabled);
|
||||
|
||||
// See https://issues.apache.org/jira/browse/HTTPCLIENT-1138
|
||||
SchemeRegistry supportedSchemes = null;
|
||||
|
|
@ -62,17 +115,24 @@ public class HttpClientFactory implements LifeCycleListener {
|
|||
supportedSchemes = SchemeRegistryFactory.createDefault();
|
||||
}
|
||||
|
||||
// FIXME: By pass host name verification
|
||||
SSLSocketFactory socketFactory = (SSLSocketFactory)supportedSchemes.getScheme("https").getSchemeSocketFactory();
|
||||
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
if (!sslHostVerificationEnabled) {
|
||||
// FIXME: By pass host name verification
|
||||
SSLSocketFactory socketFactory =
|
||||
(SSLSocketFactory)supportedSchemes.getScheme("https").getSchemeSocketFactory();
|
||||
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
}
|
||||
|
||||
PoolingClientConnectionManager connectionManager =
|
||||
new PoolingClientConnectionManager(supportedSchemes);
|
||||
new PoolingClientConnectionManager(supportedSchemes, timeToLive, TimeUnit.SECONDS);
|
||||
|
||||
connectionManager.setDefaultMaxPerRoute(256);
|
||||
connectionManager.setMaxTotal(1024);
|
||||
|
||||
return new DefaultHttpClient(connectionManager, defaultParameters);
|
||||
connectionManager.setDefaultMaxPerRoute(maxPerRoute);
|
||||
connectionManager.setMaxTotal(maxTotal);
|
||||
|
||||
DefaultHttpClient client = new DefaultHttpClient(connectionManager, defaultParameters);
|
||||
if (timeToLive <= 0) {
|
||||
client.setReuseStrategy(new NoConnectionReuseStrategy());
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue