Implementation:Datahub project Datahub HasTags Mixin
| Knowledge Sources | |
|---|---|
| Domains | Java_SDK, Metadata_Management |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
HasTags is a Java mixin interface providing tag operations (add, remove, set, get) for any DataHub entity that supports the globalTags aspect, using a self-bounded generic pattern for fluent method chaining.
Description
The HasTags<T> interface uses Java default methods to inject tag management behavior into entity classes without requiring code duplication. It is parameterized with a self-bounded generic T extends Entity & HasTags<T> to ensure that fluent setter methods return the concrete entity type.
Key characteristics:
- Patch-based add/remove:
addTag()andremoveTag()use an accumulatedGlobalTagsPatchBuilderinstance, retrieved and registered via the entity'sgetPatchBuilder()andregisterPatchBuilder()methods. Multiple tag operations are batched into a single MCP. - Full replacement set:
setTags()creates a completeGlobalTagsaspect with aTagAssociationArrayand emits it as aMetadataChangeProposalWrapperwith UPSERT change type. This replaces all existing tags. - Lazy-loaded read:
getTags()reads theGlobalTagsaspect from the entity's cache viagetAspectLazy(). - URN normalization: Tag strings are automatically prefixed with
"urn:li:tag:"if not already in URN format. For example,addTag("pii")is equivalent toaddTag("urn:li:tag:pii"). - Server compatibility: Includes a static
transformPatchToFullAspect()method that converts patch MCPs to full aspect replacement MCPs via read-modify-write for compatibility with older DataHub servers (<= v1.3.0). TheapplyPatchOperations()method parses JSON Patch arrays and applies ADD/REMOVE operations on the/tags/path.
Entities implementing this interface: Chart, Container, Dashboard, DataFlow, DataJob, MLModel, MLModelGroup, and Dataset.
Usage
Any entity class extending Entity that needs tag support should implement HasTags<MyEntity>. The interface provides all tag operations via default methods, requiring no additional implementation in the entity class itself.
Code Reference
Source Location
- Repository: Datahub_project_Datahub
- File: metadata-integration/java/datahub-client/src/main/java/datahub/client/v2/entity/HasTags.java
Signature
public interface HasTags<T extends Entity & HasTags<T>> {
// Add operations (patch-based, accumulated)
default T addTag(String tagUrn);
default T addTag(TagUrn tagUrn);
// Remove operations (patch-based, accumulated)
default T removeTag(String tagUrn);
default T removeTag(TagUrn tagUrn);
// Full replacement
default T setTags(List<String> tagUrns);
// Read
default List<TagAssociation> getTags();
// Server compatibility (static)
static MetadataChangeProposal transformPatchToFullAspect(
MetadataChangeProposal patch, EntityClient client)
throws IOException, ExecutionException, InterruptedException;
// Patch application (package-private static)
static GlobalTags applyPatchOperations(GlobalTags current, MetadataChangeProposal patch)
throws IOException;
}
Import
import datahub.client.v2.entity.HasTags;
I/O Contract
Inputs
| Method | Parameter | Type | Description |
|---|---|---|---|
addTag |
tagUrn |
String or TagUrn |
Tag URN or short name (auto-prefixed with urn:li:tag:)
|
removeTag |
tagUrn |
String or TagUrn |
Tag URN to remove |
setTags |
tagUrns |
List<String> |
Complete list of tag URNs to set (replaces all) |
Outputs
| Method | Return Type | Description |
|---|---|---|
addTag / removeTag / setTags |
T (concrete entity type) |
Returns this for fluent chaining
|
getTags |
List<TagAssociation> |
List of tag associations, or null if no tags |
transformPatchToFullAspect |
MetadataChangeProposal |
Full UPSERT MCP with applied tag changes |
Usage Examples
// Using HasTags via a concrete entity
Dataset dataset = Dataset.builder()
.platform("snowflake")
.name("my_table")
.build();
// Add tags (short name auto-prefixed)
dataset.addTag("pii");
dataset.addTag("urn:li:tag:sensitive");
// Remove a tag
dataset.removeTag("deprecated");
// Replace all tags
dataset.setTags(List.of("production", "verified", "urn:li:tag:tier1"));
// Read tags
List<TagAssociation> tags = dataset.getTags();
// Implementing HasTags in a custom entity
public class MyEntity extends Entity implements HasTags<MyEntity> {
// All tag operations are provided by default methods
// No additional implementation needed
}