Skip to content

Commit dba2661

Browse files
release: 5.3.0 (#543)
* docs: update documentation links to be more uniform * docs(client): update jackson compat error message * docs: explain jackson compat in readme * perf(internal): improve compilation+test speed * docs: explain http client customization * feat(api): api update * codegen metadata * release: 5.3.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent 6ead207 commit dba2661

19 files changed

Lines changed: 189 additions & 122 deletions

.github/workflows/publish-sonatype.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
export -- GPG_SIGNING_KEY_ID
3434
printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD"
3535
GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')"
36-
./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD"
36+
./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache
3737
env:
3838
SONATYPE_USERNAME: ${{ secrets.FINCH_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }}
3939
SONATYPE_PASSWORD: ${{ secrets.FINCH_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }}

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "5.2.0"
2+
".": "5.3.0"
33
}

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 45
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-ff61a38530dfae03860bceb49379e84bfc7434eeb5d2f1dc9677cb162014faf1.yml
3-
openapi_spec_hash: df3bdaf4acf575bb07767cae7ca24d69
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-46640c1b468813b828be61b1af5cb5450f9555c4c757c5a740189906a8d56672.yml
3+
openapi_spec_hash: 1d5845ae61d2c0a143db43d579b048c5
44
config_hash: 53778a0b839c4f6ad34fbba051f5e8a6

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# Changelog
22

