- Built on Rust SDK 2.3.1: the JNI layer (
rust/jni/) now depends ondatabricks-zerobus-ingest-sdk = "2.3.1"(was 2.0.1). - Added native library support for Linux musl (Alpine) on x86_64 and aarch64. The libc flavor is detected automatically at runtime; override with
-Dzerobus.libc=musl|glibc. - Added
ZerobusSdk.streamBuilder(), a fluent builder for creating streams that mirrors the Rust SDK'sstream_builder(). It supports JSON, Protocol Buffer, and Arrow Flight streams through a single chainable API and is now the recommended way to create streams. SeeStreamBuilder. ZerobusSdknow has a three-argument constructor accepting an optionalapplicationNameparameter. When set, it is appended to the HTTPuser-agentheader on gRPC requests to the Zerobus service (it is not sent on requests to the login service that mint the OAuth token), so callers can be identified in server-side telemetry. The wire value becomeszerobus-sdk-java/<version> <applicationName>(e.g.zerobus-sdk-java/1.3.0 my-app/1.0). The existing two-argument constructor is unchanged.
- Lowered the glibc baseline for bundled Java JNI Linux artifacts to glibc 2.26, enabling the standard Java SDK JAR to run on Amazon Linux 2 environments such as Mule Runtime 4.11.6e without requiring customers to rebuild the native library.
- Fixed the
GeneratePrototool rejectingVARIANTcolumns withUnsupported column type(andUnsupported array/map element typewhen nested).VARIANTnow maps tostring(unshredded JSON-encoded text) at the top level and insideARRAY/MAP, matching the other SDKs. - Fixed the default
recoveryRetries, which was3instead of the4used by the Rust core and every other SDK (Go, TypeScript, C++). A stream left with the default now makes 4 recovery attempts on transient failures instead of 3, matching the documented cross-SDK behavior. Callers that setrecoveryRetriesexplicitly are unaffected. (#438)
- Reworked README and Javadoc to steer users toward the high-throughput ingestion pattern: ingest with
ingestRecordOffset()in a loop without waiting, thenflush()(orwaitForOffset()on the last offset) once. Added a performance callout warning against waiting for an acknowledgment after every record, documentedAckCallbackas the non-blocking alternative, and rewrote the Quick Start example to use the offset-based API instead of the deprecatedingestRecord().join()loop.
- The Java SDK now generates its protobuf classes from the canonical
rust/sdk/zerobus_service.protoinstead of a local copy undersrc/main/proto/. This reconciles schema drift: the generated classes now include the batch-ingest messages (JsonRecordBatch,ProtoEncodedRecordBatch,IngestRecordBatchRequest) that the canonical schema already defined. Purely additive — no change to the hand-writtencom.databricks.zerobuspublic API, and batch ingestion (ingestRecordsOffset) already worked via the JNI boundary. - Added a
maven-enforcer-pluginrule that failsmvn package/install/deployif the JNI native libraries (linux-x86_64,linux-aarch64,linux-musl-x86_64,linux-musl-aarch64,windows-x86_64) aren't staged undersrc/main/resources/native/. v1.2.0 was published with an empty JAR because the release pipeline ranmvn deployon a fresh checkout without staging natives; this guard makes that failure mode impossible going forward. Local Java-only builds that don't need packaged natives can skip this specific rule with-Dzerobus.skipNativeLibCheck=true.
- Deprecated
ZerobusSdk.createJsonStream,ZerobusSdk.createProtoStream, andZerobusSdk.createArrowStream(all overloads) in favor ofZerobusSdk.streamBuilder(). The deprecated methods continue to work unchanged and are scheduled for removal in the next major release.
- Added
StreamBuilderand its typed sub-builders (StreamBuilder.JsonStreamBuilder,StreamBuilder.ProtoStreamBuilder,StreamBuilder.ArrowStreamBuilder), returned byZerobusSdk.streamBuilder(). - Added a three-argument
ZerobusSdk(String serverEndpoint, String unityCatalogEndpoint, String applicationName)constructor. The existing two-argument constructor delegates to it with anullapplication name.
- Built on Rust SDK 2.0.1: The JNI layer (
rust/jni/) now depends ondatabricks-zerobus-ingest-sdk = "2.0.1"(was 2.0.0). The Java-facing API surface (ZerobusSdk,ZerobusProtoStream,ZerobusJsonStream,ZerobusArrowStream,StreamConfigurationOptions,ArrowStreamConfigurationOptions) is unchanged. - Arrow Flight promoted to Beta:
ZerobusArrowStream/ArrowStreamConfigurationOptionsand the surrounding documentation (README, examples) are no longer labelled experimental. The API is stabilising but may still change before reaching GA. (Mirrors the Rust SDK 2.0.1 promotion.) ArrowStreamConfigurationOptions: AddedstreamPausedMaxWaitTimeMsfor the maximum time (milliseconds) to wait in the paused state during graceful close (-1= full server duration,0= immediate recovery).- Java SDK identifier on the wire: The SDK now reports itself as
zerobus-sdk-java/<version>on the HTTPuser-agentheader (previously it inherited the Rust SDK identifierzerobus-sdk-rs/<rust-version>). Server-side telemetry can now distinguish Java clients from Rust clients.
-
StreamConfigurationOptions.maxInflightRecordsdefault raised from50_000to1_000_000to match the Rust SDK 2.0.1 default. The Java wrapper previously hard-coded 50k while the Rust SDK quietly raised its default to 1M, so Java clients ran with a 20× lower in-flight ceiling than Rust clients. Callers who relied on the old cap can pin it back explicitly:StreamConfigurationOptions.builder() .setMaxInflightRecords(50_000) .build();
- Updated
ArrowIngestionExample.javato demonstrate all three IPC compression codecs end-to-end. Opens three streams in sequence (NONE,LZ4_FRAME,ZSTD), ingests 10 batches per stream, thenwaitForOffset+flush+close. - Updated
README.md,examples/README.md,examples/arrow/README.md, and Javadoc onZerobusArrowStream/ArrowStreamConfigurationOptions/ZerobusSdk.createArrowStreamto reflect the Beta promotion. - Documented the JDK 9+
--add-opens=java.base/java.nio=...JVM flags required byarrow-memory-netty17.x when usingZerobusArrowStream, in both the main README and the Arrow examples README.
maven-surefire-pluginnow passes the required--add-opensflags so Arrow integration tests run cleanly on JDK 9+ without per-developer setup.- Bumped
zerobus-jnicrate version from1.1.1to1.2.0(used by the Java SDK identifier embedded at compile time viaCARGO_PKG_VERSION).
- Fixed
isClosed()returningfalseafter the stream internally closed due to non-retryable errors (e.g. server rejection, auth failure). The JNI layer now checks both the wrapper state and the Rust stream's internal closed flag. Affects both proto/JSON streams and Arrow streams.
- License: Migrated from the Databricks License to the Apache License 2.0
- Arrow Flight Support (Experimental): Added support for ingesting Apache Arrow
VectorSchemaRootbatches via Arrow Flight protocol- Note: Arrow Flight is not yet supported by default from the Zerobus server side.
- New
ZerobusArrowStreamclass withingestBatch(),waitForOffset(),flush(),close(),getUnackedBatches()methods - New
ArrowStreamConfigurationOptionsfor configuring Arrow streams (max inflight batches, recovery, timeouts, IPC compression) - Configurable IPC compression via
ArrowStreamConfigurationOptions.setIpcCompression()(supportsLZ4_FRAMEandZSTD) - New
createArrowStream()andrecreateArrowStream()methods onZerobusSdk - Accepts
VectorSchemaRootdirectly viaingestBatch()(IPC serialization handled internally) - Arrow is opt-in: add
arrow-vectorandarrow-memory-nettyas dependencies (provided scope,>= 15.0.0)
- Classloader Isolation Compatibility: Fixed
NoClassDefFoundErrorwhen using the SDK inside Spring Boot. JNI class references are now cached asGlobalRefs duringJNI_OnLoad, so native daemon threads no longer rely onFindClassthrough the system classloader. - Fixed proto generation tool to skip reserved field numbers 19000-19999 for tables with more than 19000 columns
- Added
arrow-vector17.0.0 as provided dependency for Arrow Flight support - Added
arrow-memory-netty17.0.0 as test dependency for integration tests - Uses existing JNI Arrow Flight bindings from Rust SDK (
nativeCreateArrowStream,nativeIngestBatch, etc.)
- Added
createArrowStream(String tableName, Schema schema, String clientId, String clientSecret)toZerobusSdk - Added
createArrowStream(String tableName, Schema schema, String clientId, String clientSecret, ArrowStreamConfigurationOptions options)toZerobusSdk - Added
recreateArrowStream(ZerobusArrowStream closedStream)toZerobusSdk - Added
ZerobusArrowStreamclass with methods:ingestBatch(),waitForOffset(),flush(),close(),getUnackedBatches(),isClosed(),getTableName(),getOptions() - Added
ArrowStreamConfigurationOptionsclass with fields:maxInflightBatches,recovery,recoveryTimeoutMs,recoveryBackoffMs,recoveryRetries,serverLackOfAckTimeoutMs,flushTimeoutMs,connectionTimeoutMs,ipcCompression - Added
IPCCompressionTypeenum with values:NONE,LZ4_FRAME,ZSTD - Added optional dependency:
org.apache.arrow:arrow-vector >= 15.0.0(provided scope)
- Fixed TLS certificate validation failure when behind corporate VPN/proxy with MITM certificates (e.g., GlobalProtect). The underlying Rust native library now loads CA certificates from the OS native trust store (respecting
SSL_CERT_FILEand system certificate stores) while keeping bundled Mozilla roots as a fallback.
GA release of the Databricks Zerobus Ingest SDK for Java.
- Added HTTP proxy support via standard environment variables (
grpc_proxy,https_proxy,http_proxy), following gRPC core conventions. Proxied connections use HTTP CONNECT tunneling with end-to-end TLS. Supportsno_grpc_proxy/no_proxyfor bypass rules.
- Updated native Rust backend to v0.6.0
- Schemeless server endpoints now automatically get
https://prepended - All documentation and examples updated to explicitly use
https://prefixed endpoints - Added Linux aarch64 (ARM64) native library support
- The SDK now uses JNI (Java Native Interface) to call the Zerobus Rust SDK instead of pure Java gRPC calls
- Native library is automatically loaded from the classpath or system library path
- Token management and background processing handled by native code
ZerobusProtoStream - Protocol Buffer ingestion with method-level generics:
ingestRecordOffset(T record)- Auto-encoded: SDK encodes Message to bytesingestRecordOffset(byte[] bytes)- Pre-encoded: User provides encoded bytesingestRecordsOffset(List<T> records)- Batch auto-encoded ingestioningestRecordsOffset(List<byte[]> bytes)- Batch pre-encoded ingestiongetUnackedRecords()- ReturnsList<byte[]>of unacked recordsgetUnackedRecords(Parser<T>)- Returns parsedList<T>of unacked recordsgetUnackedBatches()- ReturnsList<EncodedBatch>preserving batch grouping
ZerobusJsonStream - JSON ingestion without Protocol Buffer dependency:
ingestRecordOffset(String json)- Pre-serialized: User provides JSON stringingestRecordOffset(T obj, JsonSerializer<T>)- Auto-serialized: SDK serializes objectingestRecordsOffset(List<String> jsons)- Batch pre-serialized ingestioningestRecordsOffset(List<T> objs, JsonSerializer<T>)- Batch auto-serialized ingestiongetUnackedRecords()- ReturnsList<String>of unacked JSON recordsgetUnackedRecords(JsonDeserializer<T>)- Returns parsedList<T>of unacked recordsgetUnackedBatches()- ReturnsList<EncodedBatch>preserving batch grouping
ZerobusSdk.createProtoStream(tableName, descriptorProto, clientId, clientSecret)- Create proto streamZerobusSdk.createProtoStream(tableName, descriptorProto, clientId, clientSecret, options)- With optionsZerobusSdk.createJsonStream(tableName, clientId, clientSecret)- Create JSON streamZerobusSdk.createJsonStream(tableName, clientId, clientSecret, options)- With optionsZerobusSdk.recreateStream(ZerobusProtoStream)- Recreate proto stream with unacked record re-ingestionZerobusSdk.recreateStream(ZerobusJsonStream)- Recreate JSON stream with unacked record re-ingestionZerobusSdk.recreateStream(ZerobusStream)- Recreate legacy stream (deprecated)
BaseZerobusStream- Abstract base class with native JNI methodsJsonSerializer<T>- Functional interface for object-to-JSON serializationJsonDeserializer<T>- Functional interface for JSON-to-object deserializationEncodedBatch- Represents a batch of encoded records for recoveryAckCallback- Callback interface withonAck(long)andonError(long, String)
ZerobusStream - Use ZerobusProtoStream instead:
ingestRecord(T record)- ReturnsCompletableFuture<Void>, useingestRecordOffset()insteadgetStreamId()- No longer exposed by native backend, returns empty stringgetState()- ReturnsOPENEDorCLOSEDonlygetUnackedRecords()- Breaking: Returns empty iterator (records stored in native, type erasure prevents deserialization). UseZerobusProtoStream.getUnackedRecords(Parser<T>)for typed access, or userecreateStream()which handles re-ingestion automatically using cached raw bytes.
StreamConfigurationOptions:
setAckCallback(Consumer<IngestRecordResponse>)- No longer invoked by native backend. UsesetAckCallback(AckCallback)instead
TokenFactory- Token management now handled by native Rust SDKBackgroundTask- Background processing now handled by native Rust SDKZerobusSdkStubUtils- gRPC stub utilities no longer needed with native backend
- Linux x86_64: Supported
- Windows x86_64: Supported
- macOS x86_64: Supported
- macOS aarch64 (Apple Silicon): Supported
Initial release of the Databricks Zerobus Ingest SDK for Java.
- Added
ZerobusSdkclass for creating ingestion streams - Added
ZerobusStreamclass for managing stateful gRPC streams - Added
RecordAcknowledgmentfor blocking until record acknowledgment - Added
TablePropertiesfor configuring table schema and name - Added
StreamConfigurationOptionsfor stream behavior configuration - Added
ZerobusExceptionandNonRetriableExceptionfor error handling - Added
StreamStateenum for tracking stream lifecycle - Added utility methods in
ZerobusSdkStubUtilsfor gRPC stub management - Support for Java 8 and higher