Skip to content
  •  
  •  
  •  
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.39.0"
".": "0.40.0"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
configured_endpoints: 103
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-c8fc7d0bf70bf7ed91a141f346a02929e4d25a6fac7b59f58b68136ed6ff024f.yml
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-48084a007f009b4358484f09a3a7b74a990c402669f9d15adfbb60e4f835f951.yml
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Changelog

## 0.40.0 (2025-03-05)

Full Changelog: [v0.39.0...v0.40.0](https://github.com/orbcorp/orb-java/compare/v0.39.0...v0.40.0)

### ⚠ BREAKING CHANGES

* **client:** refactor multipart formdata impl ([#296](https://github.com/orbcorp/orb-java/issues/296))

### Features

* **api:** api update ([#300](https://github.com/orbcorp/orb-java/issues/300)) ([d5cb74a](https://github.com/orbcorp/orb-java/commit/d5cb74a47458809ba335447204b1b21166df0ede))
* **client:** allow configuring timeouts granularly ([#294](https://github.com/orbcorp/orb-java/issues/294)) ([fd71049](https://github.com/orbcorp/orb-java/commit/fd7104918a50f62d44769d167cd3d0c665710c5e))
* **client:** support raw response access ([#295](https://github.com/orbcorp/orb-java/issues/295)) ([70b0eb8](https://github.com/orbcorp/orb-java/commit/70b0eb8d409fdf3c4c1369d089c9c0f52f674268))


### Chores

* **client:** expose `Optional`, not nullable, from `ClientOptions` ([#299](https://github.com/orbcorp/orb-java/issues/299)) ([20f1914](https://github.com/orbcorp/orb-java/commit/20f191444e7d58a9ed38174f7a7f5ce027e39101))
* **client:** refactor multipart formdata impl ([#296](https://github.com/orbcorp/orb-java/issues/296)) ([22e538b](https://github.com/orbcorp/orb-java/commit/22e538b1422b5bef07a22d0d84bf4a86dd77cea1))
* **internal:** refactor `ErrorHandlingTest` ([#292](https://github.com/orbcorp/orb-java/issues/292)) ([d1ec6ff](https://github.com/orbcorp/orb-java/commit/d1ec6ff7570f4751c55862bd687009ff1f9e4b74))


### Documentation

* add raw response readme documentation ([#297](https://github.com/orbcorp/orb-java/issues/297)) ([648e2e6](https://github.com/orbcorp/orb-java/commit/648e2e6fe04d533a22fdbd730d84a39705f85561))
* note required fields in `builder` javadoc ([#298](https://github.com/orbcorp/orb-java/issues/298)) ([1af73ac](https://github.com/orbcorp/orb-java/commit/1af73ac23511ae32f4c4c051c45e95384cbb7c25))

## 0.39.0 (2025-03-01)

Full Changelog: [v0.38.0...v0.39.0](https://github.com/orbcorp/orb-java/compare/v0.38.0...v0.39.0)
Expand Down
70 changes: 50 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

[![Maven Central](https://img.shields.io/maven-central/v/com.withorb.api/orb-java)](https://central.sonatype.com/artifact/com.withorb.api/orb-java/0.39.0)
[![Maven Central](https://img.shields.io/maven-central/v/com.withorb.api/orb-java)](https://central.sonatype.com/artifact/com.withorb.api/orb-java/0.40.0)

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

Expand All @@ -19,7 +19,7 @@ The REST API documentation can be found on [docs.withorb.com](https://docs.witho
### Gradle

```kotlin
implementation("com.withorb.api:orb-java:0.39.0")
implementation("com.withorb.api:orb-java:0.40.0")
```

### Maven
Expand All @@ -28,7 +28,7 @@ implementation("com.withorb.api:orb-java:0.39.0")
<dependency>
<groupId>com.withorb.api</groupId>
<artifactId>orb-java</artifactId>
<version>0.39.0</version>
<version>0.40.0</version>
</dependency>
```

Expand All @@ -43,8 +43,8 @@ This library requires Java 8 or later.
```java
import com.withorb.api.client.OrbClient;
import com.withorb.api.client.okhttp.OrbOkHttpClient;
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;

// Configures using the `ORB_API_KEY` and `ORB_WEBHOOK_SECRET` environment variables
OrbClient client = OrbOkHttpClient.fromEnv();
Expand All @@ -53,7 +53,7 @@ CustomerCreateParams params = CustomerCreateParams.builder()
.email("example-customer@withorb.com")
.name("My Customer")
.build();
Customer customer = client.customers().create(params);
CustomerModel customerModel = client.customers().create(params);
```

## Client configuration
Expand Down Expand Up @@ -107,7 +107,7 @@ See this table for the available options:

To send a request to the Orb API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.

For example, `client.customers().create(...)` should be called with an instance of `CustomerCreateParams`, and it will return an instance of `Customer`.
For example, `client.customers().create(...)` should be called with an instance of `CustomerCreateParams`, and it will return an instance of `CustomerModel`.

## Immutability

Expand All @@ -124,8 +124,8 @@ The default client is synchronous. To switch to asynchronous execution, call the
```java
import com.withorb.api.client.OrbClient;
import com.withorb.api.client.okhttp.OrbOkHttpClient;
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;
import java.util.concurrent.CompletableFuture;

// Configures using the `ORB_API_KEY` and `ORB_WEBHOOK_SECRET` environment variables
Expand All @@ -135,16 +135,16 @@ CustomerCreateParams params = CustomerCreateParams.builder()
.email("example-customer@withorb.com")
.name("My Customer")
.build();
CompletableFuture<Customer> customer = client.async().customers().create(params);
CompletableFuture<CustomerModel> customerModel = client.async().customers().create(params);
```

Or create an asynchronous client from the beginning:

```java
import com.withorb.api.client.OrbClientAsync;
import com.withorb.api.client.okhttp.OrbOkHttpClientAsync;
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;
import java.util.concurrent.CompletableFuture;

// Configures using the `ORB_API_KEY` and `ORB_WEBHOOK_SECRET` environment variables
Expand All @@ -154,11 +154,41 @@ CustomerCreateParams params = CustomerCreateParams.builder()
.email("example-customer@withorb.com")
.name("My Customer")
.build();
CompletableFuture<Customer> customer = client.customers().create(params);
CompletableFuture<CustomerModel> customerModel = client.customers().create(params);
```

The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.

## Raw responses

The SDK defines methods that deserialize responses into instances of Java classes. However, these methods don't provide access to the response headers, status code, or the raw response body.

To access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:

```java
import com.withorb.api.core.http.Headers;
import com.withorb.api.core.http.HttpResponseFor;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;

CustomerCreateParams params = CustomerCreateParams.builder()
.email("example-customer@withorb.com")
.name("My Customer")
.build();
HttpResponseFor<CustomerModel> customerModel = client.customers().withRawResponse().create(params);

int statusCode = customerModel.statusCode();
Headers headers = customerModel.headers();
```

You can still deserialize the response into an instance of a Java class if needed:

```java
import com.withorb.api.models.CustomerModel;

CustomerModel parsedCustomerModel = customerModel.parse();
```

## Error handling

The SDK throws custom unchecked exception types:
Expand Down Expand Up @@ -193,12 +223,12 @@ To iterate through all results across all pages, you can use `autoPager`, which
### Synchronous

```java
import com.withorb.api.models.Coupon;
import com.withorb.api.models.CouponListPage;
import com.withorb.api.models.CouponModel;

// As an Iterable:
CouponListPage page = client.coupons().list(params);
for (Coupon coupon : page.autoPager()) {
for (CouponModel coupon : page.autoPager()) {
System.out.println(coupon);
};

Expand All @@ -221,12 +251,12 @@ asyncClient.coupons().list(params).autoPager()
If none of the above helpers meet your needs, you can also manually request pages one-by-one. A page of results has a `data()` method to fetch the list of objects, as well as top-level `response` and other methods to fetch top-level data about the page. It also has methods `hasNextPage`, `getNextPage`, and `getNextPageParams` methods to help with pagination.

```java
import com.withorb.api.models.Coupon;
import com.withorb.api.models.CouponListPage;
import com.withorb.api.models.CouponModel;

CouponListPage page = client.coupons().list(params);
while (page != null) {
for (Coupon coupon : page.data()) {
for (CouponModel coupon : page.data()) {
System.out.println(coupon);
}

Expand Down Expand Up @@ -295,10 +325,10 @@ Requests time out after 1 minute by default.
To set a custom timeout, configure the method call using the `timeout` method:

```java
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;

Customer customer = client.customers().create(
CustomerModel customerModel = client.customers().create(
params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()
);
```
Expand Down Expand Up @@ -432,18 +462,18 @@ By default, the SDK will not throw an exception in this case. It will throw [`Or
If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:

```java
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerModel;

Customer customer = client.customers().create(params).validate();
CustomerModel customerModel = client.customers().create(params).validate();
```

Or configure the method call to validate the response using the `responseValidation` method:

```java
import com.withorb.api.models.Customer;
import com.withorb.api.models.CustomerCreateParams;
import com.withorb.api.models.CustomerModel;

Customer customer = client.customers().create(
CustomerModel customerModel = client.customers().create(
params, RequestOptions.builder().responseValidation(true).build()
);
```
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
allprojects {
group = "com.withorb.api"
version = "0.39.0" // x-release-please-version
version = "0.40.0" // x-release-please-version
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.withorb.api.client.okhttp

import com.withorb.api.core.RequestOptions
import com.withorb.api.core.Timeout
import com.withorb.api.core.checkRequired
import com.withorb.api.core.http.Headers
import com.withorb.api.core.http.HttpClient
Expand Down Expand Up @@ -88,13 +89,12 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
)
}

val timeout = requestOptions.timeout
if (timeout != null) {
requestOptions.timeout?.let {
clientBuilder
.connectTimeout(timeout)
.readTimeout(timeout)
.writeTimeout(timeout)
.callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
.connectTimeout(it.connect())
.readTimeout(it.read())
.writeTimeout(it.write())
.callTimeout(it.request())
}

val client = clientBuilder.build()
Expand Down Expand Up @@ -195,23 +195,24 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
class Builder internal constructor() {

private var baseUrl: HttpUrl? = null
// The default timeout is 1 minute.
private var timeout: Duration = Duration.ofSeconds(60)
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null

fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl.toHttpUrl() }

fun timeout(timeout: Duration) = apply { this.timeout = timeout }
fun timeout(timeout: Timeout) = apply { this.timeout = timeout }

fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())

fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }

fun build(): OkHttpClient =
OkHttpClient(
okhttp3.OkHttpClient.Builder()
.connectTimeout(timeout)
.readTimeout(timeout)
.writeTimeout(timeout)
.callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
.connectTimeout(timeout.connect())
.readTimeout(timeout.read())
.writeTimeout(timeout.write())
.callTimeout(timeout.request())
.proxy(proxy)
.build(),
checkRequired("baseUrl", baseUrl),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import com.withorb.api.client.OrbClient
import com.withorb.api.client.OrbClientImpl
import com.withorb.api.core.ClientOptions
import com.withorb.api.core.Timeout
import com.withorb.api.core.http.Headers
import com.withorb.api.core.http.QueryParams
import java.net.Proxy
Expand All @@ -17,6 +18,7 @@ class OrbOkHttpClient private constructor() {

companion object {

/** Returns a mutable builder for constructing an instance of [OrbOkHttpClient]. */
@JvmStatic fun builder() = Builder()

@JvmStatic fun fromEnv(): OrbClient = builder().fromEnv().build()
Expand All @@ -27,8 +29,7 @@ class OrbOkHttpClient private constructor() {

private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var baseUrl: String = ClientOptions.PRODUCTION_URL
// The default timeout for the client is 1 minute.
private var timeout: Duration = Duration.ofSeconds(60)
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null

fun baseUrl(baseUrl: String) = apply {
Expand Down Expand Up @@ -120,7 +121,19 @@ class OrbOkHttpClient private constructor() {
clientOptions.removeAllQueryParams(keys)
}

fun timeout(timeout: Duration) = apply { this.timeout = timeout }
fun timeout(timeout: Timeout) = apply {
clientOptions.timeout(timeout)
this.timeout = timeout
}

/**
* Sets the maximum time allowed for a complete HTTP call, not including retries.
*
* See [Timeout.request] for more details.
*
* For fine-grained control, pass a [Timeout] object.
*/
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())

fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import com.withorb.api.client.OrbClientAsync
import com.withorb.api.client.OrbClientAsyncImpl
import com.withorb.api.core.ClientOptions
import com.withorb.api.core.Timeout
import com.withorb.api.core.http.Headers
import com.withorb.api.core.http.QueryParams
import java.net.Proxy
Expand All @@ -17,6 +18,7 @@ class OrbOkHttpClientAsync private constructor() {

companion object {

/** Returns a mutable builder for constructing an instance of [OrbOkHttpClientAsync]. */
@JvmStatic fun builder() = Builder()

@JvmStatic fun fromEnv(): OrbClientAsync = builder().fromEnv().build()
Expand All @@ -27,8 +29,7 @@ class OrbOkHttpClientAsync private constructor() {

private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var baseUrl: String = ClientOptions.PRODUCTION_URL
// The default timeout for the client is 1 minute.
private var timeout: Duration = Duration.ofSeconds(60)
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null

fun baseUrl(baseUrl: String) = apply {
Expand Down Expand Up @@ -120,7 +121,19 @@ class OrbOkHttpClientAsync private constructor() {
clientOptions.removeAllQueryParams(keys)
}

fun timeout(timeout: Duration) = apply { this.timeout = timeout }
fun timeout(timeout: Timeout) = apply {
clientOptions.timeout(timeout)
this.timeout = timeout
}

/**
* Sets the maximum time allowed for a complete HTTP call, not including retries.
*
* See [Timeout.request] for more details.
*
* For fine-grained control, pass a [Timeout] object.
*/
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())

fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

Expand Down
Loading
Loading