Java SDK
The Java SDK is the easiest way to query the Spice Cloud Platform from Java.
It uses Apache Arrow Flight to efficiently stream data to the client and Apache Arrow Records as data frames.
Supported Java Versions
The library targets Java 11 and above, and is tested against the following implementations:
Microsoft OpenJDK 11, 17, 21
Eclipse Temurin 21, 23, 24
Oracle JDK 17, 21, 23, 24, 25
Installation
<dependency>
<groupId>ai.spice</groupId>
<artifactId>spiceai</artifactId>
<version>0.7.0</version>
<scope>compile</scope>
</dependency>implementation 'ai.spice:spiceai:0.7.0'Usage
1. Import the package.
2. Create a SpiceClient by providing your API key. Get your free API key at spice.ai.
SpiceClient implements AutoCloseable, so use it in a try-with-resources block.
The builder also accepts withFlightAddress(URI), withHttpAddress(URI), withUserAgent(String), withMaxRetries(int), and withArrowMemoryLimitMB(long). The API key must be in appId|key form.
For mutual TLS, connection pooling, and query deadlines, see Mutual TLS and Performance tuning.
3. Execute a query and get back a FlightStream.
4. Iterate through the FlightStream to access the records.
Check full example to learn more.
Parameterized queries
queryWithParams(String sql, Object... params) binds positional $1, $2 placeholders and returns an ArrowReader, which the caller closes.
Parameterized queries run on Apache Arrow Flight SQL prepared statements over the same connections as query(), so they inherit the client's TLS, retry, and keep-alive settings.
Prepared statements are cached and reused, which removes the prepare round trips from every repeated query. The cache holds 64 statements by default; withPreparedStatementCacheSize(0) disables caching:
Failures surface as a FlightRuntimeException wrapped in an ExecutionException.
Usage with local Spice.ai OSS runtime
Follow the quickstart guide to install and run spice locally. The builder defaults to the local runtime:
Or using custom flight address:
Always include an explicit port. An http:// or https:// address is rewritten to a grpc+tcp:// or grpc+tls:// address using the URI's port, so an address without one resolves to an invalid port.
Check Spice OSS documentation or Java SDK Sample to learn more
Default endpoints
Spice.ai Cloud
https://flight.spiceai.io:443
https://data.spiceai.io
Local runtime
http://localhost:50051
http://localhost:8090
These can also be set with the SPICE_FLIGHT_URL and SPICE_HTTP_URL environment variables.
Mutual TLS
Connect to a Spice deployment that requires mutual TLS, or one presenting a certificate signed by a private certificate authority. All three options take a path to a PEM file:
withTlsClientCertFile
Client certificate presented to the server
withTlsClientKeyFile
Private key for the client certificate
withTlsRootCertFile
Certificate authority used to verify the server
The settings apply to Flight queries, parameterized queries, and HTTP operations. withTlsRootCertFile can be used on its own to trust a private CA without presenting a client certificate.
Health and runtime status
Three methods report runtime state. None throws when the runtime is unreachable, so they are safe to poll from a health probe.
isHealthy() suits a liveness check, and isReady() a readiness check — a runtime can respond before its datasets finish loading.
runtimeStatus() returns per-connection detail and throws ExecutionException on failure. Each ConnectionDetails exposes getName(), getEndpoint(), getStatus(), getRawStatus(), and isReady(). getStatus() returns a ComponentStatus: INITIALIZING, READY, DISABLED, ERROR, REFRESHING, SHUTTING_DOWN, NOT_LOADED, or UNKNOWN.
UNKNOWN means the runtime reported a status this version of the SDK does not recognize. Use getRawStatus() to read the value the runtime sent.
Performance tuning
withChannelCount(int)
1
Size of the round-robin gRPC connection pool, for highly concurrent workloads
withQueryTimeout(Duration)
none
Deadline for query planning, prepare, and bind calls; must be positive
withPreparedStatementCacheSize(int)
64
Prepared statements retained for reuse; 0 disables caching
withQueryTimeout bounds the planning and binding calls, not the streaming of results — a long-running result stream is not cut short by it.
Connection pooling with HikariCP
Spice can also be reached over JDBC using the Apache Arrow Flight SQL JDBC driver, which allows pooling connections with HikariCP. See the spice-java README for a worked example.
Refreshing a dataset
refreshDataset(String dataset) triggers a refresh of an accelerated dataset, optionally taking a RefreshOptions.
Connection retry
The SpiceClient implements connection retry mechanism (3 attempts by default). The number of attempts can be configured with withMaxRetries:
Retries are performed for connection and system internal errors. It is the SDK user's responsibility to properly handle other errors, for example RESOURCE_EXHAUSTED (HTTP 429).
Attempts use exponential backoff with random jitter, capped at 10 seconds per wait. The jitter keeps a fleet of clients from retrying in lockstep, and the backoff lets the default three attempts span a load-balancer failover or a runtime restart.
Because retries now wait between attempts, a query against an unreachable runtime takes longer to report failure. Use withMaxRetries(0) where a fast failure matters more than surviving a restart.
Re-authentication
An expired handshake token is detected and renewed automatically: the client re-handshakes once and retries the request, so long-lived SpiceClient instances keep working without calling reset().
reset() retires existing connections gracefully — in-flight queries and open result streams run to completion while new queries use fresh connections.
Contributing
Contribute to or file an issue with the spice-java library at: https://github.com/spiceai/spice-java
Last updated
Was this helpful?