Skip to main content

OkHttp Transport

Maven Dependencies​

<!-- Juneau transport adapter -->
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-client-okhttp</artifactId>
<version>${juneau.version}</version>
</dependency>

<!-- OkHttp 5 (transitive from the adapter, pinned here for clarity) -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-jvm</artifactId>
<version>5.3.2</version>
</dependency>
OkHttp 5 artifact name

The adapter targets OkHttp 5.x, whose Maven artifact is okhttp-jvm (not the older okhttp artifact used by OkHttp 4.x). Make sure your dependency manager resolves the correct artifact.


Overview​

juneau-rest-client-okhttp provides an HttpTransport implementation backed by OkHttp 5.x (com.squareup.okhttp3:okhttp-jvm). Consider it when:

  • You want transparent HTTP/2 with automatic HTTP/1.1 fallback.
  • You are developing for Android, where OkHttp is the de-facto HTTP client.
  • You want efficient request/response body streaming with minimal in-memory buffering (OkHttp streams the request body directly to the socket when the content length is known).
  • You rely on OkHttp-native interceptors, authenticators, or cookie jars elsewhere in your application and want to share the same OkHttpClient instance.

The transport is auto-discovered via ServiceLoader when the module is on the classpath. An explicit .transport(...) call always wins over auto-discovery.


Getting Started​

Zero-configuration default​

import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.okhttp.*;

RestClient client = RestClient.builder()
.transport(OkHttpTransport.create()) // wraps new OkHttpClient()
.serializer(Json5Serializer.DEFAULT)
.parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();

try (var resp = client.get("/users/123").run()) {
var user = resp.body().as(User.class);
}

client.close();

OkHttpTransport.create() is shorthand for OkHttpTransport.builder().build(). It creates a new OkHttpClient with default settings.

Auto-discovery​

Add the module to the classpath and omit the .transport(...) call:

RestClient client = RestClient.builder()
.serializer(Json5Serializer.DEFAULT)
.parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();

Configuring the Underlying OkHttpClient​

Use OkHttpTransportBuilder.httpClient(OkHttpClient) to supply your own OkHttpClient. The transport will call dispatcher().executorService().shutdown() and connectionPool().evictAll() on it when RestClient.close() is called.

import okhttp3.*;
import org.apache.juneau.marshall.json5.*;
import org.apache.juneau.rest.client.*;
import org.apache.juneau.rest.client.okhttp.*;

OkHttpClient okClient = new OkHttpClient.Builder()
.connectTimeout(java.time.Duration.ofSeconds(5))
.readTimeout(java.time.Duration.ofSeconds(30))
.build();

RestClient client = RestClient.builder()
.transport(OkHttpTransport.builder()
.httpClient(okClient)
.build())
.serializer(Json5Serializer.DEFAULT)
.parser(Json5Parser.DEFAULT)
.rootUrl("https://api.example.com")
.build();

Sharing One OkHttpClient Across Multiple RestClients​

OkHttp's documentation strongly recommends sharing a single OkHttpClient instance across the application so that its connection pool and thread pool are reused. Pass the same instance to each adapter:

OkHttpClient shared = new OkHttpClient();

RestClient users = RestClient.builder()
.transport(OkHttpTransport.builder().httpClient(shared).build())
.rootUrl("https://users.example.com")
.build();

RestClient orders = RestClient.builder()
.transport(OkHttpTransport.builder().httpClient(shared).build())
.rootUrl("https://orders.example.com")
.build();

When sharing, managing the OkHttpClient lifecycle (shutdown) is the caller's responsibility.

Connection Pooling​

OkHttp manages its connection pool internally. You can tune it via ConnectionPool:

import okhttp3.*;

OkHttpClient pooled = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(
20, // max idle connections
5, java.util.concurrent.TimeUnit.MINUTES)) // keep-alive duration
.build();

SSL / TLS​

import javax.net.ssl.*;
import okhttp3.*;

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);

OkHttpClient tlsClient = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
.build();

OkHttp Interceptors​

OkHttp-native interceptors can be wired through the OkHttpClient builder and are transparent to Juneau's own interceptor chain:

OkHttpClient intercepted = new OkHttpClient.Builder()
.addInterceptor(chain -> {
Request request = chain.request().newBuilder()
.addHeader("X-Correlation-Id", UUID.randomUUID().toString())
.build();
return chain.proceed(request);
})
.build();

Lifecycle and Shutdown​

OkHttpTransport.close() drains the connection pool and shuts down the dispatcher's thread pool:

// httpClient.dispatcher().executorService().shutdown();
// httpClient.connectionPool().evictAll();

If you supplied a shared OkHttpClient, call close() on the last RestClient to use it, or manage the OkHttpClient lifecycle yourself.


See Also​