diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index de2352f..50b3403 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.52"
+ ".": "0.1.0-alpha.53"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7839d20..931081b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## 0.1.0-alpha.53 (2026-02-19)
+
+Full Changelog: [v0.1.0-alpha.52...v0.1.0-alpha.53](https://github.com/OneBusAway/java-sdk/compare/v0.1.0-alpha.52...v0.1.0-alpha.53)
+
+### Features
+
+* **client:** add connection pooling option ([9dcb580](https://github.com/OneBusAway/java-sdk/commit/9dcb580bc844c9f90296c4e4a2a8c2c53b70bb95))
+
+
+### Chores
+
+* **internal:** make `OkHttp` constructor internal ([ac8f1c2](https://github.com/OneBusAway/java-sdk/commit/ac8f1c28e6ec0a636fa725bd9f033703388b3282))
+
## 0.1.0-alpha.52 (2026-02-18)
Full Changelog: [v0.1.0-alpha.51...v0.1.0-alpha.52](https://github.com/OneBusAway/java-sdk/compare/v0.1.0-alpha.51...v0.1.0-alpha.52)
diff --git a/README.md b/README.md
index 8ce5406..bab555c 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.52)
-[](https://javadoc.io/doc/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.52)
+[](https://central.sonatype.com/artifact/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.53)
+[](https://javadoc.io/doc/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.53)
@@ -15,7 +15,7 @@ It is generated with [Stainless](https://www.stainless.com/).
-The REST API documentation can be found on [developer.onebusaway.org](https://developer.onebusaway.org). Javadocs are available on [javadoc.io](https://javadoc.io/doc/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.52).
+The REST API documentation can be found on [developer.onebusaway.org](https://developer.onebusaway.org). Javadocs are available on [javadoc.io](https://javadoc.io/doc/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.53).
@@ -26,7 +26,7 @@ The REST API documentation can be found on [developer.onebusaway.org](https://de
### Gradle
```kotlin
-implementation("org.onebusaway:onebusaway-sdk-java:0.1.0-alpha.52")
+implementation("org.onebusaway:onebusaway-sdk-java:0.1.0-alpha.53")
```
### Maven
@@ -35,7 +35,7 @@ implementation("org.onebusaway:onebusaway-sdk-java:0.1.0-alpha.52")
org.onebusaway
onebusaway-sdk-java
- 0.1.0-alpha.52
+ 0.1.0-alpha.53
```
@@ -335,6 +335,25 @@ OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
.build();
```
+### Connection pooling
+
+To customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods:
+
+```java
+import java.time.Duration;
+import org.onebusaway.client.OnebusawaySdkClient;
+import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
+
+OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
+ .fromEnv()
+ // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa.
+ .maxIdleConnections(10)
+ .keepAliveDuration(Duration.ofMinutes(2))
+ .build();
+```
+
+If both options are unset, OkHttp's default connection pool settings are used.
+
### HTTPS
> [!NOTE]
diff --git a/build.gradle.kts b/build.gradle.kts
index 53440ea..f6df474 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,7 +8,7 @@ repositories {
allprojects {
group = "org.onebusaway"
- version = "0.1.0-alpha.52" // x-release-please-version
+ version = "0.1.0-alpha.53" // x-release-please-version
}
subprojects {
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
index 5dcdf9c..915d5da 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
@@ -7,11 +7,13 @@ import java.time.Duration
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
+import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
+import okhttp3.ConnectionPool
import okhttp3.Dispatcher
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
@@ -34,7 +36,7 @@ import org.onebusaway.core.http.HttpResponse
import org.onebusaway.errors.OnebusawaySdkIoException
class OkHttpClient
-private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient {
+internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient {
override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
val call = newCall(request, requestOptions)
@@ -202,6 +204,8 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var dispatcherExecutorService: ExecutorService? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
@@ -213,6 +217,28 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
+ /**
+ * Sets the maximum number of idle connections kept by the underlying [ConnectionPool].
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Sets the keep-alive duration for idle connections in the underlying [ConnectionPool].
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
this.dispatcherExecutorService = dispatcherExecutorService
}
@@ -242,6 +268,22 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
.apply {
dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
+ val maxIdleConnections = maxIdleConnections
+ val keepAliveDuration = keepAliveDuration
+ if (maxIdleConnections != null && keepAliveDuration != null) {
+ connectionPool(
+ ConnectionPool(
+ maxIdleConnections,
+ keepAliveDuration.toNanos(),
+ TimeUnit.NANOSECONDS,
+ )
+ )
+ } else {
+ check((maxIdleConnections != null) == (keepAliveDuration != null)) {
+ "Both or none of `maxIdleConnections` and `keepAliveDuration` must be set, but only one was set"
+ }
+ }
+
val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
index 1399e4c..3f28f91 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
@@ -47,6 +47,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class OnebusawaySdkOkHttpClient private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
+ /**
+ * The maximum number of idle connections kept by the underlying OkHttp connection pool.
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Alias for [Builder.maxIdleConnections].
+ *
+ * This unboxed primitive overload exists for backwards compatibility.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int) =
+ maxIdleConnections(maxIdleConnections as Int?)
+
+ /**
+ * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
+ */
+ fun maxIdleConnections(maxIdleConnections: Optional) =
+ maxIdleConnections(maxIdleConnections.getOrNull())
+
+ /**
+ * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
+ /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
+ fun keepAliveDuration(keepAliveDuration: Optional) =
+ keepAliveDuration(keepAliveDuration.getOrNull())
+
/**
* The socket factory used to secure HTTPS connections.
*
@@ -317,6 +359,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .maxIdleConnections(maxIdleConnections)
+ .keepAliveDuration(keepAliveDuration)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
index 9a4f625..d4260af 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
@@ -47,6 +47,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
+ /**
+ * The maximum number of idle connections kept by the underlying OkHttp connection pool.
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Alias for [Builder.maxIdleConnections].
+ *
+ * This unboxed primitive overload exists for backwards compatibility.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int) =
+ maxIdleConnections(maxIdleConnections as Int?)
+
+ /**
+ * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
+ */
+ fun maxIdleConnections(maxIdleConnections: Optional) =
+ maxIdleConnections(maxIdleConnections.getOrNull())
+
+ /**
+ * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
+ /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
+ fun keepAliveDuration(keepAliveDuration: Optional) =
+ keepAliveDuration(keepAliveDuration.getOrNull())
+
/**
* The socket factory used to secure HTTPS connections.
*
@@ -317,6 +359,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .maxIdleConnections(maxIdleConnections)
+ .keepAliveDuration(keepAliveDuration)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)