Skip to content

Releases: spiceai/spice-java

Spice Java SDK v0.6.0

26 Mar 13:54
1380a8f

Choose a tag to compare

Highlights

This release focuses on transport resilience and dependency upgrades. A new reset() method provides manual recovery from stuck transport connections, gRPC keep-alive detects dead connections early, and DNS re-resolution enables automatic recovery from load-balancer IP rotation.

What's New

🔄 Connection Reset

The SDK now supports a reset() method for manual transport recovery. When the underlying gRPC connection becomes permanently stuck (e.g. TLS handshake to a wrong backend, persistent UNAVAILABLE after retries), reset() discards the bad connection and immediately establishes a fresh one:

SpiceClient client = SpiceClient.builder()
    .withApiKey(API_KEY)
    .withSpiceCloud()
    .build();

try {
    try (FlightStream stream = client.query(sql)) {
        // process results...
    }
} catch (ExecutionException e) {
    if (isTransportFailure(e.getCause())) {
        client.reset();   // discard bad transport, reconnect immediately
        try (FlightStream stream = client.query(sql)) {
            // process results with fresh connection...
        }
    } else {
        throw e;
    }
}

Key behaviors:

  • Thread-safe (synchronized) — concurrent reset calls are serialized
  • Idempotent — safe to call multiple times
  • Throws IllegalStateException if client is already closed
  • Resets both Flight and ADBC connections

🏥 gRPC Keep-Alive

HTTP/2 keep-alive pings are now enabled by default to detect dead connections quickly:

  • Keep-alive interval: 30 seconds
  • Keep-alive timeout: 10 seconds
  • Keep-alive without calls: enabled (pings even when idle)

🌐 DNS Re-Resolution

The SDK now uses dns:/// target resolution for gRPC channels, enabling periodic hostname re-resolution. This allows clients to automatically recover from load-balancer IP rotation (e.g. AWS NLB) without manual intervention.

DNS cache TTL: For more aggressive DNS refresh (recommended for cloud-deployed clients), set the JVM property:

-Dnetworkaddress.cache.ttl=30

🛡️ Lazy Transport Recovery

A new ensureFlightClient() safety net automatically rebuilds the Flight client if the internal reference is null at query time, adding an extra layer of resilience.

⬆️ Updated Dependencies

Dependency Previous Current
Apache Arrow Flight SQL 18.3.0 19.0.0
Apache Arrow ADBC Driver Flight SQL 0.21.0 0.22.0
Apache Arrow ADBC Core 0.21.0 0.22.0
Gson 2.13.1 2.13.2
Netty 4.1.130.Final 4.2.12.Final

🔧 Updated Build Plugins

Plugin Previous Current
maven-surefire-plugin 3.5.4 3.5.5
maven-source-plugin 3.3.1 3.4.0
central-publishing-maven-plugin 0.9.0 0.10.0
spotbugs-maven-plugin 4.9.3.0 4.9.8.2
dependency-check-maven 12.1.1 12.2.0
jacoco-maven-plugin 0.8.13 0.8.14
maven-enforcer-plugin 3.5.0 3.6.2

Spice Java SDK v0.5.0

06 Jan 03:03
d4620cf

Choose a tag to compare

Highlights

This release introduces Parameterized Queries using ADBC (Arrow Database Connectivity), providing a safer and more efficient way to execute queries with dynamic parameters.

What's New

🎯 Parameterized Queries

The SDK now supports parameterized queries through the new queryWithParams() method. This is the recommended approach for queries with user input to prevent SQL injection attacks.

// With automatic type inference
ArrowReader reader = client.queryWithParams(
    "SELECT * FROM taxi_trips WHERE trip_distance > $1 LIMIT 10",
    5.0);  // Double is inferred as Float64

// With multiple parameters
ArrowReader reader = client.queryWithParams(
    "SELECT * FROM taxi_trips WHERE trip_distance > $1 AND fare_amount > $2 LIMIT 10",
    5.0, 20.0);

🔧 Explicit Type Control with Param Class

For precise control over Arrow types, use the new Param class with typed factory methods:

import ai.spice.Param;

ArrowReader reader = client.queryWithParams(
    "SELECT * FROM orders WHERE order_id = $1 AND amount >= $2",
    Param.int64(12345),
    Param.decimal128(new BigDecimal("99.99"), 10, 2));

Available typed parameter constructors:

  • Integers: int8, int16, int32, int64, uint8, uint16, uint32, uint64
  • Floating point: float16, float32, float64
  • Strings: string, largeString
  • Binary: binary, largeBinary, fixedSizeBinary
  • Boolean: bool
  • Date/Time: date32, date64, time32, time64, timestamp, duration
  • Decimals: decimal128, decimal256
  • Null: nullValue

📦 New Dependencies

  • Added Apache Arrow ADBC FlightSQL driver (adbc-driver-flight-sql:0.21.0)
  • Added Apache Arrow ADBC Core (adbc-core:0.21.0)
  • Added Gson (gson:2.13.1)
  • Added SLF4J API (slf4j-api:2.0.17) for structured logging

