javaokhttp

Do OkHttpClient instances created with newBuilder() from common client share the same pools?


According to the docs of OkHttpClient, it is better to use a single shared instance.

In my case I need a client for HTTP requests and a client for WebSocket connections; both have different configurations.

So I created this class, which builds a base client and then calls BASE.newBuilder() for both HTTP and WS clients:

public class OkHttpClients{

    private static final OkHttpClient BASE = new OkHttpClient.Builder().build();

    private static final OkHttpClient HTTP = BASE.newBuilder()
        .followRedirects(false)
        .readTimeout(Duration.ofSeconds(5))
        .retryOnConnectionFailure(true)
        .build();

    private static final OkHttpClient WS = BASE.newBuilder()
        .pingInterval(Duration.ofMinutes(1))
        .readTimeout(Duration.ofMillis(0))
        .connectTimeout(Duration.ofMillis(0))
        .build();

    public static OkHttpClient getHttp(){
        return HTTP;
    }

    public static OkHttpClient getWS(){
        return WS;
    }

}

In my case, are the instances sharing the same inner pools, like OkHttpClient is saying?


Solution

  • According to the docs in the OkHttpClient class, the method newBuilder() allows to build and create a client that shares the same connection pool, thread pools, and configuration of the original one.

    Customize Your Client With newBuilder()

    You can customize a shared OkHttpClient instance with [newBuilder]. This builds a client that shares the same connection pool, thread pools, and configuration. Use the builder methods to add configuration to the derived client for a specific purpose.

    Regarding your question

    In my case the instances are sharing the same inner pools, like OkHttpClient is saying?

    Yes, and this can be easily tested by creating two OkHttpClient instances, where the second is created with newBuilder() from the first client, and then checking if both of them share the same instance of ConnectionPool.

    OkHttpClient okHttpClient1 = new OkHttpClient();
    OkHttpClient okHttpClient2 = okHttpClient1.newBuilder().build();
    
    // Prints true
    System.out.println(okHttpClient1.connectionPool().equals(okHttpClient2.connectionPool()));
    

    Regarding your last question

    Is it good to do this in my case?

    Probably not, but I may have misunderstood you case.

    From my understanding, you want to have two separate clients that handle disntinctively HTTP requests and WebSockets requests. The fact that you want them to be two separate instances leads me to think that you do not want them to share any state. So, if you truly want to handle those requests separately, you should create two competely independent instances.

    public class OkHttpClients {
    
        private static final OkHttpClient HTTP = new OkHttpClient.Builder()
            .followRedirects(false)
            .readTimeout(Duration.ofSeconds(5))
            .retryOnConnectionFailure(true)
            .build();
    
        private static final OkHttpClient WS = new OkHttpClient.Builder()
            .pingInterval(Duration.ofMinutes(1))
            .readTimeout(Duration.ofMillis(0))
            .connectTimeout(Duration.ofMillis(0))
            .build();
    
        public static OkHttpClient getHttp(){
            return HTTP;
        }
    
        public static OkHttpClient getWS(){
            return WS;
        }
    }
    

    Keep in mind that the docs recommend using a single OkHttpClient for an optimal usage; It is not mandatory.

    Instead, if you specifically want the two clients to share their state while having different configurations, you could keep your code as it is.