Implementation:Datahub project Datahub RestEmitter
| Knowledge Sources | |
|---|---|
| Domains | Java_SDK, Metadata_Management |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
RestEmitter is a thread-safe HTTP client wrapper that provides non-blocking emission of metadata change proposals (MCPs) to the DataHub GMS backend over REST.
Description
The RestEmitter class is a thin wrapper on top of the Apache HttpClient 5 async library. It handles the details of JSON serialization of metadata aspects, authentication via bearer tokens, retry strategies, SSL configuration, and both the legacy RestLI ingest endpoint (/aspects?action=ingestProposal) and the OpenAPI entities endpoint (/openapi/entities/v1/). All HTTP calls are non-blocking, returning Future<MetadataWriteResponse> to allow asynchronous metadata emission.
Key responsibilities:
- Serialization: Converts
MetadataChangeProposalandMetadataChangeProposalWrapperobjects to JSON payloads using Jackson andJacksonDataTemplateCodec. - Authentication: Supports bearer token authentication via the
Authorizationheader, along with custom extra headers. - SSL: Supports optional SSL verification disablement for development environments via
TrustAllStrategyandNoopHostnameVerifier. - Retry: Uses a configurable
DatahubHttpRequestRetryStrategywith max retries and retry interval. - Connection test: Provides a
testConnection()method that GETs the/configendpoint to verify connectivity. - OpenAPI support: Supports batch upserts via
List<UpsertAspectRequest>on the OpenAPI endpoint.
The class implements the Emitter interface and is annotated @ThreadSafe.
Usage
Use RestEmitter when you need to programmatically emit metadata to a DataHub instance from a Java application. It is the primary transport mechanism used by the Java SDK V2 EntityClient to send entity data to the server. Users can construct it via the fluent builder factory method or obtain it indirectly through DataHubClientV2.
Code Reference
Source Location
- Repository: Datahub_project_Datahub
- File: metadata-integration/java/datahub-client/src/main/java/datahub/client/rest/RestEmitter.java
Signature
@ThreadSafe
@Slf4j
public class RestEmitter implements Emitter {
// Factory methods
public static RestEmitter create(Consumer<RestEmitterConfig.RestEmitterConfigBuilder> builderSupplier);
public static RestEmitter createWithDefaults();
// Constructor
public RestEmitter(RestEmitterConfig config);
// Emit methods
public Future<MetadataWriteResponse> emit(MetadataChangeProposalWrapper mcpw, Callback callback) throws IOException;
public Future<MetadataWriteResponse> emit(MetadataChangeProposal mcp, Callback callback) throws IOException;
public Future<MetadataWriteResponse> emit(List<UpsertAspectRequest> request, Callback callback) throws IOException;
// Utility methods
public boolean testConnection() throws IOException, ExecutionException, InterruptedException;
public RestEmitterConfig getConfig();
public Future<MetadataWriteResponse> get(String urlStr) throws IOException;
public void close() throws IOException;
}
Import
import datahub.client.rest.RestEmitter;
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
config |
RestEmitterConfig |
Configuration including server URL, token, timeout, SSL settings, extra headers, retry policy, and async ingest flag |
mcpw |
MetadataChangeProposalWrapper |
Wrapped metadata change proposal for emission via RestLI endpoint |
mcp |
MetadataChangeProposal |
Raw metadata change proposal for emission via RestLI endpoint |
request |
List<UpsertAspectRequest> |
Batch of aspect upsert requests for emission via OpenAPI endpoint |
callback |
Callback |
Optional callback invoked on completion or failure |
Outputs
| Return Type | Description |
|---|---|
Future<MetadataWriteResponse> |
Asynchronous response indicating success/failure, HTTP status, and response body content |
boolean |
Connection test result (from testConnection())
|
Usage Examples
// Create with fluent builder
RestEmitter emitter = RestEmitter.create(b -> b
.server("http://localhost:8080")
.token("your-access-token")
);
// Test connection
boolean connected = emitter.testConnection();
// Emit a MetadataChangeProposalWrapper
MetadataChangeProposalWrapper mcp = MetadataChangeProposalWrapper.builder()
.entityType("dataset")
.entityUrn(datasetUrn)
.upsert()
.aspect(ownership)
.build();
Future<MetadataWriteResponse> future = emitter.emit(mcp, null);
MetadataWriteResponse response = future.get();
// Create with default settings
RestEmitter defaultEmitter = RestEmitter.createWithDefaults();
// Close when done
emitter.close();