⬆️ Updated Dependencies

  • Apache Arrow Flight SQL: 17.0.0 → 18.3.0
  • Netty: 4.1.108.Final → 4.1.130.Final
  • SLF4J: 2.0.16 → 2.0.17 (moved to slf4j-api, slf4j-simple now test-scoped)

🔧 Updated Build Plugins

  • maven-surefire-plugin: 3.3.0 → 3.5.4
  • maven-source-plugin: 3.3.0 → 3.3.1
  • maven-javadoc-plugin: 3.6.3 → 3.12.0
  • maven-gpg-plugin: 3.2.1 → 3.2.8
  • central-publishing-maven-plugin: 0.5.0 → 0.9.0

📝 Logging Support

The SDK now includes structured logging via SLF4J. Users can plug in their preferred logging implementation (Logback, Log4j2, etc.). Log messages are emitted at:

  • DEBUG: Client initialization, query execution, ADBC connection lifecycle
  • WARN: Recoverable errors during resource cleanup
  • ERROR: Query failures, connection errors

New Files

  • Param.java - Parameter class with typed factory methods
  • ParameterizedQueryTest.java - Test suite for parameterized queries
  • ExampleParameterizedQueries.java - Example usage of parameterized queries
  • ExampleIteratingResults.java - Comprehensive example showing how to iterate through query results

Automatic Type Inference

The following Java types are automatically inferred when passed to queryWithParams():

Java Type Arrow Type
byte Int8
short Int16
int Int32
long Int64
float Float32
double Float64
String Utf8
boolean Bool
byte[] Binary
LocalDate Date32
LocalTime Time64 (microseconds)
LocalDateTime Timestamp (microseconds, UTC)
Duration Duration (microseconds)
BigDecimal Decimal128/256
null Null

🔒 Security Benefits

Parameterized queries provide protection against SQL injection attacks:

// ❌ Vulnerable to SQL injection
String userId = getUserInput(); // Could be: "1 OR 1=1"
String sql = "SELECT * FROM users WHERE id = " + userId;
FlightStream stream = client.query(sql);

// ✅ Safe from SQL injection
ArrowReader reader = client.queryWithParams(
    "SELECT * FROM users WHERE id = $1",
    userId);

Breaking Changes

None. This release is fully backward compatible with v0.4.0.

Upgrade Guide

Simply update your dependency version from 0.4.0 to 0.5.0:

Maven:

<dependency>
  <groupId>ai.spice</groupId>
  <artifactId>spiceai</artifactId>
  <version>0.5.0</version>
</dependency>

Gradle:

implementation 'ai.spice:spiceai:0.5.0'

Contributors

Thanks to everyone who contributed to this release!

What's Changed

  • feat: Add x-spice-user-agent header by @peasee in #25
  • docs: Add endgame release process by @peasee in #28
  • feat: Add support for refresh options by @peasee in #27
  • Adding custom User-Agent to Java SDK by @eadgbear in #29
  • Prepend user-supplied user-agent by @phillipleblanc in #30
  • Fix integration tests: Use quickstart dataset for Cloud by @sgrebnov in #33
  • Add configurable Arrow memory limit - withArrowMemoryLimitMB by @kczimm in #32
  • Set version to 0.4.0 in documentation by @sgrebnov in #34
  • Update end_game.md with Maven Central steps by @sgrebnov in #35
  • feat: Add Parameterized Queries & Logging by @lukekim in #37

New Contributors

Full Changelog: v0.3.0...v0.5.0

v0.4.0

10 Nov 18:22

Choose a tag to compare

What's Changed

Memory Configuration

The SpiceClient uses an Arrow RootAllocator to manage off-heap memory. By default, it utilizes all available memory. Starting with the 0.4.0 release, you can configure a memory limit:

SpiceClient client = SpiceClient.builder()
    .withArrowMemoryLimitMB(1024) // 1GB limit
    .build();

New Contributors

Full Changelog: v0.3.0...v0.4.0

v0.3.0

12 Sep 03:26

Choose a tag to compare

What's Changed

Full Changelog: v0.2.0...v0.3.0

v0.2.0

20 Aug 14:22
e7c72e1

Choose a tag to compare

What's Changed

Full Changelog: v0.1.0...v0.2.0

Spice Java SDK v0.1.0

17 Jul 22:33
814832f

Choose a tag to compare

What's Changed

  • Java SDK core functionality and tests by @sgrebnov in #1
  • Add publishing to Maven Central by @sgrebnov in #2
  • Implement connection retry mechanism by @sgrebnov in #5
  • Implement AutoCloseable interface for SpiceClient by @sgrebnov in #7
  • Fix Maven link for SDK artifacts by @sgrebnov in #8
  • Update Readme to match the latest code version by @sgrebnov in #9
  • Update README.md - small edits and improvements by @digadeesh in #10
  • Fix Maven publishing: add required step to load signing key by @sgrebnov in #11
  • Set version to 0.1.0 by @sgrebnov in #12

New Contributors

Full Changelog: https://github.com/spiceai/spice-java/commits/v0.1.0