Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Datahub project Datahub Entity Mutable Patch

From Leeroopedia


Property Value
Implementation Name Entity_Mutable_Patch
Workflow Java_SDK_V2_Entity_Management
Type API Doc
Principle Principle:Datahub_project_Datahub_Patch_Based_Updates
Repository https://github.com/datahub-project/datahub
Last Updated 2026-02-09 17:00 GMT

Overview

Description

Entity_Mutable_Patch documents the entity.mutable() method and the fluent patch API for modifying metadata entities. The mutable() method creates a writable copy from a read-only entity (fetched from the server), enabling a read-modify-write workflow. Once mutable, the entity exposes fluent methods like setDescription(), addTag(), addOwner(), and addTerm() that accumulate JSON Patch operations internally. These patches are emitted when client.entities().upsert(entity) is called.

The VersionAwarePatchTransformer handles server version compatibility by transforming patches to full aspect replacements for servers that do not support specific patch types (DataHub Core <= v1.3.0).

Usage

Call .mutable() on any read-only entity to get a writable copy. If the entity is already mutable (e.g., created via a builder), .mutable() returns the same instance (idempotent). Apply modifications through the fluent API, then call client.entities().upsert(entity) to persist changes.

Code Reference

Source Location

  • metadata-integration/java/datahub-client/src/main/java/datahub/client/v2/entity/Entity.java (Lines 384-747) -- mutable() method and patch infrastructure
  • metadata-integration/java/datahub-client/src/main/java/datahub/client/v2/patch/VersionAwarePatchTransformer.java (Lines 51-184) -- Server version-aware patch transformation

Signature

// Create mutable copy from read-only entity
public <T extends Entity> T mutable()

// Fluent mutation methods (available on mutable entities)
public Dataset setDescription(@Nonnull String description)
public Dataset setSystemDescription(@Nonnull String description)
public Dataset setEditableDescription(@Nonnull String description)
public Dataset setDisplayName(@Nonnull String name)
public Dataset addCustomProperty(@Nonnull String key, @Nonnull String value)
public Dataset removeCustomProperty(@Nonnull String key)
public Dataset setCustomProperties(@Nonnull Map<String, String> properties)

// From HasTags interface
public T addTag(@Nonnull String tag)
public T removeTag(@Nonnull String tag)

// From HasOwners interface
public T addOwner(@Nonnull String ownerUrn, @Nonnull OwnershipType type)
public T removeOwner(@Nonnull String ownerUrn)

// From HasGlossaryTerms interface
public T addTerm(@Nonnull String termUrn)
public T removeTerm(@Nonnull String termUrn)

// From HasDomains interface
public T setDomain(@Nonnull String domainUrn)
public T unsetDomain()

// Patch registration (internal)
protected void registerPatchBuilder(String aspectName, AbstractMultiFieldPatchBuilder<?> builder)
protected void addPatchMcp(MetadataChangeProposal patch)

Import

import datahub.client.v2.entity.Entity;
import datahub.client.v2.entity.Dataset;
import datahub.client.v2.patch.VersionAwarePatchTransformer;

I/O Contract

mutable() Method:

Input Output Behavior
Called on read-only entity New mutable copy of the entity Creates writable copy via reflection-based cloning; shares aspect cache with original, fresh mutation tracking
Called on mutable entity Same entity instance (this) Idempotent -- returns self without creating a copy

Mutation Methods:

Method Patch Aspect Operation Type Mode Awareness
setDescription(String) editableDatasetProperties (SDK) or datasetProperties (INGESTION) JSON Patch ADD Yes -- writes to editable or system aspect based on mode
addTag(String) globalTags JSON Patch ADD No
removeTag(String) globalTags JSON Patch REMOVE No
addOwner(String, OwnershipType) ownership JSON Patch ADD No
removeOwner(String) ownership JSON Patch REMOVE No
addTerm(String) glossaryTerms JSON Patch ADD No
removeTerm(String) glossaryTerms JSON Patch REMOVE No
setDomain(String) domains Full aspect UPSERT No
addCustomProperty(String, String) datasetProperties Accumulated patch ADD No
removeCustomProperty(String) datasetProperties Accumulated patch REMOVE No

Version-Aware Transformation:

Server Version Behavior
DataHub Core > v1.3.0 Patches passed through unchanged
DataHub Core <= v1.3.0 Editable property patches transformed to full aspect replacements via read-modify-write
All versions mlModelProperties patches always transformed with retry function
Unknown (serverConfig null) Patches passed through unchanged with warning

Exceptions:

Exception Cause
ReadOnlyEntityException Mutation method called on a read-only entity (must call .mutable() first)
RuntimeException Reflection-based cloning fails in mutable()

Usage Examples

Read-Modify-Write Pattern

import datahub.client.v2.entity.Dataset;

// Step 1: Fetch entity (returns read-only)
String urn = "urn:li:dataset:(urn:li:dataPlatform:snowflake,analytics.users,PROD)";
Dataset readOnly = client.entities().get(urn, Dataset.class);

// Step 2: Create mutable copy
Dataset mutable = readOnly.mutable();

// Step 3: Apply patch operations (accumulated internally)
mutable.setDescription("Updated user analytics table");
mutable.addTag("verified");
mutable.addOwner("urn:li:corpuser:alice", OwnershipType.DATA_OWNER);
mutable.addTerm("urn:li:glossaryTerm:UserData");

// Step 4: Upsert persists all patches
client.entities().upsert(mutable);

Patching a Newly Built Entity

// Entities created via builders are already mutable
Dataset dataset = Dataset.builder()
    .platform("bigquery")
    .name("project.dataset.events")
    .description("Event stream")
    .build();

// Patches accumulate alongside builder-cached aspects
dataset.addTag("streaming");
dataset.addCustomProperty("retention_days", "90");

// Upsert emits both full aspects (description) and patches (tag, custom property)
client.entities().upsert(dataset);

Accumulated Custom Property Operations

Dataset mutable = readOnly.mutable();

// Multiple addCustomProperty calls accumulate in a single DatasetPropertiesPatchBuilder
mutable.addCustomProperty("team", "data-eng");
mutable.addCustomProperty("sla", "99.9%");
mutable.addCustomProperty("cost_center", "CC-1234");
mutable.removeCustomProperty("deprecated_key");

// One patch MCP is emitted containing all four operations
client.entities().upsert(mutable);

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment