Java
Our API Reference has generic examples in every supported language, and we strive to make the experience of each SDK very similar. However, there are some things specific to the Java SDK that we want to call out here.
Java 11+ Required
Section titled “Java 11+ Required”The Java SDK requires Java 11 or higher and uses modern Java features including CompletableFuture for asynchronous operations.
Installation
Section titled “Installation”The SDK can be installed via Maven or Gradle:
Maven:
<dependency> <groupId>cloud.stately</groupId> <artifactId>statelydb</artifactId> <version>LATEST</version></dependency>Gradle:
dependencies { implementation 'cloud.stately:statelydb:+'}Creating Item Objects
Section titled “Creating Item Objects”The generated code uses the Builder pattern for creating item objects. Each item type has a Builder class that requires all mandatory fields in the constructor and provides optional field setters:
import schema.User;import schema.Movie;
// Create a User with all required fieldsUser user = new User.Builder( "Jane Doe", // displayName "jane.doe@example.com", // email Instant.now().getEpochSecond(), // lastLoginDate 1L // numLogins).build();
// Create a Movie with all required fieldsMovie movie = new Movie.Builder( "Drama", // genre 1994L, // year "Forrest Gump", // title 142L, // duration "PG-13" // rating).build();Asynchronous Operations
Section titled “Asynchronous Operations”All client operations return CompletableFuture<T> objects for asynchronous execution:
// Asynchronous put operationCompletableFuture<StatelyItem> putResult = client.put(user);
// Block and get the resultUser result = putResult.<User>get();
// Or handle asynchronouslyputResult.thenAccept(item -> { System.out.println("Saved user: " + item.getDisplayName());});Key Path Helper
Section titled “Key Path Helper”The generated types include a primaryKeyPath() method that returns the primary key path for an item:
User user = // ... create userString keyPath = user.primaryKeyPath(); // e.g., "/usr-12345678-1234-1234-1234-123456789012"
// For manual key path construction, convert UUIDs to stringsUUID userId = user.getId();String manualKeyPath = "/usr-" + userId.toString();Checking an Item’s Type
Section titled “Checking an Item’s Type”Many client APIs return a StatelyItem, but you want to know exactly what type it is. You can use Java’s instanceof operator and casting for this:
if (item instanceof Movie) { Movie movie = (Movie) item; // it's a movie}
// Or with pattern matching (Java 16+)switch (item) { case Movie movie -> { // it's a movie } case User user -> { // it's a user } default -> { // unknown type }}Error Handling
Section titled “Error Handling”StatelyDB-specific errors are wrapped in StatelyException which provides both gRPC and Stately error codes:
import cloud.stately.statelydb.common.StatelyException;
try { client.get("/item-nonexistent").get();} catch (Exception e) { if (e.getCause() instanceof StatelyException) { StatelyException statelyError = (StatelyException) e.getCause(); System.out.println("StatelyDB error: " + statelyError.getMessage()); System.out.println("Stately code: " + statelyError.getStatelyCode()); System.out.println("gRPC code: " + statelyError.getGrpcCode()); } else { System.out.println("Other error: " + e.getMessage()); }}Resource Management
Section titled “Resource Management”The client requires a ScheduledExecutorService for background operations (primarily auth token refresh). Always shut down the client and executor when done:
import schema.ClientBuilder;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
try { Client client = new ClientBuilder(storeId, scheduler).build(); // Use the client...} finally { client.close(); scheduler.shutdown();}Transactions
Section titled “Transactions”Transactions use a handler pattern where you provide a lambda that receives a transaction context:
import cloud.stately.statelydb.TransactionResult;
TransactionResult result = client.transaction(txn -> { // Perform multiple operations within the transaction return txn.put(item1) .thenCompose(putResult -> txn.put(item2)) .thenCompose(putResult -> txn.delete("/another-keypath"));}).get();
if (result.isCommitted()) { System.out.println("Transaction successful"); System.out.println("Items created: " + result.getPuts().size());}