Send data to Deephaven from a Java client
This guide shows how to send data to Deephaven from an external Java application using the Deephaven Java client and input tables. Input tables allow a client to add, update, and delete rows in a Deephaven table.
Note
If your data source can run directly on the Deephaven server, consider using server-side input tables or DynamicTableWriter instead. Server-side ingestion is generally more efficient because it avoids network overhead.
When to use client-side input tables
Use client-side input tables when:
- Managing reference data: Upload configuration, lookup tables, or static datasets that may need updates.
- Tracking state: Maintain the latest status per entity (e.g., device status, order state, user preferences).
- Interactive editing: Allow users or external systems to add, update, or remove records.
- Forwarding external data: Relay data from message queues, APIs, or sensors running in separate JVMs.
Setup
Add the Deephaven Java client dependencies to your project. Replace <version> with the version that matches your Deephaven server (e.g., 0.36.1). For Gradle:
JVM configuration
On Java 9+, Arrow requires reflective access to java.nio.Buffer. Add this JVM option to avoid InaccessibleObjectException:
For Gradle's application plugin, configure the run task:
Or for a specific JavaExec task:
Basic pattern
The basic pattern for sending data from a Java client is:
- Create a
FlightSessionto connect to the Deephaven server. - Define an input table spec using
InMemoryKeyBackedInputTable,InMemoryAppendOnlyInputTable, orBlinkInputTable. - Execute the spec to create the input table on the server.
- Publish the input table to the query scope so it's accessible and the server maintains a reference.
- Close the handle to avoid leaking client-side resources (the server-side table persists via the scope).
- Build data rows using
ColumnHeaderandNewTable. - Add to the input table via
ScopeIdwithFlightSession.addToInputTable. For keyed tables, this inserts new rows or updates existing ones.
Repeat steps 6-7 as needed.
Complete example
The following example tracks device status using a keyed input table. Each device has a unique ID, and updates replace the previous status for that device.
Input table types
The Java client supports three types of input tables:
Keyed
Rows are identified by key columns. Adding a row with an existing key replaces that row. Deletion is supported.
With keyed tables, you can delete rows by providing just the key values:
Append-only
Rows are added to the end of the table. No key columns, no updates, no deletion. Use this when you need a simple log or event stream.
Blink
Rows are visible for only one update graph cycle, then disappear. Use this for event streams where you only need to process the latest batch.
Resource management
TableHandle lifecycle
TableHandle represents a managed export and implements Closeable. Unclosed handles leak server-side resources for the lifetime of the client. The recommended pattern is:
- Execute the spec to create the input table.
- Publish it to the query scope (creates a server-side reference).
- Close the handle immediately.
- Send data via
ScopeId.
This ensures the server-side table persists (via the scope) while avoiding client-side resource leaks.
Data upload lifecycle
The FlightSession.addToInputTable method handles data upload automatically:
- Uploads the
NewTableto the server as a temporary export. - Calls the input table service to add the data.
- Releases the temporary export when complete.
If you need more control, you can use the lower-level Session API:
Batch uploads
For better performance, batch multiple rows into a single upload:
Working examples
The Deephaven repository includes complete working examples:
AddToInputTable.java- Append-only input table with validationKeyValueInputTable.java- Keyed input table with add/deleteAddToBlinkTable.java- Blink input table