3+
## 5.3.0 (2025-04-18)
4+
5+
Full Changelog: [v5.2.0...v5.3.0](https://github.com/Finch-API/finch-api-java/compare/v5.2.0...v5.3.0)
6+
7+
### Features
8+
9+
* **api:** api update ([8a943e8](https://github.com/Finch-API/finch-api-java/commit/8a943e843922b45684c633f2ef1d0e158b04c6d7))
10+
11+
12+
### Performance Improvements
13+
14+
* **internal:** improve compilation+test speed ([7ce9aa1](https://github.com/Finch-API/finch-api-java/commit/7ce9aa1115f40676d990dabb5fbeb365b834cdcc))
15+
16+
17+
### Documentation
18+
19+
* **client:** update jackson compat error message ([3966f0e](https://github.com/Finch-API/finch-api-java/commit/3966f0eb05820ed6359991b877d3599727b295d7))
20+
* explain http client customization ([09d6b33](https://github.com/Finch-API/finch-api-java/commit/09d6b33bc87d1232cc855d0e9621a4f594985878))
21+
* explain jackson compat in readme ([acd26d9](https://github.com/Finch-API/finch-api-java/commit/acd26d9181ec31200b4c820bffde37761aa18d52))
22+
* update documentation links to be more uniform ([184534f](https://github.com/Finch-API/finch-api-java/commit/184534f3eda9aeffde671073fcd6b140620da87e))
23+
324
## 5.2.0 (2025-04-12)
425

526
Full Changelog: [v5.1.0...v5.2.0](https://github.com/Finch-API/finch-api-java/compare/v5.1.0...v5.2.0)

README.md

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<!-- x-release-please-start-version -->
44

5-
[![Maven Central](https://img.shields.io/maven-central/v/com.tryfinch.api/finch-java)](https://central.sonatype.com/artifact/com.tryfinch.api/finch-java/5.2.0)
6-
[![javadoc](https://javadoc.io/badge2/com.tryfinch.api/finch-java/5.2.0/javadoc.svg)](https://javadoc.io/doc/com.tryfinch.api/finch-java/5.2.0)
5+
[![Maven Central](https://img.shields.io/maven-central/v/com.tryfinch.api/finch-java)](https://central.sonatype.com/artifact/com.tryfinch.api/finch-java/5.3.0)
6+
[![javadoc](https://javadoc.io/badge2/com.tryfinch.api/finch-java/5.3.0/javadoc.svg)](https://javadoc.io/doc/com.tryfinch.api/finch-java/5.3.0)
77

88
<!-- x-release-please-end -->
99

@@ -15,7 +15,7 @@ It is generated with [Stainless](https://www.stainless.com/).
1515

1616
<!-- x-release-please-start-version -->
1717

18-
The REST API documentation can be found on [developer.tryfinch.com](https://developer.tryfinch.com/). Javadocs are also available on [javadoc.io](https://javadoc.io/doc/com.tryfinch.api/finch-java/5.2.0).
18+
The REST API documentation can be found on [developer.tryfinch.com](https://developer.tryfinch.com/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.tryfinch.api/finch-java/5.3.0).
1919

2020
<!-- x-release-please-end -->
2121

@@ -26,7 +26,7 @@ The REST API documentation can be found on [developer.tryfinch.com](https://deve
2626
### Gradle
2727

2828
```kotlin
29-
implementation("com.tryfinch.api:finch-java:5.2.0")
29+
implementation("com.tryfinch.api:finch-java:5.3.0")
3030
```
3131

3232
### Maven
@@ -35,7 +35,7 @@ implementation("com.tryfinch.api:finch-java:5.2.0")
3535
<dependency>
3636
<groupId>com.tryfinch.api</groupId>
3737
<artifactId>finch-java</artifactId>
38-
<version>5.2.0</version>
38+
<version>5.3.0</version>
3939
</dependency>
4040
```
4141

@@ -295,6 +295,17 @@ both of which will raise an error if the signature is invalid.
295295
Note that the "body" parameter must be the raw JSON string sent from the server (do not parse it first).
296296
The `.unwrap()` method can parse this JSON for you.
297297

298+
## Jackson
299+
300+
The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.
301+
302+
The SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).
303+
304+
If the SDK threw an exception, but you're _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`FinchOkHttpClient`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt) or [`FinchOkHttpClientAsync`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt).
305+
306+
> [!CAUTION]
307+
> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.
308+
298309
## Network options
299310

300311
### Retries
@@ -372,6 +383,42 @@ FinchClient client = FinchOkHttpClient.builder()
372383
.build();
373384
```
374385

386+
### Custom HTTP client
387+
388+
The SDK consists of three artifacts:
389+
390+
- `finch-java-core`
391+
- Contains core SDK logic
392+
- Does not depend on [OkHttp](https://square.github.io/okhttp)
393+
- Exposes [`FinchClient`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClient.kt), [`FinchClientAsync`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientAsync.kt), [`FinchClientImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientImpl.kt), and [`FinchClientAsyncImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientAsyncImpl.kt), all of which can work with any HTTP client
394+
- `finch-java-client-okhttp`
395+
- Depends on [OkHttp](https://square.github.io/okhttp)
396+
- Exposes [`FinchOkHttpClient`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt) and [`FinchOkHttpClientAsync`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt), which provide a way to construct [`FinchClientImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientImpl.kt) and [`FinchClientAsyncImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientAsyncImpl.kt), respectively, using OkHttp
397+
- `finch-java`
398+
- Depends on and exposes the APIs of both `finch-java-core` and `finch-java-client-okhttp`
399+
- Does not have its own logic
400+
401+
This structure allows replacing the SDK's default HTTP client without pulling in unnecessary dependencies.
402+
403+
#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)
404+
405+
> [!TIP]
406+
> Try the available [network options](#network-options) before replacing the default client.
407+
408+
To use a customized `OkHttpClient`:
409+
410+
1. Replace your [`finch-java` dependency](#installation) with `finch-java-core`
411+
2. Copy `finch-java-client-okhttp`'s [`OkHttpClient`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/OkHttpClient.kt) class into your code and customize it
412+
3. Construct [`FinchClientImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientImpl.kt) or [`FinchClientAsyncImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientAsyncImpl.kt), similarly to [`FinchOkHttpClient`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt) or [`FinchOkHttpClientAsync`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt), using your customized client
413+
414+
### Completely custom HTTP client
415+
416+
To use a completely custom HTTP client:
417+
418+
1. Replace your [`finch-java` dependency](#installation) with `finch-java-core`
419+
2. Write a class that implements the [`HttpClient`](finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/HttpClient.kt) interface
420+
3. Construct [`FinchClientImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientImpl.kt) or [`FinchClientAsyncImpl`](finch-java-core/src/main/kotlin/com/tryfinch/api/client/FinchClientAsyncImpl.kt), similarly to [`FinchOkHttpClient`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt) or [`FinchOkHttpClientAsync`](finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt), using your new client class
421+
375422
## Undocumented API functionality
376423

377424
The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repositories {
88

99
allprojects {
1010
group = "com.tryfinch.api"
11-
version = "5.2.0" // x-release-please-version
11+
version = "5.3.0" // x-release-please-version
1212
}
1313

1414
subprojects {

buildSrc/src/main/kotlin/finch.kotlin.gradle.kts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ plugins {
99

1010
kotlin {
1111
jvmToolchain {
12-
languageVersion.set(JavaLanguageVersion.of(17))
12+
languageVersion.set(JavaLanguageVersion.of(21))
1313
}
1414

1515
compilerOptions {
@@ -19,6 +19,8 @@ kotlin {
1919
// Suppress deprecation warnings because we may still reference and test deprecated members.
2020
// TODO: Replace with `-Xsuppress-warning=DEPRECATION` once we use Kotlin compiler 2.1.0+.
2121
"-nowarn",
22+
// Use as many threads as there are CPU cores on the machine for compilation.
23+
"-Xbackend-threads=0",
2224
)
2325
jvmTarget.set(JvmTarget.JVM_1_8)
2426
languageVersion.set(KotlinVersion.KOTLIN_1_8)
@@ -34,8 +36,7 @@ configure<SpotlessExtension> {
3436
}
3537
}
3638

37-
// Run tests in parallel to some degree.
3839
tasks.withType<Test>().configureEach {
39-
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1)
40-
forkEvery = 100
40+
systemProperty("junit.jupiter.execution.parallel.enabled", true)
41+
systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent")
4142
}

finch-java-core/src/main/kotlin/com/tryfinch/api/core/Check.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ internal fun checkJacksonVersionCompatibility() {
6262
}
6363
check(incompatibleJacksonVersions.isEmpty()) {
6464
"""
65-
This SDK depends on Jackson version $MINIMUM_JACKSON_VERSION, but the following incompatible Jackson versions were detected at runtime:
65+
This SDK requires a minimum Jackson version of $MINIMUM_JACKSON_VERSION, but the following incompatible Jackson versions were detected at runtime:
6666
6767
${incompatibleJacksonVersions.asSequence().map { (version, incompatibilityReason) ->
6868
"- `${version.toFullString().replace("/", ":")}` ($incompatibilityReason)"
@@ -73,6 +73,8 @@ This can happen if you are either:
7373
2. Depending on some library that depends on different Jackson versions, potentially transitively
7474
7575
Double-check that you are depending on compatible Jackson versions.
76+
77+
See https://www.github.com/Finch-API/finch-api-java#jackson for more information.
7678
"""
7779
.trimIndent()
7880
}

finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/RetryingHttpClient.kt

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import kotlin.math.pow
2323
class RetryingHttpClient
2424
private constructor(
2525
private val httpClient: HttpClient,
26+
private val sleeper: Sleeper,
2627
private val clock: Clock,
2728
private val maxRetries: Int,
2829
private val idempotencyHeader: String?,
@@ -62,10 +63,10 @@ private constructor(
6263
null
6364
}
6465

65-
val backoffMillis = getRetryBackoffMillis(retries, response)
66+
val backoffDuration = getRetryBackoffDuration(retries, response)
6667
// All responses must be closed, so close the failed one before retrying.
6768
response?.close()
68-
Thread.sleep(backoffMillis.toMillis())
69+
sleeper.sleep(backoffDuration)
6970
}
7071
}
7172

@@ -111,10 +112,10 @@ private constructor(
111112
}
112113
}
113114

114-
val backoffMillis = getRetryBackoffMillis(retries, response)
115+
val backoffDuration = getRetryBackoffDuration(retries, response)
115116
// All responses must be closed, so close the failed one before retrying.
116117
response?.close()
117-
return sleepAsync(backoffMillis.toMillis()).thenCompose {
118+
return sleeper.sleepAsync(backoffDuration).thenCompose {
118119
executeWithRetries(requestWithRetryCount, requestOptions)
119120
}
120121
}
@@ -179,7 +180,7 @@ private constructor(
179180
// retried.
180181
throwable is IOException || throwable is FinchIoException
181182

182-
private fun getRetryBackoffMillis(retries: Int, response: HttpResponse?): Duration {
183+
private fun getRetryBackoffDuration(retries: Int, response: HttpResponse?): Duration {
183184
// About the Retry-After header:
184185
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
185186
response
@@ -226,33 +227,40 @@ private constructor(
226227

227228
companion object {
228229

229-
private val TIMER = Timer("RetryingHttpClient", true)
230-
231-
private fun sleepAsync(millis: Long): CompletableFuture<Void> {
232-
val future = CompletableFuture<Void>()
233-
TIMER.schedule(
234-
object : TimerTask() {
235-
override fun run() {
236-
future.complete(null)
237-
}
238-
},
239-
millis,
240-
)
241-
return future
242-
}
243-
244230
@JvmStatic fun builder() = Builder()
245231
}
246232

247233
class Builder internal constructor() {
248234

249235
private var httpClient: HttpClient? = null
236+
private var sleeper: Sleeper =
237+
object : Sleeper {
238+
239+
private val timer = Timer("RetryingHttpClient", true)
240+
241+
override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis())
242+
243+
override fun sleepAsync(duration: Duration): CompletableFuture<Void> {
244+
val future = CompletableFuture<Void>()
245+
timer.schedule(
246+
object : TimerTask() {
247+
override fun run() {
248+
future.complete(null)
249+
}
250+
},
251+
duration.toMillis(),
252+
)
253+
return future
254+
}
255+
}
250256
private var clock: Clock = Clock.systemUTC()
251257
private var maxRetries: Int = 2
252258
private var idempotencyHeader: String? = null
253259

254260
fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient }
255261

262+
@JvmSynthetic internal fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper }
263+
256264
fun clock(clock: Clock) = apply { this.clock = clock }
257265

258266
fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries }
@@ -262,9 +270,17 @@ private constructor(
262270
fun build(): HttpClient =
263271
RetryingHttpClient(
264272
checkRequired("httpClient", httpClient),
273+
sleeper,
265274
clock,
266275
maxRetries,
267276
idempotencyHeader,
268277
)
269278
}
279+
280+
internal interface Sleeper {
281+
282+
fun sleep(duration: Duration)
283+
284+
fun sleepAsync(duration: Duration): CompletableFuture<Void>
285+
}
270286
}

finch-java-core/src/main/kotlin/com/tryfinch/api/models/Company.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ private constructor(
131131
fun primaryEmail(): Optional<String> = primaryEmail.getOptional("primary_email")
132132

133133
/**
134-
* The phone number of the main administrator on the account. Format: `XXXXXXXXXX`
134+
* The phone number of the main administrator on the account. Format: E.164, with extension
135+
* where applicable, e.g. `+NNNNNNNNNNN xExtension`
135136
*
136137
* @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the
137138
* server responded with an unexpected value).
@@ -431,7 +432,10 @@ private constructor(
431432
this.primaryEmail = primaryEmail
432433
}
433434

434-
/** The phone number of the main administrator on the account. Format: `XXXXXXXXXX` */
435+
/**
436+
* The phone number of the main administrator on the account. Format: E.164, with extension
437+
* where applicable, e.g. `+NNNNNNNNNNN xExtension`
438+
*/
435439
fun primaryPhoneNumber(primaryPhoneNumber: String?) =
436440
primaryPhoneNumber(JsonField.ofNullable(primaryPhoneNumber))
437441

0 commit comments

Comments
 (0)