I have two Spring Boot Services A and B. Also an external service C. That's the request path:
Web Browser <-> service A <-> Service B <-> External Service C
The external service is returning a resource which goes back to frontend. For communication between A, B and C I'm using Rest Template. Everything goes fine when entering the Web App but as soon as I'm running BDD tests which are running in parallel (9 threads) I'm getting NoHttpResponseException in service B when calling External Service C.
org.apache.http.NoHttpResponseException Service_C failed to respond
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:141)
at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
Here is my Rest Template configuration:
@Bean
public RestTemplate restTemplateExternal() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpComponentsClientHttpRequestFactory requestFactory = getRequestFactoryWithDisabledSSLValidation();
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}
private HttpComponentsClientHttpRequestFactory getRequestFactoryWithDisabledSSLValidation() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setSSLSocketFactory(csf)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
return requestFactory;
}
I've already tried to call connectionManager.setValidateAfterInactivity(0);
but it doesn't help.
Let me add that all the request from service B to external service C are to the same endpoint. Only parameter (x) is changing:/resource?param={x}
To be honest I'm not 100% sure if HttpClient is gonna be created with each request to service (RestTemplate bean is Singleton) or is that only one instance per service?
Maybe i need to 'setDefaultMaxPerRoute' in Connection Manager? If yes then how do i distinguish what is the proper number? I'd really appreciate a brief description of how to properly configure RestTemplate in such case.