Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.0.4"
".": "0.1.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 5
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-b7fdba3d3f97c7debc22c7ca30b828bce81bcd64648df8c94029b27a3321ebb9.yml
openapi_spec_hash: 03f1315f1d32ada42445ca920f047dff
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-38618cc5c938e87eeacf4893d6a6ba4e6ef7da390e6283dc7b50b484a7b97165.yml
openapi_spec_hash: b9e439ecee904ded01aa34efdee88856
config_hash: cb5d75abef6264b5d86448caf7295afa
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 0.1.0 (2026-01-01)

Full Changelog: [v0.0.4...v0.1.0](https://github.com/CASParser/cas-parser-java/compare/v0.0.4...v0.1.0)

### Features

* **api:** api update ([91a54b7](https://github.com/CASParser/cas-parser-java/commit/91a54b7acbf164ad459293fe697a4b0c9a795758))
* **api:** api update ([557721f](https://github.com/CASParser/cas-parser-java/commit/557721f0775228db057005e912d8f820f512fcca))
* **client:** expose sleeper option ([482319f](https://github.com/CASParser/cas-parser-java/commit/482319f0e19023df4e3ba5414e38914f6ad037fa))


### Bug Fixes

* **client:** deserialization of empty objects ([ce29632](https://github.com/CASParser/cas-parser-java/commit/ce29632f7f03c172ad042bbaa68e431ab2fd7fa7))
* **client:** ensure single timer is created per client ([482319f](https://github.com/CASParser/cas-parser-java/commit/482319f0e19023df4e3ba5414e38914f6ad037fa))
* **client:** incorrect `getPackageVersion` impl ([6772c5e](https://github.com/CASParser/cas-parser-java/commit/6772c5eeb5557a1e494852713cc55ec722b75145))


### Chores

* improve formatter performance ([692db64](https://github.com/CASParser/cas-parser-java/commit/692db64a36ef927e9c0ea23bd57192af99aaaf02))

## 0.0.4 (2025-09-13)

Full Changelog: [v0.0.3...v0.0.4](https://github.com/CASParser/cas-parser-java/compare/v0.0.3...v0.0.4)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2025 Cas Parser
Copyright 2026 Cas Parser

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

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

[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.4)
[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.0.4/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.4)
[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.1.0)
[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.1.0/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.1.0)

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

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

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

The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.4).
The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.1.0).

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

Expand All @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.casparser.in](https://docs.casp
### Gradle

```kotlin
implementation("com.cas_parser.api:cas-parser-java:0.0.4")
implementation("com.cas_parser.api:cas-parser-java:0.1.0")
```

### Maven
Expand All @@ -33,7 +33,7 @@ implementation("com.cas_parser.api:cas-parser-java:0.0.4")
<dependency>
<groupId>com.cas_parser.api</groupId>
<artifactId>cas-parser-java</artifactId>
<version>0.0.4</version>
<version>0.1.0</version>
</dependency>
```

Expand Down Expand Up @@ -248,13 +248,13 @@ The SDK uses the standard [OkHttp logging interceptor](https://github.com/square
Enable logging by setting the `CAS_PARSER_LOG` environment variable to `info`:

```sh
$ export CAS_PARSER_LOG=info
export CAS_PARSER_LOG=info
```

Or to `debug` for more verbose logging:

```sh
$ export CAS_PARSER_LOG=debug
export CAS_PARSER_LOG=debug
```

## ProGuard and R8
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {

allprojects {
group = "com.cas_parser.api"
version = "0.0.4" // x-release-please-version
version = "0.1.0" // x-release-please-version
}

subprojects {
Expand Down
1 change: 1 addition & 0 deletions cas-parser-java-client-okhttp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ dependencies {

testImplementation(kotlin("test"))
testImplementation("org.assertj:assertj-core:3.25.3")
testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.cas_parser.api.client.okhttp
import com.cas_parser.api.client.CasParserClient
import com.cas_parser.api.client.CasParserClientImpl
import com.cas_parser.api.core.ClientOptions
import com.cas_parser.api.core.Sleeper
import com.cas_parser.api.core.Timeout
import com.cas_parser.api.core.http.Headers
import com.cas_parser.api.core.http.HttpClient
Expand Down Expand Up @@ -120,6 +121,17 @@ class CasParserOkHttpClient private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The interface to use for delaying execution, like during retries.
*
* This is primarily useful for using fake delays in tests.
*
* Defaults to real execution delays.
*
* This class takes ownership of the sleeper and closes it when closed.
*/
fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }

/**
* The clock to use for operations that require timing, like retries.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.cas_parser.api.client.okhttp
import com.cas_parser.api.client.CasParserClientAsync
import com.cas_parser.api.client.CasParserClientAsyncImpl
import com.cas_parser.api.core.ClientOptions
import com.cas_parser.api.core.Sleeper
import com.cas_parser.api.core.Timeout
import com.cas_parser.api.core.http.Headers
import com.cas_parser.api.core.http.HttpClient
Expand Down Expand Up @@ -120,6 +121,17 @@ class CasParserOkHttpClientAsync private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The interface to use for delaying execution, like during retries.
*
* This is primarily useful for using fake delays in tests.
*
* Defaults to real execution delays.
*
* This class takes ownership of the sleeper and closes it when closed.
*/
fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }

/**
* The clock to use for operations that require timing, like retries.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import java.io.IOException
import java.io.InputStream
import java.net.Proxy
import java.time.Duration
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
Expand All @@ -29,8 +30,8 @@ import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import okio.BufferedSink

class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) :
HttpClient {
class OkHttpClient
private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient {

override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
val call = newCall(request, requestOptions)
Expand All @@ -50,20 +51,25 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC
): CompletableFuture<HttpResponse> {
val future = CompletableFuture<HttpResponse>()

request.body?.run { future.whenComplete { _, _ -> close() } }

newCall(request, requestOptions)
.enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
future.complete(response.toResponse())
}
val call = newCall(request, requestOptions)
call.enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
future.complete(response.toResponse())
}

override fun onFailure(call: Call, e: IOException) {
future.completeExceptionally(CasParserIoException("Request failed", e))
}
override fun onFailure(call: Call, e: IOException) {
future.completeExceptionally(CasParserIoException("Request failed", e))
}
)
}
)

future.whenComplete { _, e ->
if (e is CancellationException) {
call.cancel()
}
request.body?.close()
}

return future
}
Expand Down Expand Up @@ -109,19 +115,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC

val builder = Request.Builder().url(toUrl()).method(method.name, body)
headers.names().forEach { name ->
headers.values(name).forEach { builder.header(name, it) }
headers.values(name).forEach { builder.addHeader(name, it) }
}

if (
!headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0
) {
builder.header(
builder.addHeader(
"X-Stainless-Read-Timeout",
Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(),
)
}
if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) {
builder.header(
builder.addHeader(
"X-Stainless-Timeout",
Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.cas_parser.api.client.okhttp

import com.cas_parser.api.core.http.HttpMethod
import com.cas_parser.api.core.http.HttpRequest
import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
import com.github.tomakehurst.wiremock.junit5.WireMockTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.parallel.ResourceLock

@WireMockTest
@ResourceLock("https://github.com/wiremock/wiremock/issues/169")
internal class OkHttpClientTest {

private lateinit var baseUrl: String
private lateinit var httpClient: OkHttpClient

@BeforeEach
fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) {
baseUrl = wmRuntimeInfo.httpBaseUrl
httpClient = OkHttpClient.builder().build()
}

@Test
fun executeAsync_whenFutureCancelled_cancelsUnderlyingCall() {
stubFor(post(urlPathEqualTo("/something")).willReturn(ok()))
val responseFuture =
httpClient.executeAsync(
HttpRequest.builder()
.method(HttpMethod.POST)
.baseUrl(baseUrl)
.addPathSegment("something")
.build()
)
val call = httpClient.okHttpClient.dispatcher.runningCalls().single()

responseFuture.cancel(false)

// Should have cancelled the underlying call
assertThat(call.isCanceled()).isTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ private constructor(
* rarely needs to be overridden.
*/
@get:JvmName("jsonMapper") val jsonMapper: JsonMapper,
/**
* The interface to use for delaying execution, like during retries.
*
* This is primarily useful for using fake delays in tests.
*
* Defaults to real execution delays.
*
* This class takes ownership of the sleeper and closes it when closed.
*/
@get:JvmName("sleeper") val sleeper: Sleeper,
/**
* The clock to use for operations that require timing, like retries.
*
Expand Down Expand Up @@ -131,6 +141,7 @@ private constructor(
private var httpClient: HttpClient? = null
private var checkJacksonVersionCompatibility: Boolean = true
private var jsonMapper: JsonMapper = jsonMapper()
private var sleeper: Sleeper? = null
private var clock: Clock = Clock.systemUTC()
private var baseUrl: String? = null
private var headers: Headers.Builder = Headers.builder()
Expand All @@ -145,6 +156,7 @@ private constructor(
httpClient = clientOptions.originalHttpClient
checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility
jsonMapper = clientOptions.jsonMapper
sleeper = clientOptions.sleeper
clock = clientOptions.clock
baseUrl = clientOptions.baseUrl
headers = clientOptions.headers.toBuilder()
Expand Down Expand Up @@ -185,6 +197,17 @@ private constructor(
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper }

/**
* The interface to use for delaying execution, like during retries.
*
* This is primarily useful for using fake delays in tests.
*
* Defaults to real execution delays.
*
* This class takes ownership of the sleeper and closes it when closed.
*/
fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) }

/**
* The clock to use for operations that require timing, like retries.
*
Expand Down Expand Up @@ -369,6 +392,7 @@ private constructor(
*/
fun build(): ClientOptions {
val httpClient = checkRequired("httpClient", httpClient)
val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper())
val apiKey = checkRequired("apiKey", apiKey)

val headers = Headers.builder()
Expand All @@ -392,11 +416,13 @@ private constructor(
httpClient,
RetryingHttpClient.builder()
.httpClient(httpClient)
.sleeper(sleeper)
.clock(clock)
.maxRetries(maxRetries)
.build(),
checkJacksonVersionCompatibility,
jsonMapper,
sleeper,
clock,
baseUrl,
headers.build(),
Expand All @@ -421,5 +447,6 @@ private constructor(
*/
fun close() {
httpClient.close()
sleeper.close()
}
}
Loading
Loading