diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index c7159c1..28e831b 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.0.2"
+ ".": "0.0.3"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 0caf7fc..92721c7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -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
-config_hash: 0e1291f316b20497ad29b59a231a8680
+config_hash: cb5d75abef6264b5d86448caf7295afa
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8db43c8..3e1e157 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
# Changelog
+## 0.0.3 (2025-08-22)
+
+Full Changelog: [v0.0.2...v0.0.3](https://github.com/CASParser/cas-parser-java/compare/v0.0.2...v0.0.3)
+
+### Chores
+
+* **ci:** reduce log noise ([b66b3f9](https://github.com/CASParser/cas-parser-java/commit/b66b3f9da67d09730f90fc863a3aa05bd54d1b14))
+* **client:** refactor closing / shutdown ([a96f2f2](https://github.com/CASParser/cas-parser-java/commit/a96f2f22d6b5e36631fd79ad19e71b45c33a1402))
+* **internal:** fix multipart tests ([c564310](https://github.com/CASParser/cas-parser-java/commit/c56431084f5366b0b5887619ca0e1e4c44fe6e6c))
+* **internal:** support running formatters directly ([aec2ce4](https://github.com/CASParser/cas-parser-java/commit/aec2ce4f099cfebef00d9357a1c1cc8280caa83b))
+
## 0.0.2 (2025-08-18)
Full Changelog: [v0.0.1...v0.0.2](https://github.com/CASParser/cas-parser-java/compare/v0.0.1...v0.0.2)
diff --git a/README.md b/README.md
index 7646bdb..0a2616d 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.2)
-[](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.2)
+[](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.3)
+[](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.3)
@@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/).
-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.2).
+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.3).
@@ -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.2")
+implementation("com.cas_parser.api:cas-parser-java:0.0.3")
```
### Maven
@@ -33,7 +33,7 @@ implementation("com.cas_parser.api:cas-parser-java:0.0.2")
com.cas_parser.api
cas-parser-java
- 0.0.2
+ 0.0.3
```
diff --git a/build.gradle.kts b/build.gradle.kts
index 48085d5..45a77c9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,7 +9,7 @@ repositories {
allprojects {
group = "com.cas_parser.api"
- version = "0.0.2" // x-release-please-version
+ version = "0.0.3" // x-release-please-version
}
subprojects {
diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt
index 2301ccd..d8b0b67 100644
--- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt
+++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt
@@ -46,7 +46,7 @@ class CasParserClientAsyncImpl(private val clientOptions: ClientOptions) : CasPa
override fun casGenerator(): CasGeneratorServiceAsync = casGenerator
- override fun close() = clientOptions.httpClient.close()
+ override fun close() = clientOptions.close()
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
CasParserClientAsync.WithRawResponse {
diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt
index 0104e8f..fe0f962 100644
--- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt
+++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt
@@ -46,7 +46,7 @@ class CasParserClientImpl(private val clientOptions: ClientOptions) : CasParserC
override fun casGenerator(): CasGeneratorService = casGenerator
- override fun close() = clientOptions.httpClient.close()
+ override fun close() = clientOptions.close()
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
CasParserClient.WithRawResponse {
diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt
index 516a36d..d330bc7 100644
--- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt
+++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt
@@ -21,6 +21,8 @@ private constructor(
* The HTTP client to use in the SDK.
*
* Use the one published in `cas-parser-java-client-okhttp` or implement your own.
+ *
+ * This class takes ownership of the client and closes it when closed.
*/
@get:JvmName("httpClient") val httpClient: HttpClient,
/**
@@ -157,6 +159,8 @@ private constructor(
* The HTTP client to use in the SDK.
*
* Use the one published in `cas-parser-java-client-okhttp` or implement your own.
+ *
+ * This class takes ownership of the client and closes it when closed.
*/
fun httpClient(httpClient: HttpClient) = apply {
this.httpClient = PhantomReachableClosingHttpClient(httpClient)
@@ -404,4 +408,18 @@ private constructor(
)
}
}
+
+ /**
+ * Closes these client options, relinquishing any underlying resources.
+ *
+ * This is purposefully not inherited from [AutoCloseable] because the client options are
+ * long-lived and usually should not be synchronously closed via try-with-resources.
+ *
+ * It's also usually not necessary to call this method at all. the default client automatically
+ * releases threads and connections if they remain idle, but if you are writing an application
+ * that needs to aggressively release unused resources, then you may call this method.
+ */
+ fun close() {
+ httpClient.close()
+ }
}
diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt
new file mode 100644
index 0000000..d26c7ba
--- /dev/null
+++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt
@@ -0,0 +1,58 @@
+package com.cas_parser.api.core
+
+import java.util.concurrent.Callable
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Future
+import java.util.concurrent.TimeUnit
+
+/**
+ * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom
+ * reachable.
+ *
+ * This class ensures the [ExecutorService] is shut down even if the user forgets to do it.
+ */
+internal class PhantomReachableExecutorService(private val executorService: ExecutorService) :
+ ExecutorService {
+ init {
+ closeWhenPhantomReachable(this) { executorService.shutdown() }
+ }
+
+ override fun execute(command: Runnable) = executorService.execute(command)
+
+ override fun shutdown() = executorService.shutdown()
+
+ override fun shutdownNow(): MutableList = executorService.shutdownNow()
+
+ override fun isShutdown(): Boolean = executorService.isShutdown
+
+ override fun isTerminated(): Boolean = executorService.isTerminated
+
+ override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean =
+ executorService.awaitTermination(timeout, unit)
+
+ override fun submit(task: Callable): Future = executorService.submit(task)
+
+ override fun submit(task: Runnable, result: T): Future =
+ executorService.submit(task, result)
+
+ override fun submit(task: Runnable): Future<*> = executorService.submit(task)
+
+ override fun invokeAll(
+ tasks: MutableCollection>
+ ): MutableList> = executorService.invokeAll(tasks)
+
+ override fun invokeAll(
+ tasks: MutableCollection>,
+ timeout: Long,
+ unit: TimeUnit,
+ ): MutableList> = executorService.invokeAll(tasks, timeout, unit)
+
+ override fun invokeAny(tasks: MutableCollection>): T =
+ executorService.invokeAny(tasks)
+
+ override fun invokeAny(
+ tasks: MutableCollection>,
+ timeout: Long,
+ unit: TimeUnit,
+ ): T = executorService.invokeAny(tasks, timeout, unit)
+}
diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt
index e85c9de..7fd81ef 100644
--- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt
+++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt
@@ -55,18 +55,6 @@ internal class CasParserCamsKfintechParamsTest {
val body = params._body()
- assertThat(body.filterValues { !it.value.isNull() })
- .usingRecursiveComparison()
- // TODO(AssertJ): Replace this and the `mapValues` below with:
- // https://github.com/assertj/assertj/issues/3165
- .withEqualsForType(
- { a, b -> a.readBytes() contentEquals b.readBytes() },
- InputStream::class.java,
- )
- .isEqualTo(
- mapOf().mapValues { (_, field) ->
- field.map { (it as? ByteArray)?.inputStream() ?: it }
- }
- )
+ assertThat(body.filterValues { !it.value.isNull() }).isEmpty()
}
}
diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt
index 778a492..6293280 100644
--- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt
+++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt
@@ -55,18 +55,6 @@ internal class CasParserCdslParamsTest {
val body = params._body()
- assertThat(body.filterValues { !it.value.isNull() })
- .usingRecursiveComparison()
- // TODO(AssertJ): Replace this and the `mapValues` below with:
- // https://github.com/assertj/assertj/issues/3165
- .withEqualsForType(
- { a, b -> a.readBytes() contentEquals b.readBytes() },
- InputStream::class.java,
- )
- .isEqualTo(
- mapOf().mapValues { (_, field) ->
- field.map { (it as? ByteArray)?.inputStream() ?: it }
- }
- )
+ assertThat(body.filterValues { !it.value.isNull() }).isEmpty()
}
}
diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt
index c593b64..fba23f6 100644
--- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt
+++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt
@@ -55,18 +55,6 @@ internal class CasParserNsdlParamsTest {
val body = params._body()
- assertThat(body.filterValues { !it.value.isNull() })
- .usingRecursiveComparison()
- // TODO(AssertJ): Replace this and the `mapValues` below with:
- // https://github.com/assertj/assertj/issues/3165
- .withEqualsForType(
- { a, b -> a.readBytes() contentEquals b.readBytes() },
- InputStream::class.java,
- )
- .isEqualTo(
- mapOf().mapValues { (_, field) ->
- field.map { (it as? ByteArray)?.inputStream() ?: it }
- }
- )
+ assertThat(body.filterValues { !it.value.isNull() }).isEmpty()
}
}
diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt
index f3795e8..795fbfd 100644
--- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt
+++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt
@@ -55,18 +55,6 @@ internal class CasParserSmartParseParamsTest {
val body = params._body()
- assertThat(body.filterValues { !it.value.isNull() })
- .usingRecursiveComparison()
- // TODO(AssertJ): Replace this and the `mapValues` below with:
- // https://github.com/assertj/assertj/issues/3165
- .withEqualsForType(
- { a, b -> a.readBytes() contentEquals b.readBytes() },
- InputStream::class.java,
- )
- .isEqualTo(
- mapOf().mapValues { (_, field) ->
- field.map { (it as? ByteArray)?.inputStream() ?: it }
- }
- )
+ assertThat(body.filterValues { !it.value.isNull() }).isEmpty()
}
}
diff --git a/cas-parser-java-proguard-test/build.gradle.kts b/cas-parser-java-proguard-test/build.gradle.kts
index dc5f093..de62f9c 100644
--- a/cas-parser-java-proguard-test/build.gradle.kts
+++ b/cas-parser-java-proguard-test/build.gradle.kts
@@ -37,8 +37,6 @@ val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) {
outjars(proguardJarPath)
printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt")
- dontwarn()
-
val javaHome = System.getProperty("java.home")
if (System.getProperty("java.version").startsWith("1.")) {
// Before Java 9, the runtime classes were packaged in a single jar file.
diff --git a/cas-parser-java-proguard-test/test.pro b/cas-parser-java-proguard-test/test.pro
index 7cc2e8a..fcbe936 100644
--- a/cas-parser-java-proguard-test/test.pro
+++ b/cas-parser-java-proguard-test/test.pro
@@ -5,4 +5,5 @@
-keep class org.junit.** { *; }
# Many warnings don't apply for our testing purposes.
+-dontnote
-dontwarn
\ No newline at end of file
diff --git a/scripts/format b/scripts/format
index 7c0be4d..65db176 100755
--- a/scripts/format
+++ b/scripts/format
@@ -4,5 +4,18 @@ set -e
cd "$(dirname "$0")/.."
-echo "==> Running formatters"
-./gradlew format
+if command -v ktfmt &> /dev/null; then
+ echo "==> Running ktfmt"
+ ./scripts/kotlin-format
+else
+ echo "==> Running gradlew formatKotlin"
+ ./gradlew formatKotlin
+fi
+
+if command -v palantir-java-format &> /dev/null; then
+ echo "==> Running palantir-java-format"
+ ./scripts/java-format
+else
+ echo "==> Running gradlew formatJava"
+ ./gradlew formatJava
+fi
diff --git a/scripts/java-format b/scripts/java-format
new file mode 100755
index 0000000..ad5febc
--- /dev/null
+++ b/scripts/java-format
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -e
+
+cd "$(dirname "$0")/.."
+
+find . -name "*.java" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r palantir-java-format --palantir --replace "$@"
diff --git a/scripts/kotlin-format b/scripts/kotlin-format
new file mode 100755
index 0000000..3b8be9e
--- /dev/null
+++ b/scripts/kotlin-format
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -e
+
+cd "$(dirname "$0")/.."
+
+find . -name "*.kt" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r ktfmt --kotlinlang-style "$@"
diff --git a/scripts/lint b/scripts/lint
index aea8af7..dbc8f77 100755
--- a/scripts/lint
+++ b/scripts/lint
@@ -5,4 +5,19 @@ set -e
cd "$(dirname "$0")/.."
echo "==> Running lints"
-./gradlew lint
+
+if command -v ktfmt &> /dev/null; then
+ echo "==> Checking ktfmt"
+ ./scripts/kotlin-format --dry-run --set-exit-if-changed
+else
+ echo "==> Running gradlew lintKotlin"
+ ./gradlew lintKotlin
+fi
+
+if command -v palantir-java-format &> /dev/null; then
+ echo "==> Checking palantir-java-format"
+ ./scripts/java-format --dry-run --set-exit-if-changed
+else
+ echo "==> Running gradlew lintJava"
+ ./gradlew lintJava
+fi