Skip to content

Commit a9bfefc

Browse files
oschwaldclaude
andcommitted
STF-322: Document transport-failure retry in README and CHANGELOG
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4e93c3e commit a9bfefc

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
5.0.3 (unreleased)
5+
------------------
6+
7+
* Added `WebServiceClient.Builder.maxRetries(int)` to bound transport-failure
8+
retries (default 1; set 0 to disable). See the README for retry semantics.
9+
410
5.0.2 (2025-12-08)
511
------------------
612

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,50 @@ are not created for each request.
7272
See the [API documentation](https://maxmind.github.io/GeoIP2-java/) for
7373
more details.
7474

75+
### Connection pooling and transport retries ###
76+
77+
`WebServiceClient` is thread-safe and reuses a pooled `HttpClient` across
78+
requests. Idle connections in the pool can be silently closed by load
79+
balancers or other intermediaries. When the next request reuses one of these
80+
half-closed connections, the JDK reports the failure as a `Connection reset`,
81+
`Broken pipe`, or related transport `IOException`.
82+
83+
To smooth over these intermittent transport failures, the SDK retries once
84+
by default. Any transport-level `IOException` raised by the underlying HTTP
85+
send is retried, with the following exclusions:
86+
87+
* `HttpTimeoutException` — a request-phase timeout. Connect-phase timeouts
88+
(`HttpConnectTimeoutException`) are also excluded because they extend
89+
`HttpTimeoutException`. The SDK honors the timeouts you configure.
90+
* `InterruptedIOException` — the calling thread was interrupted; the SDK
91+
honors the cancellation rather than override it.
92+
* Typically deterministic failures: `UnknownHostException`,
93+
`ConnectException`, `SSLHandshakeException`, `SSLPeerUnverifiedException`.
94+
Retrying these would just delay surfacing a config bug.
95+
* If the calling thread is already interrupted when the predicate runs, the
96+
retry is short-circuited regardless of the exception type.
97+
98+
HTTP 4xx and 5xx responses are not retried — they are returned as
99+
`HttpResponse` objects (not `IOException`s) and surfaced through the existing
100+
exception hierarchy. Web service requests are idempotent GETs, so retried
101+
requests are byte-identical to the original.
102+
103+
You can change the retry budget via the builder:
104+
105+
```java
106+
WebServiceClient client = new WebServiceClient.Builder(42, "license_key")
107+
.maxRetries(2) // up to two retries (three total attempts)
108+
.build();
109+
```
110+
111+
Set `.maxRetries(0)` to disable the retry entirely. Negative values throw
112+
`IllegalArgumentException`.
113+
114+
If you frequently see `Connection reset` errors, you can also reduce the
115+
JDK's keep-alive timeout via the system property
116+
`jdk.httpclient.keepalive.timeout` (in seconds) to evict pooled connections
117+
before any intermediary does so.
118+
75119
## Web Service Example ##
76120

77121
### Country Service ###

0 commit comments

Comments
 (0)