okhttp setSslSocketFacotry vs okhttp3 sslSocketFactory with different output - spring-boot

I have to move from okhttp/setSslSocketFacotry to okhttp3/sslSocketFactory but I got different output on my variables
On okhttpv2 with,
client0.setSslSocketFactory(ctx.getSocketFactory());
With okhttp3,
OkHttpClient client0 = new OkHttpClient.Builder()
.sslSocketFactory(ctx.getSocketFactory())
.writeTimeout(timeout * 1000L, TimeUnit.MILLISECONDS)
.readTimeout(timeout * 1000L, TimeUnit.MILLISECONDS)
.build();
You could see the full code here in my previous post,
okhttp to okhttp3 with setSslSocketFactory, setWriteTimeout and setReadTimeout

Related

How can I configure the socket option "keepalive" for Jedis client while using Redis database?

I want to configure my client's socket options as in the following example which is created for Lettuce. Is there a way to make it in Jedis?
#Bean
public LettucePoolingClientConfiguration lettucePoolConfig() {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxIdle(poolMaxIdle);
poolConfig.setMinIdle(poolMinIdle);
poolConfig.setMaxTotal(poolMaxActive);
SocketOptions socketOptions = SocketOptions.builder().keepAlive(
SocketOptions.KeepAliveOptions.builder()
.enable(true)
.idle(Duration.ofMinutes(3))
.count(3)
.interval(Duration.ofSeconds(10))
.build()).build();
ClientOptions clientOptions = ClientOptions.builder()
.socketOptions(socketOptions)
.build();
return LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig)
.readFrom(ReadFrom.MASTER)
.clientOptions(clientOptions)
.build();
}

Replace org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory

When I upgrade implementation 'org.springframework.cloud:spring-cloud-openfeign-core:2.2.2.RELEASE' to latest version implementation 'org.springframework.cloud:spring-cloud-openfeign-core:3.1.1'
I get error for this imported class:
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
#Bean
public Client client(
HttpClientConnectionManager httpClientConnectionManager,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
CloseableHttpClient closeableHttpClient = HttpClients.custom()
.setConnectionManager(httpClientConnectionManager)
.build();
ApacheHttpClient delegate = new ApacheHttpClient(closeableHttpClient);
return new LoadBalancerFeignClient(delegate, lbClientFactory, clientFactory);
}
Do you know how I have to replace them in order to use the latest version?
ribbon was excluded from that spring boot version, you should now use loadbalancer instead. Check this class org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration, from my POV, you just need to remove all your ribbon dependencies from the code and that's it.

Unable to Extract trust manager on IBM JRE8 with OKHTTP3

Can Any one help on this please.
I am also using OKHTTP3 version 4.8.1 to write HTTP2 client . Its Working on Oracle JDK 8 but not working on IBM JRE 8.
Error message:
java.lang.IllegalStateException: Unable to extract the trust manager on okhttp3.internal.Platform#e85a0ce8, sslSocketFactory is class com.ibm.jsse2.SSLSocketFactoryImpl.
Thank you
You are relying on a long deprecated method
https://github.com/square/okhttp/blob/cd722373281202492043f4294fccfe6f691ddc01/okhttp/src/main/kotlin/okhttp3/OkHttpClient.kt#L741
It's deprecated because it had to assume a lot about the JVM, that breaks on each JVM update or across vendors. You should instead call the method with X509TrustManager as a parameter
https://github.com/square/okhttp/blob/cd722373281202492043f4294fccfe6f691ddc01/okhttp/src/main/kotlin/okhttp3/OkHttpClient.kt#L767
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager)
.build();

How to correctly instantiate RestTemplate without leaking resources

Please I have the following bean definitions
#Bean
public RestTemplate produceRestTemplate(ClientHttpRequestFactory requestFactory){
RestTemplate restTemplate = new RestTemplate(requestFactory);
restTemplate.setErrorHandler(restTemplateErrorHandler);
return restTemplate;
}
#Bean
public ClientHttpRequestFactory createRequestFactory() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(maxTotalConn);
connectionManager.setDefaultMaxPerRoute(maxPerChannel);
RequestConfig config = RequestConfig.custom().setConnectTimeout(100000).build();
CloseableHttpClient httpClient = HttpClients.createDefault();
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
The code works well but the problem is that fortify flags the code above as being potentially problematic with the following
"The function createRequestFactory() sometimes
fails to release a socket allocated by createDefault() on line 141."
Please anyone with any ideas as to how to correctly do this without fortify raising alarms
Thanks in advance
I am pretty sure that you don't need to do anything. It looks to be a fortify issue that it might not be updated to this usage scenario. There is a mechanism to take exceptions when working with code analyzers - these tools are not always correct.
A Bit of Discussion
Imagine , you are using CloseableHttpClient in a scenario where there would be no #Bean or HttpComponentsClientHttpRequestFactory , then I would say that fortify is correct because that is the very intention of using a java.io.Closeable .
Spring beans are usually singleton with an intention of instance reuse so fortify should know that you are not creating multiple instances and close() method on AutoCloseable would be called when factory is destroyed at shutdown.
if you look at code of - org.springframework.http.client.HttpComponentsClientHttpRequestFactory , this is there.
/**
* Shutdown hook that closes the underlying
* {#link org.apache.http.conn.HttpClientConnectionManager ClientConnectionManager}'s
* connection pool, if any.
*/
#Override
public void destroy() throws Exception {
if (this.httpClient instanceof Closeable) {
((Closeable) this.httpClient).close();
}
}
Your fortify is looking at code in isolation and not in integrated way so its flagging.
Check this 2 points, for solving the problem.
If you never call the httpClient.close() method, sometime you can effectivlely
run out of socket.
If you're code call this method automatically somewhere there is no vuln and problem.
Anyway, this could be a FalsePositiv depending of the Version of the Java and Lib you use

Many Threads in "wait" when using RestTemplate

I'm having a problem with slowiness when many request come to my website, It starts to generate "Wait" threads, I've set up the rest template as a Bean
#Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(Integer.parseInt(env.getProperty("service.configuration.http.http-request-timeout")))
.setReadTimeout(Integer.parseInt(env.getProperty("service.configuration.http.http-request-timeout")))
.requestFactory(clientHttpRequestFactory())
.build();
}
When i look for the process which is generating that problem i find HttpClient in wait.
Anybody knows what can i do to solve this problem?
I'm using java8, apache tomcat, spring boot
In my past project I used this kind of configuration:
#Bean
public RestTemplate restTemplate()
{
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient());
RestTemplate result = new RestTemplate(factory);
return result;
}
#Bean
public HttpClient httpClient()
{
CloseableHttpClient httpClient = null;
//Use a connection pool
PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager();
HttpClientBuilder hcb = HttpClientBuilder.create();
//Close Idle connection after 5 seconds
pcm.closeIdleConnections(5000, TimeUnit.MILLISECONDS);
//Specify all the timeouts in milli-seconds
RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(5000).setSocketTimeout(5000).setConnectTimeout(5000).build();
hcb.setDefaultRequestConfig(config);
hcb.setConnectionManager(pcm).setConnectionManagerShared(true);
// Check if proxy is required to connect to the final resource
if (proxyEnable)
{
//If enabled.... configure it
BasicCredentialsProvider credentialProvider = new BasicCredentialsProvider();
AuthScope scope = new AuthScope(hostProxy, portProxy);
if( StringUtils.hasText(usernameProxy) && StringUtils.hasText(passwordProxy) )
{
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(usernameProxy, passwordProxy);
credentialProvider.setCredentials(scope, credentials);
}
hcb.setDefaultCredentialsProvider(credentialProvider).setRoutePlanner(proxyRoutePlanner);
}
//Use custom keepalive strategy
if (cas != null)
{
hcb.setKeepAliveStrategy(cas);
}
httpClient = hcb.build();
return httpClient;
}
Where cas is an instance of:
public class WsKeepAliveStrategy implements ConnectionKeepAliveStrategy
{
private Long timeout;
#Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context)
{
return timeout;
}
public void setTimeout(Long timeout)
{
this.timeout = timeout;
}
}
In this way I could configure httpclient in order to use a connection pool, specify when to close the idle connection and specify the socket timeout, connection timeout, connection request timeout
By using this configuration I add no more issue
I hope it can be useful
Angelo
Must be a case of missing timeout, should try to get the exact problem happening in your case, and change the setting causing that. Changing RequestFactory to another library may or may not solve that it all depends on the problem - so my advise is to identify it first.
For example:
We faced similar issue that our thread was getting stuck in restTemplate so we took a thread dump which were like
"pool-12-thread-1" #41 prio=5 os_prio=0 tid=0x00007f17a624e000 nid=0x3d runnable [0x00007f1738f96000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
- locked <0x00000000ebc7d888> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
- locked <0x00000000ebc7d8a0> (a sun.security.ssl.AppInputStream)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
- locked <0x00000000e94b9608> (a java.io.BufferedInputStream)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1569)
- locked <0x00000000d57e5a30> (a sun.net.www.protocol.https.DelegateHttpsURLConnection)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
- locked <0x00000000d57e5a30> (a sun.net.www.protocol.https.DelegateHttpsURLConnection)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:84)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652)
It clearly show that the reason is missing timeout in read so we added
final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(10_000); // 10 sec as needed by us
final RestTemplate restTemplate = new RestTemplate(requestFactory);
Similarly after you got the reason, add proper timeout
HERE explains why it happens.
This configuration is inline with another Baeldung's article about rest template builder. It seems nice and clean but it hides a default PoolingHttpClientConnectionManager with the defaultMaxPerRoute set to 5.
What does this default max per route means? It means that only 5 simultaneous HTTP connections to the same host will be possible.
So you can configure RestTemplate to use a pooled implementation such as HttpComponentsClientHttpRequestFactory with overridden defaultMaxPerRoute:
PoolingHttpClientConnectionManager poolingConnManager = new
PoolingHttpClientConnectionManager();
poolingConnManager.setMaxTotal(50);
poolingConnManager.setDefaultMaxPerRoute(50);

Resources