How to Use the OpenMetadata SDK for Java: A Complete Guide
Use the OpenMetadata Java SDK by configuring OpenMetadataConfig with your server URL and token, instantiating OpenMetadataClient, setting it as the default for fluent helpers, then calling methods like Tables.create() or Tables.find() to manage metadata entities.
The OpenMetadata SDK provides a type-safe, fluent Java API that mirrors the OpenMetadata REST API. This guide walks through the complete workflow—from configuration to CRUD operations, CSV import/export, and working with multiple entity types—based on the actual source code in the open-metadata/OpenMetadata repository.
Setting Up the OpenMetadata SDK
Add the Maven Dependency
Include the SDK in your pom.xml:
<dependency>
<groupId>org.openmetadata</groupId>
<artifactId>openmetadata-sdk</artifactId>
<version>1.5.0</version>
</dependency>
The latest version is defined in the SDK's pom.xml at openmetadata-sdk/pom.xml.
Configuring the OpenMetadata Client
Create the Configuration
The OpenMetadataConfig class in openmetadata-sdk/src/main/java/org/openmetadata/sdk/config/OpenMetadataConfig.java provides a builder for connection settings:
import org.openmetadata.sdk.config.OpenMetadataConfig;
OpenMetadataConfig config = OpenMetadataConfig.builder()
.serverUrl("http://localhost:8585/api")
.accessToken("YOUR_PERSONAL_ACCESS_TOKEN")
.debug(true)
.build();
Generate your personal access token in the OpenMetadata UI under Settings > Tokens.
Initialize the Client
The OpenMetadataClient class in openmetadata-sdk/src/main/java/org/openmetadata/sdk/client/OpenMetadataClient.java aggregates service objects for each entity type:
import org.openmetadata.sdk.client.OpenMetadataClient;
OpenMetadataClient client = new OpenMetadataClient(config);
Register the Default Client
Fluent helpers require a default client. The Tables class in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java provides the registration mechanism:
import static org.openmetadata.sdk.fluent.Tables.*;
Tables.setDefaultClient(client);
Once set, all fluent classes (Tables, Databases, Teams, Users, etc.) automatically retrieve the client via Tables.getClient().
Core Fluent Operations with the OpenMetadata SDK
Create a Table
The Tables.create() method returns a TableCreator that builds and executes the REST call:
import org.openmetadata.schema.api.data.CreateTable;
import org.openmetadata.schema.type.Column;
import org.openmetadata.schema.type.ColumnDataType;
// Build the request object
CreateTable request = new CreateTable()
.name("customers")
.databaseSchema("sample_data.ecommerce_db.shopify")
.description("Customer information")
.columns(List.of(
new Column()
.name("id")
.dataType(ColumnDataType.BIGINT),
new Column()
.name("email")
.dataType(ColumnDataType.VARCHAR)
.dataLength(255),
new Column()
.name("created_at")
.dataType(ColumnDataType.TIMESTAMP)));
// Execute via fluent API
var table = Tables.create()
.withDescription(request.getDescription())
.inSchema(request.getDatabaseSchema())
.withColumns(request.getColumns())
.name(request.getName())
.execute(); // Returns org.openmetadata.schema.entity.data.Table
The TableCreator forwards the request to client.tables().create(request) as implemented in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 69-76.
Retrieve a Table
Fetch by UUID or fully-qualified name with optional field expansion:
// By UUID
var table = Tables.get("3fa85f64-5717-4562-b3fc-2c963f66afa6");
// By FQN with related data
var table = Tables.findByName("sample_data.ecommerce_db.shopify.customers")
.includeOwners()
.includeTags()
.fetch()
.get();
The find and findByName helpers construct proper query parameters (include, fields) as shown in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 78-92.
Update a Table
Modify fields and persist changes:
var updated = Tables.find(table.getId().toString())
.fetch()
.withDescription("Updated description")
.withDisplayName("Customers")
.save(); // PATCHes the entity and returns refreshed Table
FluentTable.save() detects modifications and calls client.tables().update(id, entity) per openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 99-104.
Delete a Table
Remove with optional cascade and permanence:
Tables.find(table.getId().toString())
.delete()
.recursively() // cascade delete
.permanently() // hard delete (vs. soft delete)
.confirm();
TableDeleter builds query parameters (recursive, hardDelete) and invokes client.tables().delete(id, params) as implemented in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 67-75.
List Tables
Paginate through results:
List<Tables.FluentTable> tables = Tables.list()
.limit(20)
.after("cursor-token") // pagination cursor
.fetch(); // → List<FluentTable>
The lister wraps the generic list endpoint and converts each Table to FluentTable per openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 94-102.
CSV Import and Export with the OpenMetadata SDK
Export Table Definition to CSV
String csv = Tables.exportCsv("sample_data.ecommerce_db.shopify.customers")
.async() // optional – returns job ID for async processing
.toCsv(); // → CSV string (or job ID if async)
CsvExporter calls client.tables().exportCsv(...) or exportCsvAsync(...) as shown in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 15-22.
Import CSV to Update Columns
String csvData = """
columnName,dataType,dataLength,description
phone_number,VARCHAR,20,Customer phone
""";
String result = Tables.importCsv("sample_data.ecommerce_db.shopify.customers")
.withData(csvData)
.dryRun() // validates only; omit for actual import
.apply(); // → response JSON (or job ID for async)
CsvImporter reads CSV from string or file, then invokes client.tables().importCsv(...) or the async variant per openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java lines 44-52.
Working with Other Entities in the OpenMetadata SDK
The SDK provides parallel fluent helpers for all major entity types:
| Entity | Fluent Helper | Example |
|---|---|---|
| Database | Databases |
Databases.create().name("sales").in("sample_data").execute(); |
| Team | Teams |
Teams.create().name("analytics").withDescription("Analytics team").execute(); |
| User | Users |
Users.create().name("john.doe").withEmail("john.doe@example.com").execute(); |
| Dashboard | Dashboards |
Dashboards.findByName("sales_metrics").fetch(); |
| Pipeline | Pipelines |
Pipelines.list().limit(50).fetch(); |
All helpers follow the same pattern: setDefaultClient(), then use create(), find(), list(), or direct service calls (client.users(), client.databases(), …).
Complete Minimal Example
import org.openmetadata.sdk.config.OpenMetadataConfig;
import org.openmetadata.sdk.client.OpenMetadataClient;
import static org.openmetadata.sdk.fluent.Tables.*;
public class SdkDemo {
public static void main(String[] args) {
// 1️⃣ Config & client
var cfg = OpenMetadataConfig.builder()
.serverUrl("http://localhost:8585/api")
.accessToken(System.getenv("OM_TOKEN"))
.debug(true)
.build();
var client = new OpenMetadataClient(cfg);
Tables.setDefaultClient(client);
// 2️⃣ Create a table
var table = Tables.create()
.name("orders")
.inSchema("sample_data.sales_db.public")
.withDescription("Orders table")
.withColumns(List.of(
new org.openmetadata.schema.type.Column()
.name("order_id")
.dataType(org.openmetadata.schema.type.ColumnDataType.BIGINT),
new org.openmetadata.schema.type.Column()
.name("amount")
.dataType(org.openmetadata.schema.type.ColumnDataType.DOUBLE)))
.execute();
System.out.println("Created: " + table.getFullyQualifiedName());
// 3️⃣ Update description
Tables.find(table.getId().toString())
.fetch()
.withDescription("Updated orders description")
.save();
// 4️⃣ Export to CSV
String csv = Tables.exportCsv(table.getFullyQualifiedName()).toCsv();
System.out.println("CSV:\n" + csv);
}
}
This demonstrates the complete lifecycle: configure → client → default client → fluent operations. Run after adding the SDK dependency and providing a valid token.
Key Source Files in the OpenMetadata SDK
| File | Purpose | Location |
|---|---|---|
OpenMetadataConfig.java |
Builder for connection settings (URL, token, timeouts) | openmetadata-sdk/src/main/java/org/openmetadata/sdk/config/OpenMetadataConfig.java |
OpenMetadataClient.java |
Core client creating service objects and handling HTTP transport | openmetadata-sdk/src/main/java/org/openmetadata/sdk/client/OpenMetadataClient.java |
Tables.java |
Fluent wrapper for all table operations (create, find, list, CSV, etc.) | openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java |
PureFluentAPIExample.java |
End-to-end sample demonstrating client initialization, CRUD, and CSV usage | openmetadata-sdk/src/main/java/org/openmetadata/sdk/examples/PureFluentAPIExample.java |
TableService.java |
Low-level service communicating with the /v1/tables REST endpoint |
openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/dataassets/TableService.java |
These files illustrate the SDK architecture: configuration → client → service objects → fluent helpers.
Summary
- Configure with
OpenMetadataConfig.builder()to set server URL, access token, and optional debug mode. - Instantiate
OpenMetadataClientwith your configuration to create the HTTP transport layer. - Register the client as default via
Tables.setDefaultClient()to enable fluent helpers across all entity types. - Operate using fluent methods—
create(),find(),list(),save(),delete()—with built-in pagination, field expansion, and CSV support. - Extend the same pattern to
Databases,Teams,Users,Dashboards,Pipelines, and other entities.
The OpenMetadata SDK abstracts REST complexity while preserving full API coverage, enabling compile-time type safety and idiomatic Java patterns for data catalog operations.
Frequently Asked Questions
How do I authenticate with the OpenMetadata SDK?
Generate a personal access token in the OpenMetadata UI under Settings > Tokens, then pass it to OpenMetadataConfig.builder().accessToken("your-token"). The SDK sends this as a Bearer token in the Authorization header for all requests.
What is the difference between the fluent API and direct service calls?
The fluent API (Tables.create(), Tables.find()) provides a chainable, type-safe interface that handles parameter building and object conversion. Direct service calls (client.tables().create(request)) offer lower-level access to the REST endpoints. Both use the same underlying TableService in openmetadata-sdk/src/main/java/org/openmetadata/sdk/services/dataassets/TableService.java.
How do I handle pagination when listing entities?
Use the .after("cursor") and .limit(n) methods on list operations. The Tables.list() method in openmetadata-sdk/src/main/java/org/openmetadata/sdk/fluent/Tables.java converts the paginated response into a List<FluentTable> while preserving the cursor for subsequent requests.
Can I perform bulk operations with the OpenMetadata SDK?
Yes. Use importCsv() and exportCsv() methods for bulk column updates and table schema exports. Add .async() to run these as background jobs, returning a job ID you can poll for completion status.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →