Skip to main content
This section contains SDK-specific guidance beyond the shared API reference. Find details on async APIs, executors, and other language-specific behaviors for Java, Kotlin, and more.

Java

Java SDK provides additional features to control how requests are executed. This guide covers how to set request timeouts, configure retries for failed requests, and make asynchronous calls.

Setting request timeouts for Oso Cloud

You may configure your client to abort requests to Oso Cloud that exceed given timeouts. When a timeout is exceeded, the SDK will throw a com.osohq.oso_cloud.OsoTimeoutException.

Setting a default timeout for all requests

Use withDefaultTimeoutMilliseconds to set a timeout that applies to all requests.
import com.osohq.oso_cloud.Oso;
import com.osohq.oso_cloud.OsoClientOptions;

OsoClientOptions options = new OsoClientOptions.Builder()
    .withDefaultTimeoutMilliseconds(2000)
    .build();
Oso oso = new Oso(YOUR_API_KEY, null, options);

Setting separate timeouts for read and write requests

  • Use withReadTimeoutMilliseconds to set a timeout that applies only to requests that read data from Oso Cloud; such as authorize and get.
  • Use withWriteTimeoutMilliseconds to set a timeout that applies only to requests that write data to Oso Cloud; such as insert and delete.
If you use these together with withDefaultTimeoutMilliseconds, that default timeout will NOT be applied to requests for which a more specific timeout was set.
import com.osohq.oso_cloud.Oso;
import com.osohq.oso_cloud.OsoClientOptions;

OsoClientOptions options = new OsoClientOptions.Builder()
    .withReadTimeoutMilliseconds(500)
    .withWriteTimeoutMilliseconds(2000)
    .build();
Oso oso = new Oso(YOUR_API_KEY, null, options);

Retrying failed requests

The Oso Cloud client automatically retries requests that failed for any of the following reasons:
  • HTTP 429 (Too Many Requests)
  • HTTP 5xx (Server Errors)
  • Connection errors
  • Timeouts
The client will make a total of up to 3 attempts, with jittered delays of 0-20ms for the first retry and 0-40ms for the second retry.

Making non-blocking CompletableFuture requests with Oso.Async

By default, the Oso Cloud client is blocking: calling a function will block the execution of the current thread until the function returns. In versions 1.4 and above, you can use the Oso.Async API to make non-blocking requests that run on an Executor. Oso.Async supports all the same functions as Oso, but each function returns a CompletableFuture, which you can get() or cancel() as necessary. Cancelling the futures returned by these functions will abort any in-progress HTTP requests. You can obtain an Oso.Async instance by calling withAsyncExecutor(Executor) on an Oso instance:
import com.osohq.oso_cloud.Oso;
import com.osohq.oso_cloud.Oso.Async;
import com.osohq.oso_cloud.Value;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

Executor executor = Executors.newSingleThreadExecutor(); // or any other Executor
Oso.Async osoAsync = (new Oso(YOUR_API_KEY)).withAsyncExecutor(executor);

// Then:
Value user = new Value("User", "alice");
Value anvilsRepository = new Value("Repository", "anvils");
String action = "read";

CompletableFuture<Boolean> allowedFuture = osoAsync.authorize(user, action, anvilsRepository);
boolean allowed = allowedFuture.get();
Or in Kotlin:
import com.osohq.oso_cloud.Oso
import com.osohq.oso_cloud.Value
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await

// Run Oso requests in the thread pool dedicated to blocking I/O
val osoAsync = Oso(YOUR_API_KEY).withAsyncExecutor(Dispatchers.IO.asExecutor())

// Then:
val allowed = osoAsync.authorize(Value("User", "alice"), "read", Value("Repository", "anvils")).await()
In Kotlin, awaiting a CompletableFuture returned by Oso.Async will cooperatively propagate cancellations. When a parent coroutine is cancelled, any in-progress HTTP requests in the awaited future will be aborted. Note that while calls to Oso.Async will not block the current thread, the underlying Runnable HTTP requests submitted to the Executor are fundamentally blocking and can block threads on your Executor when they run. You may wish to use an Executor with its own thread pool for Oso.Async, to avoid thread starvation in other parts of your application.