Documentation Index
Fetch the complete documentation index at: https://openmetadata-feat-feat-2mbfixdeploy.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Java SDK
The OpenMetadata Java SDK provides a robust client library for Java applications to interact with the OpenMetadata API. It offers comprehensive support for entity management, authentication, and integration with enterprise Java applications.
Installation
Maven
Add the OpenMetadata Java SDK dependency to your pom.xml:
<dependency>
<groupId>org.open-metadata</groupId>
<artifactId>openmetadata-java-client</artifactId>
<version>1.9.0</version>
</dependency>
Gradle
Add the dependency to your build.gradle:
implementation 'org.open-metadata:openmetadata-java-client:1.9.0'
Quick Start
Basic Connection
import org.openmetadata.client.OpenMetadataClient;
import org.openmetadata.client.model.*;
import org.openmetadata.client.auth.BasicAuthProvider;
// Create client with basic authentication
OpenMetadataClient client = OpenMetadataClient.builder()
.baseUrl("http://localhost:8585/api")
.authProvider(new BasicAuthProvider("admin", "admin"))
.build();
// Health check
if (client.healthCheck()) {
System.out.println("Successfully connected to OpenMetadata!");
}
JWT Authentication
import org.openmetadata.client.auth.JWTAuthProvider;
// Create client with JWT authentication
OpenMetadataClient client = OpenMetadataClient.builder()
.baseUrl("http://localhost:8585/api")
.authProvider(new JWTAuthProvider("your-jwt-token"))
.build();
Core Functionality
Working with Entities
Database Services
import org.openmetadata.schema.entity.services.DatabaseService;
import org.openmetadata.schema.api.services.CreateDatabaseService;
// List all database services
List<DatabaseService> services = client.listDatabaseServices();
System.out.println("Found " + services.size() + " database services");
// Get specific service by name
DatabaseService service = client.getDatabaseServiceByName("mysql-prod");
// Create new database service
CreateDatabaseService createRequest = new CreateDatabaseService()
.withName("new-mysql-service")
.withServiceType(DatabaseServiceType.MYSQL)
.withDescription("Production MySQL database");
DatabaseService newService = client.createDatabaseService(createRequest);
Tables
import org.openmetadata.schema.entity.data.Table;
import org.openmetadata.schema.api.data.CreateTable;
// Get table by fully qualified name
Table table = client.getTableByName("mysql-prod.employees.employees");
if (table != null) {
System.out.println("Table: " + table.getName());
System.out.println("Columns: " + table.getColumns().size());
}
// List tables with pagination
EntityList<Table> tables = client.listTables(
10, // limit
null, // after cursor
"mysql-prod" // service filter
);
// Create table
CreateTable createTable = new CreateTable()
.withName("new_table")
.withDatabaseSchema("mysql-prod.employees")
.withColumns(Arrays.asList(
new Column()
.withName("id")
.withDataType(ColumnDataType.BIGINT)
.withDescription("Primary key"),
new Column()
.withName("name")
.withDataType(ColumnDataType.VARCHAR)
.withDataLength(255)
.withDescription("Employee name")
));
Table newTable = client.createTable(createTable);
Entity Operations
CRUD Operations
// Create or Update
DatabaseService service = client.createOrUpdateDatabaseService(createRequest);
// Get by ID
UUID serviceId = UUID.fromString("service-uuid-here");
DatabaseService service = client.getDatabaseServiceById(serviceId);
// Delete
client.deleteDatabaseService(serviceId, false); // soft delete
client.deleteDatabaseService(serviceId, true); // hard delete
Search and Filtering
// Search tables
SearchRequest searchRequest = new SearchRequest()
.withQuery("customer")
.withEntityTypes(Arrays.asList("table"))
.withSize(50);
SearchResponse results = client.search(searchRequest);
for (SearchHit hit : results.getHits()) {
System.out.println("Found: " + hit.getDisplayName());
}
// Advanced filtering
EntityList<Table> customerTables = client.listTables(
100,
null,
Map.of(
"service", "mysql-prod",
"database", "ecommerce"
)
);
Advanced Features
Authentication Providers
Custom Authentication
import org.openmetadata.client.auth.AuthProvider;
public class CustomAuthProvider implements AuthProvider {
private String customToken;
public CustomAuthProvider(String token) {
this.customToken = token;
}
@Override
public String getAuthToken() {
return "Bearer " + customToken;
}
@Override
public void refresh() {
// Implement token refresh logic
}
}
// Use custom auth provider
OpenMetadataClient client = OpenMetadataClient.builder()
.baseUrl("https://your-instance.com/api")
.authProvider(new CustomAuthProvider("custom-token"))
.build();
OAuth 2.0 Integration
import org.openmetadata.client.auth.OAuth2AuthProvider;
OAuth2AuthProvider authProvider = OAuth2AuthProvider.builder()
.clientId("your-client-id")
.clientSecret("your-client-secret")
.tokenUrl("https://auth.provider.com/oauth/token")
.scopes(Arrays.asList("read", "write"))
.build();
OpenMetadataClient client = OpenMetadataClient.builder()
.baseUrl("https://your-instance.com/api")
.authProvider(authProvider)
.build();
Error Handling
import org.openmetadata.client.exception.OpenMetadataException;
try {
Table table = client.getTableByName("non-existent-table");
} catch (OpenMetadataException e) {
switch (e.getErrorCode()) {
case NOT_FOUND:
System.out.println("Table not found");
break;
case UNAUTHORIZED:
System.out.println("Authentication failed");
break;
case FORBIDDEN:
System.out.println("Access denied");
break;
default:
System.out.println("Error: " + e.getMessage());
}
}
Async Operations
import java.util.concurrent.CompletableFuture;
// Async client operations
CompletableFuture<List<DatabaseService>> servicesFuture =
client.listDatabaseServicesAsync();
CompletableFuture<Table> tableFuture =
client.getTableByNameAsync("mysql-prod.employees.employees");
// Combine async operations
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(
servicesFuture,
tableFuture
).thenRun(() -> {
try {
List<DatabaseService> services = servicesFuture.get();
Table table = tableFuture.get();
System.out.println("Found " + services.size() + " services");
System.out.println("Table columns: " + table.getColumns().size());
} catch (Exception e) {
e.printStackTrace();
}
});
Configuration Options
Client Configuration
import org.openmetadata.client.config.ClientConfig;
ClientConfig config = ClientConfig.builder()
.connectionTimeout(30000) // 30 seconds
.readTimeout(60000) // 60 seconds
.retryCount(3) // Retry failed requests 3 times
.enableLogging(true) // Enable request/response logging
.enableMetrics(true) // Enable client metrics
.userAgent("MyApp/1.0") // Custom user agent
.build();
OpenMetadataClient client = OpenMetadataClient.builder()
.baseUrl("http://localhost:8585/api")
.authProvider(authProvider)
.config(config)
.build();
Connection Pooling
import org.openmetadata.client.config.ConnectionPoolConfig;
ConnectionPoolConfig poolConfig = ConnectionPoolConfig.builder()
.maxTotal(100) // Maximum total connections
.maxPerRoute(20) // Maximum connections per route
.connectionTTL(300000) // Connection TTL in milliseconds
.validateAfterInactivity(10000) // Validate connections after 10s
.build();
ClientConfig config = ClientConfig.builder()
.connectionPoolConfig(poolConfig)
.build();
Common Use Cases
// Discover all tables in a service
String serviceName = "mysql-prod";
List<Table> allTables = new ArrayList<>();
String after = null;
do {
EntityList<Table> batch = client.listTables(100, after, serviceName);
allTables.addAll(batch.getData());
after = batch.getAfter();
} while (after != null);
System.out.println("Discovered " + allTables.size() + " tables");
Bulk Operations
// Bulk update table descriptions
List<Table> tables = client.listAllTablesInService("mysql-prod");
for (Table table : tables) {
if (table.getDescription() == null || table.getDescription().isEmpty()) {
CreateTable updateRequest = new CreateTable()
.withName(table.getName())
.withDatabaseSchema(table.getDatabaseSchema().getFullyQualifiedName())
.withDescription("Auto-generated description for " + table.getName());
client.createOrUpdateTable(updateRequest);
}
}
Lineage Operations
import org.openmetadata.schema.type.EntityLineage;
// Get table lineage
EntityLineage lineage = client.getTableLineage(
"mysql-prod.employees.employees",
1, // upstream depth
1 // downstream depth
);
System.out.println("Upstream entities: " + lineage.getUpstreamEdges().size());
System.out.println("Downstream entities: " + lineage.getDownstreamEdges().size());
Spring Boot Integration
Configuration Class
@Configuration
@EnableConfigurationProperties(OpenMetadataProperties.class)
public class OpenMetadataConfig {
@Bean
public OpenMetadataClient openMetadataClient(OpenMetadataProperties properties) {
return OpenMetadataClient.builder()
.baseUrl(properties.getBaseUrl())
.authProvider(new JWTAuthProvider(properties.getJwtToken()))
.build();
}
}
@ConfigurationProperties(prefix = "openmetadata")
@Data
public class OpenMetadataProperties {
private String baseUrl;
private String jwtToken;
}
Service Layer
@Service
public class MetadataService {
private final OpenMetadataClient client;
public MetadataService(OpenMetadataClient client) {
this.client = client;
}
public List<Table> getTablesForService(String serviceName) {
return client.listAllTablesInService(serviceName);
}
public Table createTable(CreateTableRequest request) {
CreateTable createTable = new CreateTable()
.withName(request.getName())
.withDatabaseSchema(request.getSchemaFqn())
.withColumns(request.getColumns());
return client.createTable(createTable);
}
}
Best Practices
- Resource Management: Always close clients when done
- Connection Pooling: Use connection pooling for high-throughput applications
- Error Handling: Implement proper retry logic and error handling
- Authentication: Use secure authentication methods in production
- Async Operations: Use async methods for better performance in concurrent scenarios
- Pagination: Always handle pagination for large datasets
- Caching: Implement caching for frequently accessed entities
- Use batch operations when possible
- Implement connection pooling for high-concurrency applications
- Cache frequently accessed metadata
- Use async operations for better throughput
- Specify only required fields when fetching entities
- Implement proper retry strategies with exponential backoff