Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Integrating RestTemplate with an OkHttp Connection Pool in Spring Boot

Tech 2

OkHttp provides an efficient HTTP stack for RestTemplate by reusing sockets across requests to the same host, pooling idle connections to cut latency, transparently compressing responses with GZIP, and retrying recoverable network failures. With TLS support (including SNI/ALPN) and IP failover on connection issues, it’s a strong alterantive to the JDK HTTP client for production workloads.

Dependencies

Maven coordinates for OkHttp (Spring Boot’s spring-boot-starter-web already brings RestTemplate):

<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>okhttp</artifactId>
  <version>4.12.0</version>
</dependency>

Spring configuration (OkHttp client, connection pool, and RestTemplate)

package com.example.http;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

@Configuration
public class HttpClientConfig {

    // Reuse idle connections for up to 5 minutes, up to 200 idle sockets
    @Bean
    public ConnectionPool httpConnectionPool() {
        return new ConnectionPool(200, 5, TimeUnit.MINUTES);
    }

    @Bean
    public OkHttpClient okHttpClient(ConnectionPool httpConnectionPool) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectionPool(httpConnectionPool)
                .retryOnConnectionFailure(true)
                .followRedirects(true)
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS);

        // If you need to trust all certificates (NOT for production),
        // uncomment the following two lines and also declare the beans below.
        // builder.sslSocketFactory(insecureSslSocketFactory(), insecureTrustManager());
        // builder.hostnameVerifier((host, session) -> true);

        return builder.build();
    }

    @Bean
    public RestTemplate restTemplate(OkHttpClient okHttpClient) {
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory(okHttpClient));
    }

    // --- Optional: trust-all SSL (use only for testing) ---

    @Bean
    public X509TrustManager insecureTrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
                // no-op
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
                // no-op
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

    @Bean
    public SSLSocketFactory insecureSslSocketFactory() {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[]{insecureTrustManager()}, new SecureRandom());
            return ctx.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            throw new IllegalStateException("Unable to create insecure SSL context", e);
        }
    }
}

Example usage with RestTemplate

package com.example.http;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Service
public class RemoteApiClient {

    private final RestTemplate restTemplate;

    public RemoteApiClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String getUser(String userId) {
        String url = "https://httpbin.org/get?userId={id}";
        return restTemplate.getForObject(url, String.class, userId);
    }

    public String postPayload(Map<String, Object> payload) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(payload, headers);
        ResponseEntity<String> response = restTemplate.postForEntity("https://httpbin.org/post", entity, String.class);
        return response.getBody();
    }

    // Simple test invocation
    public static void main(String[] args) {
        // In a real application, Spring Boot will create beans and wire them.
        RestTemplate rt = new RestTemplate();
        RemoteApiClient client = new RemoteApiClient(rt);

        Map<String, Object> body = new HashMap<>();
        body.put("name", "alice");
        body.put("age", 30);

        System.out.println(client.getUser("123"));
        System.out.println(client.postPayload(body));
    }
}

Notes on tuning

  • Increase maxIdleConnections in ConnectionPool if you expect many distinct hosts or high fan-out, and extend keepAliveDuration for servers with long-lived keep-alives.
  • Consider setting a global call timeout if you need an overall per-request deadline: client.newBuilder().callTimeout(60, TimeUnit.SECONDS).
  • OkHttp enables transparent GZIP by default; avoid adding manual compression headers unless required by the server.
  • For production TLS, use system/default trust stores or a pinned certificate strategy instead of the trust-all example.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.