Java SDK
Type-safe Java client for InferaDB.
Coming soon. The Java SDK is under active development. The API surface shown here is based on the Rust SDK and may change before release.
Typed, fluent client for InferaDB. Requires Java 17+.
Installation
Maven
<dependency>
<groupId>com.inferadb</groupId>
<artifactId>inferadb-sdk</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
implementation "com.inferadb:inferadb-sdk:0.1.0"
Authentication
Three authentication methods:
| Method | Use Case | Security |
|---|---|---|
| Client Credentials (Ed25519 JWT) | Service-to-service | High |
| Bearer Token | User sessions, OAuth | Medium |
| API Key | Testing, simple integrations | Basic |
Client Credentials (Recommended)
import com.inferadb.InferaDB;
import com.inferadb.auth.Ed25519PrivateKey;
import com.inferadb.auth.ClientCredentials;
import java.nio.file.Path;
var key = Ed25519PrivateKey.fromPemFile(Path.of("client.pem"));
var client = InferaDB.builder()
.url("https://engine.inferadb.com")
.credentials(new ClientCredentials("my-client", key, "cert-id"))
.build();
Bearer Token
var client = InferaDB.builder()
.url("https://engine.inferadb.com")
.bearerToken(System.getenv("INFERADB_TOKEN"))
.build();
API Key
var client = InferaDB.builder()
.url("https://engine.inferadb.com")
.apiKey(System.getenv("INFERADB_API_KEY"))
.build();
Permission Checks
var vault = client.organization("my-org").vault("production");
boolean allowed = vault.check("user:alice", "can_edit", "document:readme");
With ABAC Context
import java.util.Map;
boolean allowed = vault.check("user:alice", "can_view", "document:readme",
CheckOptions.builder()
.context(Map.of("ip_address", "10.0.0.1"))
.build());
Require — Throws on Deny
// Throws AccessDeniedException if permission is denied
vault.require("user:alice", "can_edit", "document:readme");
With Consistency Token
boolean allowed = vault.check("user:alice", "can_view", "document:readme",
CheckOptions.builder()
.atLeastAsFresh(revisionToken)
.build());
Batch Check
import java.util.List;
var results = vault.checkBatch(List.of(
new CheckRequest("user:alice", "can_edit", "document:readme"),
new CheckRequest("user:bob", "can_view", "document:readme")
));
if (results.allAllowed()) {
// all checks passed
}
Relationships
Write
// Returns a revision token
var token = vault.relationships().write(
new Relationship("document:readme", "editor", "user:alice"));
Batch Write
vault.relationships().writeBatch(List.of(
new Relationship("document:readme", "editor", "user:alice"),
new Relationship("document:readme", "viewer", "user:bob")
));
List
var rels = vault.relationships()
.list()
.resource("document:readme")
.collect();
Delete
vault.relationships()
.deleteWhere()
.resource("document:readme")
.relation("viewer")
.subject("user:bob")
.execute();
Lookups
// What resources can Alice view?
var resources = vault.resources()
.accessibleBy("user:alice")
.withPermission("can_view")
.resourceType("document")
.collect();
// Who can edit this document?
var subjects = vault.subjects()
.withPermission("can_edit")
.onResource("document:readme")
.collect();
Testing
MockClient (Fastest)
Stub specific check results. With verifyOnClose(true), all expectations are asserted on client.close() – use with try-with-resources.
import com.inferadb.testing.MockClient;
var client = MockClient.builder()
.onCheck("user:alice", "can_edit", "document:readme").allow()
.onCheck("user:bob", "can_edit", "document:readme").deny()
.onCheckAnySubject("can_view", "document:readme").allow()
.defaultDeny()
.verifyOnClose(true)
.build();
InMemoryClient (Full Policy Evaluation)
import com.inferadb.testing.InMemoryClient;
var client = InMemoryClient.withSchemaAndData(
"""
type document {
relation viewer
relation editor
relation can_view = viewer | editor
}
""",
List.of(
new Relationship("document:readme", "editor", "user:alice"),
new Relationship("document:readme", "viewer", "user:bob")
)
);
TestVault (Real Instance)
Auto-cleans up on close via try-with-resources.
import com.inferadb.testing.TestVault;
try (var vault = TestVault.create(org, schemaIpl)) {
boolean allowed = vault.check("user:alice", "can_edit", "document:readme");
}
Error Handling
import com.inferadb.InferaDBException;
import com.inferadb.AccessDeniedException;
try {
vault.require("user:alice", "can_edit", "document:readme");
} catch (AccessDeniedException e) {
// permission denied
} catch (InferaDBException e) {
if (e.isRetriable()) {
// retry after e.getRetryAfter()
}
logger.error("Authorization error: kind={}, requestId={}",
e.getKind(), e.getRequestId());
}
ErrorKind enum: UNAUTHORIZED, FORBIDDEN, NOT_FOUND, RATE_LIMITED, SCHEMA_VIOLATION, UNAVAILABLE, TIMEOUT, INVALID_ARGUMENT.
Framework Integrations
Spring Boot
import com.inferadb.spring.RequirePermission;
@RestController
@RequestMapping("/documents")
public class DocumentController {
@GetMapping("/{id}")
@RequirePermission(
subject = "#{authentication.name}",
permission = "can_view",
resource = "'document:' + #id"
)
public Document getDocument(@PathVariable String id) {
return documentService.findById(id);
}
}
Spring Security Integration
import com.inferadb.spring.InferaDBAuthorizationManager;
@Bean
SecurityFilterChain filterChain(HttpSecurity http,
InferaDBAuthorizationManager authz) throws Exception {
return http
.authorizeHttpRequests(requests -> requests
.requestMatchers("/api/**").access(authz)
.anyRequest().permitAll()
)
.build();
}