You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Dinesh Babu <di...@pb.com> on 2015/01/22 17:43:36 UTC
AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available"
connections
Hi,
I am a newbie to this group
We are using Spring ReST Template to make web service calls which in turn uses Apache Http Client family of classes . We are seeing time out error from AbstractConnPool when we make calls . Details below
1) We make our first call http://abc:8080/def. For this call to complete we need to make another call which is below
2) http://abc:8080/efg . For this call to complete we need to make another call which is below
3) http://abc:8080/hij
In AbstractConnPool the available connection is not more than 2 at any given point of time which is taken by my calls in (1) and (2) . When call (3) is made since there is no available connection, this call time out.
a) Is there a solution for this scenario?
b) Is there a way to increase the number of available connections?
Regards,
Dinesh Babu.
________________________________
RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase
"available" connections
Posted by Dinesh Babu <di...@pb.com>.
We found the fix. Sharing just in case if any one comes across this issue.
The root cause was because Apache Connection pool mechanism does not seem to allow more than 2 connections for a client at any given time and we needed 3 connections. So what we did was to use a new client for each call. So the code was changed from
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
if (requestFactory == null) {
HttpClient client = buildClient();
requestFactory = new HttpComponentsClientHttpRequestFactory(client);
}
return requestFactory.createRequest(uri, httpMethod);
}
to
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpClient client = buildClient();
requestFactory = new HttpComponentsClientHttpRequestFactory(client);
return requestFactory.createRequest(uri, httpMethod);
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Dinesh Babu [mailto:dinesh.babu@pb.com]
Sent: 22 January 2015 17:14
To: HttpClient User Discussion
Subject: RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Just to pinpoint, the method used is
public <T> T get(String resource, Class<T> responseType) {
URI url = buildUrl(resource);
String fullJson = this.exchange(url, HttpMethod.GET, buildRequest(""), String.class).getBody();
return readDataElement(fullJson, responseType);
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Dinesh Babu [mailto:dinesh.babu@pb.com]
Sent: 22 January 2015 16:58
To: HttpClient User Discussion
Subject: RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Thanks Stéphane,
Below is the code.
package com.pb.viewpoint.rest.client.spring;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import com.pb.viewpoint.rest.client.ClientCustomization;
import com.pb.viewpoint.rest.client.NoClientCustomization;
import com.pb.viewpoint.rest.client.RestClient;
import com.pb.viewpoint.rest.client.RestClientException;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.pb.viewpoint.rest.client.RestClientOptions;
import javax.net.ssl.SSLContext;
public class SpringRestClient extends RestTemplate implements RestClient, ClientHttpRequestFactory {
private final String proxyHost;
private final int proxyPort;
private final ClientCustomization customization;
private final String baseUri;
private final String VIEWPOINT_JSON_DATA_PATH = "data";
private String objectRootPath = VIEWPOINT_JSON_DATA_PATH;
private HttpComponentsClientHttpRequestFactory requestFactory;
private MediaType mediaType;
private int timeout = 120;
private String userAgent = "common-rest-client";
private static final Logger LOGGER = LoggerFactory.getLogger(SpringRestClient.class);
public SpringRestClient(RestClientOptions options) {
this(options, new NoClientCustomization());
}
public SpringRestClient(RestClientOptions options, ClientCustomization customization) {
this.timeout = options.getTimeout();
this.proxyHost = options.getProxyHost();
this.proxyPort = options.getProxyPort();
this.userAgent = options.getUserAgent();
this.setContentType(options.getContentType());
this.customization = customization;
this.baseUri = options.getBaseUri();
this.setRequestFactory(this);
this.setErrorHandler(new CustomResponseErrorHandler());
}
private void setContentType(String contentType) {
String[] splits = contentType.split("/");
if (splits.length != 2) {
throw new RestClientException(String.format("ContentType '%s' is not valid", contentType));
}
this.mediaType = new MediaType(splits[0], splits[1], Charset.forName("utf-8"));
}
public String get(URI url) {
HttpEntity<String> entity = new HttpEntity<String>("parameters", constructHttpHeader());
ResponseEntity<String> responseEntity = this.exchange(url, HttpMethod.GET, entity, String.class);
return responseEntity.getBody();
}
private HttpHeaders constructHttpHeader() {
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json");
headers.setContentType(mediaType);
return headers;
}
public <T> T get(String resource, Class<T> responseType) {
URI url = buildUrl(resource);
String fullJson = this.exchange(url, HttpMethod.GET, buildRequest(""), String.class).getBody();
return readDataElement(fullJson, responseType);
}
public <T> void create(URI url, Object object, Class<T> responseType) {
this.postForObject(url, object, responseType);
}
public <T> void create(String resource, Object object, Class<T> responseType) {
URI url = buildUrl(resource);
create(url, object, responseType);
}
public void update(String resource, Object object, String id) {
URI url = buildUrl(resource + "/" + id);
this.put(url, object);
}
public void delete(String resource, String id) {
HttpEntity<String> entity = new HttpEntity<String>(constructHttpHeader());
URI url = buildUrl(resource + "/" + id);
this.exchange(url, HttpMethod.DELETE, entity, String.class);
}
public void delete(URI url, String body) {
HttpEntity<String> entity = new HttpEntity(body, constructHttpHeader());
this.postForEntity(url, entity, String.class);
}
private <T> HttpEntity<T> buildRequest(T entity) {
HttpHeaders headers = new HttpHeaders();
headers.set(org.apache.http.HttpHeaders.ACCEPT, mediaType.toString());
headers.setContentType(mediaType);
headers.set(org.apache.http.HttpHeaders.USER_AGENT, userAgent);
return new HttpEntity<T>(entity, headers);
}
private URI buildUrl(String resource) {
try {
return new URI(baseUri + "/" + resource);
} catch (URISyntaxException e) {
throw new RestClientException(e.getMessage(), e);
}
}
private <T> T readDataElement(String fullJson, Class<T> responseType) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(fullJson).findPath(objectRootPath);
return mapper.readValue(jsonNode, responseType);
} catch (JsonProcessingException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
} catch (IOException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
}
}
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
if (requestFactory == null) {
HttpClient client = buildClient();
requestFactory = new HttpComponentsClientHttpRequestFactory(client);
}
return requestFactory.createRequest(uri, httpMethod);
}
private HttpClient buildClient() {
HttpClientBuilder builder = HttpClientBuilder.create();
// Fiddler Proxy
if (isNotEmpty(proxyHost) && proxyPort > 0) {
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
builder.setProxy(proxy);
}
builder.setDefaultRequestConfig(buildRequestConfiguration());
customization.customize(builder);
enableSSL(builder);
return builder.build();
}
private void enableSSL(HttpClientBuilder builder) {
try {
SSLContext sslContext = createSSLContext();
builder.setSslcontext(sslContext);
SSLConnectionSocketFactory sslSocketFactory = createSSLSocketFactory(sslContext);
builder.setSSLSocketFactory(sslSocketFactory);
} catch(Exception e) {
LOGGER.error("Error enabling SSL in springRestClient");
}
}
private SSLContext createSSLContext() throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
TrustStrategy allTrust = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};
return SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, allTrust).build();
}
private SSLConnectionSocketFactory createSSLSocketFactory(SSLContext sslContext) {
return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
private RequestConfig buildRequestConfiguration() {
RequestConfig.Builder requestConfig = RequestConfig.custom();
requestConfig = requestConfig.setConnectTimeout(this.timeout * 1000);
requestConfig = requestConfig.setConnectionRequestTimeout(this.timeout * 1000);
requestConfig = requestConfig.setSocketTimeout(this.timeout * 1000);
return requestConfig.build();
}
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Stéphane Nicoll [mailto:snicoll@pivotal.io]
Sent: 22 January 2015 16:47
To: HttpClient User Discussion
Subject: Re: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Hey,
Looks weird. Can you share your code using the RestTemplate?
S.
On Thu, Jan 22, 2015 at 5:43 PM, Dinesh Babu <di...@pb.com> wrote:
> Hi,
>
> I am a newbie to this group
>
> We are using Spring ReST Template to make web service calls which in
> turn uses Apache Http Client family of classes . We are seeing time
> out error from AbstractConnPool when we make calls . Details below
>
> 1) We make our first call http://abc:8080/def. For this call to
> complete we need to make another call which is below
> 2) http://abc:8080/efg . For this call to complete we need to make
> another call which is below
> 3) http://abc:8080/hij
>
> In AbstractConnPool the available connection is not more than 2 at any
> given point of time which is taken by my calls in (1) and (2) . When
> call
> (3) is made since there is no available connection, this call time out.
>
> a) Is there a solution for this scenario?
> b) Is there a way to increase the number of available connections?
>
> Regards,
> Dinesh Babu.
>
> ________________________________
>
>
________________________________
B KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB [ X ܚX KK[XZ[ Y[ ]\ \ ][ X ܚX P˘\X K ܙ B ܈Y][ۘ[ [X[ K[XZ[ Y[ ]\ \ Z[˘\X K ܙ B B
________________________________
B KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB [ X ܚX KK[XZ[
Y[
]\ \ ][ X ܚX P˘\X K ܙ B ܈Y][ۘ[ [X[ K[XZ[
Y[
]\ \ Z[˘\X K ܙ B B
________________________________
RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase
"available" connections
Posted by Dinesh Babu <di...@pb.com>.
Just to pinpoint, the method used is
public <T> T get(String resource, Class<T> responseType) {
URI url = buildUrl(resource);
String fullJson = this.exchange(url, HttpMethod.GET, buildRequest(""), String.class).getBody();
return readDataElement(fullJson, responseType);
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Dinesh Babu [mailto:dinesh.babu@pb.com]
Sent: 22 January 2015 16:58
To: HttpClient User Discussion
Subject: RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Thanks Stéphane,
Below is the code.
package com.pb.viewpoint.rest.client.spring;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import com.pb.viewpoint.rest.client.ClientCustomization;
import com.pb.viewpoint.rest.client.NoClientCustomization;
import com.pb.viewpoint.rest.client.RestClient;
import com.pb.viewpoint.rest.client.RestClientException;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.pb.viewpoint.rest.client.RestClientOptions;
import javax.net.ssl.SSLContext;
public class SpringRestClient extends RestTemplate implements RestClient, ClientHttpRequestFactory {
private final String proxyHost;
private final int proxyPort;
private final ClientCustomization customization;
private final String baseUri;
private final String VIEWPOINT_JSON_DATA_PATH = "data";
private String objectRootPath = VIEWPOINT_JSON_DATA_PATH;
private HttpComponentsClientHttpRequestFactory requestFactory;
private MediaType mediaType;
private int timeout = 120;
private String userAgent = "common-rest-client";
private static final Logger LOGGER = LoggerFactory.getLogger(SpringRestClient.class);
public SpringRestClient(RestClientOptions options) {
this(options, new NoClientCustomization());
}
public SpringRestClient(RestClientOptions options, ClientCustomization customization) {
this.timeout = options.getTimeout();
this.proxyHost = options.getProxyHost();
this.proxyPort = options.getProxyPort();
this.userAgent = options.getUserAgent();
this.setContentType(options.getContentType());
this.customization = customization;
this.baseUri = options.getBaseUri();
this.setRequestFactory(this);
this.setErrorHandler(new CustomResponseErrorHandler());
}
private void setContentType(String contentType) {
String[] splits = contentType.split("/");
if (splits.length != 2) {
throw new RestClientException(String.format("ContentType '%s' is not valid", contentType));
}
this.mediaType = new MediaType(splits[0], splits[1], Charset.forName("utf-8"));
}
public String get(URI url) {
HttpEntity<String> entity = new HttpEntity<String>("parameters", constructHttpHeader());
ResponseEntity<String> responseEntity = this.exchange(url, HttpMethod.GET, entity, String.class);
return responseEntity.getBody();
}
private HttpHeaders constructHttpHeader() {
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json");
headers.setContentType(mediaType);
return headers;
}
public <T> T get(String resource, Class<T> responseType) {
URI url = buildUrl(resource);
String fullJson = this.exchange(url, HttpMethod.GET, buildRequest(""), String.class).getBody();
return readDataElement(fullJson, responseType);
}
public <T> void create(URI url, Object object, Class<T> responseType) {
this.postForObject(url, object, responseType);
}
public <T> void create(String resource, Object object, Class<T> responseType) {
URI url = buildUrl(resource);
create(url, object, responseType);
}
public void update(String resource, Object object, String id) {
URI url = buildUrl(resource + "/" + id);
this.put(url, object);
}
public void delete(String resource, String id) {
HttpEntity<String> entity = new HttpEntity<String>(constructHttpHeader());
URI url = buildUrl(resource + "/" + id);
this.exchange(url, HttpMethod.DELETE, entity, String.class);
}
public void delete(URI url, String body) {
HttpEntity<String> entity = new HttpEntity(body, constructHttpHeader());
this.postForEntity(url, entity, String.class);
}
private <T> HttpEntity<T> buildRequest(T entity) {
HttpHeaders headers = new HttpHeaders();
headers.set(org.apache.http.HttpHeaders.ACCEPT, mediaType.toString());
headers.setContentType(mediaType);
headers.set(org.apache.http.HttpHeaders.USER_AGENT, userAgent);
return new HttpEntity<T>(entity, headers);
}
private URI buildUrl(String resource) {
try {
return new URI(baseUri + "/" + resource);
} catch (URISyntaxException e) {
throw new RestClientException(e.getMessage(), e);
}
}
private <T> T readDataElement(String fullJson, Class<T> responseType) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(fullJson).findPath(objectRootPath);
return mapper.readValue(jsonNode, responseType);
} catch (JsonProcessingException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
} catch (IOException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
}
}
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
if (requestFactory == null) {
HttpClient client = buildClient();
requestFactory = new HttpComponentsClientHttpRequestFactory(client);
}
return requestFactory.createRequest(uri, httpMethod);
}
private HttpClient buildClient() {
HttpClientBuilder builder = HttpClientBuilder.create();
// Fiddler Proxy
if (isNotEmpty(proxyHost) && proxyPort > 0) {
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
builder.setProxy(proxy);
}
builder.setDefaultRequestConfig(buildRequestConfiguration());
customization.customize(builder);
enableSSL(builder);
return builder.build();
}
private void enableSSL(HttpClientBuilder builder) {
try {
SSLContext sslContext = createSSLContext();
builder.setSslcontext(sslContext);
SSLConnectionSocketFactory sslSocketFactory = createSSLSocketFactory(sslContext);
builder.setSSLSocketFactory(sslSocketFactory);
} catch(Exception e) {
LOGGER.error("Error enabling SSL in springRestClient");
}
}
private SSLContext createSSLContext() throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
TrustStrategy allTrust = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};
return SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, allTrust).build();
}
private SSLConnectionSocketFactory createSSLSocketFactory(SSLContext sslContext) {
return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
private RequestConfig buildRequestConfiguration() {
RequestConfig.Builder requestConfig = RequestConfig.custom();
requestConfig = requestConfig.setConnectTimeout(this.timeout * 1000);
requestConfig = requestConfig.setConnectionRequestTimeout(this.timeout * 1000);
requestConfig = requestConfig.setSocketTimeout(this.timeout * 1000);
return requestConfig.build();
}
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Stéphane Nicoll [mailto:snicoll@pivotal.io]
Sent: 22 January 2015 16:47
To: HttpClient User Discussion
Subject: Re: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Hey,
Looks weird. Can you share your code using the RestTemplate?
S.
On Thu, Jan 22, 2015 at 5:43 PM, Dinesh Babu <di...@pb.com> wrote:
> Hi,
>
> I am a newbie to this group
>
> We are using Spring ReST Template to make web service calls which in
> turn uses Apache Http Client family of classes . We are seeing time
> out error from AbstractConnPool when we make calls . Details below
>
> 1) We make our first call http://abc:8080/def. For this call to
> complete we need to make another call which is below
> 2) http://abc:8080/efg . For this call to complete we need to make
> another call which is below
> 3) http://abc:8080/hij
>
> In AbstractConnPool the available connection is not more than 2 at any
> given point of time which is taken by my calls in (1) and (2) . When
> call
> (3) is made since there is no available connection, this call time out.
>
> a) Is there a solution for this scenario?
> b) Is there a way to increase the number of available connections?
>
> Regards,
> Dinesh Babu.
>
> ________________________________
>
>
________________________________
B KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKCB [ X ܚX KK[XZ[
Y[
]\ \ ][ X ܚX P˘\X K ܙ B ܈Y][ۘ[ [X[ K[XZ[
Y[
]\ \ Z[˘\X K ܙ B B
________________________________
RE: AbstractConnPool (httpcore-4.3.2.jar)- how to increase
"available" connections
Posted by Dinesh Babu <di...@pb.com>.
Thanks Stéphane,
Below is the code.
package com.pb.viewpoint.rest.client.spring;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import com.pb.viewpoint.rest.client.ClientCustomization;
import com.pb.viewpoint.rest.client.NoClientCustomization;
import com.pb.viewpoint.rest.client.RestClient;
import com.pb.viewpoint.rest.client.RestClientException;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.pb.viewpoint.rest.client.RestClientOptions;
import javax.net.ssl.SSLContext;
public class SpringRestClient extends RestTemplate implements RestClient, ClientHttpRequestFactory {
private final String proxyHost;
private final int proxyPort;
private final ClientCustomization customization;
private final String baseUri;
private final String VIEWPOINT_JSON_DATA_PATH = "data";
private String objectRootPath = VIEWPOINT_JSON_DATA_PATH;
private HttpComponentsClientHttpRequestFactory requestFactory;
private MediaType mediaType;
private int timeout = 120;
private String userAgent = "common-rest-client";
private static final Logger LOGGER = LoggerFactory.getLogger(SpringRestClient.class);
public SpringRestClient(RestClientOptions options) {
this(options, new NoClientCustomization());
}
public SpringRestClient(RestClientOptions options, ClientCustomization customization) {
this.timeout = options.getTimeout();
this.proxyHost = options.getProxyHost();
this.proxyPort = options.getProxyPort();
this.userAgent = options.getUserAgent();
this.setContentType(options.getContentType());
this.customization = customization;
this.baseUri = options.getBaseUri();
this.setRequestFactory(this);
this.setErrorHandler(new CustomResponseErrorHandler());
}
private void setContentType(String contentType) {
String[] splits = contentType.split("/");
if (splits.length != 2) {
throw new RestClientException(String.format("ContentType '%s' is not valid", contentType));
}
this.mediaType = new MediaType(splits[0], splits[1], Charset.forName("utf-8"));
}
public String get(URI url) {
HttpEntity<String> entity = new HttpEntity<String>("parameters", constructHttpHeader());
ResponseEntity<String> responseEntity = this.exchange(url, HttpMethod.GET, entity, String.class);
return responseEntity.getBody();
}
private HttpHeaders constructHttpHeader() {
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json");
headers.setContentType(mediaType);
return headers;
}
public <T> T get(String resource, Class<T> responseType) {
URI url = buildUrl(resource);
String fullJson = this.exchange(url, HttpMethod.GET, buildRequest(""), String.class).getBody();
return readDataElement(fullJson, responseType);
}
public <T> void create(URI url, Object object, Class<T> responseType) {
this.postForObject(url, object, responseType);
}
public <T> void create(String resource, Object object, Class<T> responseType) {
URI url = buildUrl(resource);
create(url, object, responseType);
}
public void update(String resource, Object object, String id) {
URI url = buildUrl(resource + "/" + id);
this.put(url, object);
}
public void delete(String resource, String id) {
HttpEntity<String> entity = new HttpEntity<String>(constructHttpHeader());
URI url = buildUrl(resource + "/" + id);
this.exchange(url, HttpMethod.DELETE, entity, String.class);
}
public void delete(URI url, String body) {
HttpEntity<String> entity = new HttpEntity(body, constructHttpHeader());
this.postForEntity(url, entity, String.class);
}
private <T> HttpEntity<T> buildRequest(T entity) {
HttpHeaders headers = new HttpHeaders();
headers.set(org.apache.http.HttpHeaders.ACCEPT, mediaType.toString());
headers.setContentType(mediaType);
headers.set(org.apache.http.HttpHeaders.USER_AGENT, userAgent);
return new HttpEntity<T>(entity, headers);
}
private URI buildUrl(String resource) {
try {
return new URI(baseUri + "/" + resource);
} catch (URISyntaxException e) {
throw new RestClientException(e.getMessage(), e);
}
}
private <T> T readDataElement(String fullJson, Class<T> responseType) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(fullJson).findPath(objectRootPath);
return mapper.readValue(jsonNode, responseType);
} catch (JsonProcessingException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
} catch (IOException ex) {
throw new RestClientException("Unable to parse json response - " + ex.getMessage(), ex);
}
}
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
if (requestFactory == null) {
HttpClient client = buildClient();
requestFactory = new HttpComponentsClientHttpRequestFactory(client);
}
return requestFactory.createRequest(uri, httpMethod);
}
private HttpClient buildClient() {
HttpClientBuilder builder = HttpClientBuilder.create();
// Fiddler Proxy
if (isNotEmpty(proxyHost) && proxyPort > 0) {
HttpHost proxy = new HttpHost(proxyHost, proxyPort);
builder.setProxy(proxy);
}
builder.setDefaultRequestConfig(buildRequestConfiguration());
customization.customize(builder);
enableSSL(builder);
return builder.build();
}
private void enableSSL(HttpClientBuilder builder) {
try {
SSLContext sslContext = createSSLContext();
builder.setSslcontext(sslContext);
SSLConnectionSocketFactory sslSocketFactory = createSSLSocketFactory(sslContext);
builder.setSSLSocketFactory(sslSocketFactory);
} catch(Exception e) {
LOGGER.error("Error enabling SSL in springRestClient");
}
}
private SSLContext createSSLContext() throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
TrustStrategy allTrust = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};
return SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, allTrust).build();
}
private SSLConnectionSocketFactory createSSLSocketFactory(SSLContext sslContext) {
return new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
}
private RequestConfig buildRequestConfiguration() {
RequestConfig.Builder requestConfig = RequestConfig.custom();
requestConfig = requestConfig.setConnectTimeout(this.timeout * 1000);
requestConfig = requestConfig.setConnectionRequestTimeout(this.timeout * 1000);
requestConfig = requestConfig.setSocketTimeout(this.timeout * 1000);
return requestConfig.build();
}
}
Regards,
Dinesh Babu.
-----Original Message-----
From: Stéphane Nicoll [mailto:snicoll@pivotal.io]
Sent: 22 January 2015 16:47
To: HttpClient User Discussion
Subject: Re: AbstractConnPool (httpcore-4.3.2.jar)- how to increase "available" connections
Hey,
Looks weird. Can you share your code using the RestTemplate?
S.
On Thu, Jan 22, 2015 at 5:43 PM, Dinesh Babu <di...@pb.com> wrote:
> Hi,
>
> I am a newbie to this group
>
> We are using Spring ReST Template to make web service calls which in
> turn uses Apache Http Client family of classes . We are seeing time
> out error from AbstractConnPool when we make calls . Details below
>
> 1) We make our first call http://abc:8080/def. For this call to
> complete we need to make another call which is below
> 2) http://abc:8080/efg . For this call to complete we need to make
> another call which is below
> 3) http://abc:8080/hij
>
> In AbstractConnPool the available connection is not more than 2 at any
> given point of time which is taken by my calls in (1) and (2) . When
> call
> (3) is made since there is no available connection, this call time out.
>
> a) Is there a solution for this scenario?
> b) Is there a way to increase the number of available connections?
>
> Regards,
> Dinesh Babu.
>
> ________________________________
>
>
________________________________
Re: AbstractConnPool (httpcore-4.3.2.jar)- how to increase
"available" connections
Posted by Stéphane Nicoll <sn...@pivotal.io>.
Hey,
Looks weird. Can you share your code using the RestTemplate?
S.
On Thu, Jan 22, 2015 at 5:43 PM, Dinesh Babu <di...@pb.com> wrote:
> Hi,
>
> I am a newbie to this group
>
> We are using Spring ReST Template to make web service calls which in turn
> uses Apache Http Client family of classes . We are seeing time out error
> from AbstractConnPool when we make calls . Details below
>
> 1) We make our first call http://abc:8080/def. For this call to complete
> we need to make another call which is below
> 2) http://abc:8080/efg . For this call to complete we need to make
> another call which is below
> 3) http://abc:8080/hij
>
> In AbstractConnPool the available connection is not more than 2 at any
> given point of time which is taken by my calls in (1) and (2) . When call
> (3) is made since there is no available connection, this call time out.
>
> a) Is there a solution for this scenario?
> b) Is there a way to increase the number of available connections?
>
> Regards,
> Dinesh Babu.
>
> ________________________________
>
>