---
description: "Create, update, and manage Dashboard entities (Looker, Tableau, PowerBI, etc.) in DataHub using the Java SDK V2."
---

# Dashboard Entity

The Dashboard entity represents collections of visualizations and reports in BI tools (e.g., Looker, Tableau, PowerBI). This guide covers comprehensive dashboard operations in SDK V2.

## Creating a Dashboard

### Minimal Dashboard

Only tool and id are required:

```java
Dashboard dashboard = Dashboard.builder()
    .tool("looker")
    .id("my_sales_dashboard")
    .build();
```

### With Metadata

Add title and description at construction:

```java
Dashboard dashboard = Dashboard.builder()
    .tool("tableau")
    .id("executive_dashboard")
    .title("Executive KPI Dashboard")
    .description("Real-time executive dashboard showing key business metrics")
    .build();
```

### With Custom Properties

Include custom properties in builder:

```java
Map<String, String> props = new HashMap<>();
props.put("team", "business-intelligence");
props.put("refresh_schedule", "hourly");

Dashboard dashboard = Dashboard.builder()
    .tool("powerbi")
    .id("sales_dashboard")
    .title("Sales Performance")
    .customProperties(props)
    .build();
```

## URN Construction

Dashboard URNs follow the pattern:

```
urn:li:dashboard:({tool},{id})
```

**Automatic URN creation:**

```java
Dashboard dashboard = Dashboard.builder()
    .tool("looker")
    .id("regional_sales")
    .build();

DashboardUrn urn = dashboard.getDashboardUrn();
// urn:li:dashboard:(looker,regional_sales)
```

## Supported BI Tools

Common tool identifiers:

- `looker` - Looker
- `tableau` - Tableau
- `powerbi` - Power BI
- `superset` - Apache Superset
- `metabase` - Metabase
- `redash` - Redash
- `mode` - Mode Analytics
- `quicksight` - Amazon QuickSight
- `thoughtspot` - ThoughtSpot

## Tags

### Adding Tags

```java
// Simple tag name (auto-prefixed)
dashboard.addTag("executive");
// Creates: urn:li:tag:executive

// Full tag URN
dashboard.addTag("urn:li:tag:production");
```

### Removing Tags

```java
dashboard.removeTag("executive");
dashboard.removeTag("urn:li:tag:production");
```

### Tag Chaining

```java
dashboard.addTag("executive")
         .addTag("real-time")
         .addTag("kpi");
```

## Owners

### Adding Owners

```java
import com.linkedin.common.OwnershipType;

// Business owner
dashboard.addOwner(
    "urn:li:corpuser:john_doe",
    OwnershipType.BUSINESS_OWNER
);

// Technical owner
dashboard.addOwner(
    "urn:li:corpuser:bi_team",
    OwnershipType.TECHNICAL_OWNER
);

// Data steward
dashboard.addOwner(
    "urn:li:corpuser:governance",
    OwnershipType.DATA_STEWARD
);
```

### Removing Owners

```java
dashboard.removeOwner("urn:li:corpuser:john_doe");
```

### Owner Types

Available ownership types:

- `BUSINESS_OWNER` - Business stakeholder
- `TECHNICAL_OWNER` - Maintains the technical implementation
- `DATA_STEWARD` - Manages data quality and compliance
- `DATAOWNER` - Generic data owner
- `DEVELOPER` - Software developer
- `PRODUCER` - Dashboard producer/creator
- `CONSUMER` - Dashboard consumer
- `STAKEHOLDER` - Other stakeholder

## Glossary Terms

### Adding Terms

```java
dashboard.addTerm("urn:li:glossaryTerm:ExecutiveMetrics");
dashboard.addTerm("urn:li:glossaryTerm:BusinessIntelligence");
```

### Removing Terms

```java
dashboard.removeTerm("urn:li:glossaryTerm:ExecutiveMetrics");
```

### Term Chaining

```java
dashboard.addTerm("urn:li:glossaryTerm:KeyPerformanceIndicator")
         .addTerm("urn:li:glossaryTerm:SalesMetrics")
         .addTerm("urn:li:glossaryTerm:RealTimeData");
```

## Domain

### Setting Domain

```java
dashboard.setDomain("urn:li:domain:Sales");
```

### Removing Domain

```java
// Remove a specific domain
dashboard.removeDomain("urn:li:domain:Sales");

// Or clear all domains
dashboard.clearDomains();
```

## Custom Properties

### Adding Individual Properties

```java
dashboard.addCustomProperty("team", "sales-operations");
dashboard.addCustomProperty("refresh_schedule", "hourly");
dashboard.addCustomProperty("data_source", "snowflake");
```

### Setting All Properties

Replace all custom properties:

```java
Map<String, String> properties = new HashMap<>();
properties.put("team", "business-intelligence");
properties.put("refresh_schedule", "real-time");
properties.put("access_level", "executive");

dashboard.setCustomProperties(properties);
```

### Removing Properties

```java
dashboard.removeCustomProperty("refresh_schedule");
```

## Reading Dashboard Metadata

### Get Title

```java
String title = dashboard.getTitle();
```

### Get Description

```java
String description = dashboard.getDescription();
```

## Lineage Operations

Dashboard lineage represents the data sources (datasets) that feed into the dashboard. This creates upstream lineage relationships from the dashboard to its source datasets.

### Adding Input Datasets

Add datasets one at a time:

```java
// Using DatasetUrn
DatasetUrn dataset = DatasetUrn.createFromString(
    "urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
);
dashboard.addInputDataset(dataset);

// Using string URN
dashboard.addInputDataset(
    "urn:li:dataset:(urn:li:dataPlatform:bigquery,marketing.campaigns,PROD)"
);
```

### Setting Input Datasets

Replace all input datasets at once:

```java
List<DatasetUrn> datasets = Arrays.asList(
    DatasetUrn.createFromString(
        "urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
    ),
    DatasetUrn.createFromString(
        "urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)"
    )
);

dashboard.setInputDatasets(datasets);
```

### Removing Input Datasets

```java
// Using DatasetUrn
DatasetUrn dataset = DatasetUrn.createFromString(
    "urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)"
);
dashboard.removeInputDataset(dataset);

// Using string URN
dashboard.removeInputDataset(
    "urn:li:dataset:(urn:li:dataPlatform:bigquery,marketing.campaigns,PROD)"
);
```

### Getting Input Datasets

Retrieve all input datasets:

```java
List<DatasetUrn> inputDatasets = dashboard.getInputDatasets();
for (DatasetUrn dataset : inputDatasets) {
    System.out.println("Dataset: " + dataset);
}
```

### Lineage Chaining

```java
dashboard.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.orders,PROD)")
         .addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,sales.customers,PROD)")
         .addInputDataset("urn:li:dataset:(urn:li:dataPlatform:salesforce,Account,PROD)");
```

## Chart Relationships

Chart relationships represent the visualizations embedded in a dashboard. This creates "Contains" relationships between the dashboard and its charts.

### Adding Charts

Add charts one at a time:

```java
// Using ChartUrn
ChartUrn chart = new ChartUrn("tableau", "revenue_chart");
dashboard.addChart(chart);

// Using string URN
dashboard.addChart("urn:li:chart:(looker,sales_performance_chart)");
```

### Setting Charts

Replace all charts at once:

```java
List<ChartUrn> charts = Arrays.asList(
    new ChartUrn("tableau", "revenue_chart"),
    new ChartUrn("tableau", "customer_satisfaction_chart"),
    new ChartUrn("tableau", "regional_breakdown_chart")
);

dashboard.setCharts(charts);
```

### Removing Charts

```java
// Using ChartUrn
ChartUrn chart = new ChartUrn("tableau", "revenue_chart");
dashboard.removeChart(chart);

// Using string URN
dashboard.removeChart("urn:li:chart:(looker,sales_performance_chart)");
```

### Getting Charts

Retrieve all charts:

```java
List<ChartUrn> charts = dashboard.getCharts();
for (ChartUrn chart : charts) {
    System.out.println("Chart: " + chart);
}
```

### Chart Chaining

```java
dashboard.addChart(new ChartUrn("looker", "revenue_chart"))
         .addChart(new ChartUrn("looker", "customer_chart"))
         .addChart(new ChartUrn("looker", "product_chart"));
```

## Dashboard-Specific Properties

### Dashboard URL

Set a direct link to the dashboard in its native BI tool:

```java
// Set dashboard URL
dashboard.setDashboardUrl("https://tableau.company.com/views/sales-dashboard");

// Get dashboard URL
String url = dashboard.getDashboardUrl();
```

### Last Refreshed

Track when the dashboard data was last updated:

```java
// Set last refreshed timestamp (milliseconds since epoch)
long currentTime = System.currentTimeMillis();
dashboard.setLastRefreshed(currentTime);

// Get last refreshed timestamp
Long lastRefreshed = dashboard.getLastRefreshed();
if (lastRefreshed != null) {
    System.out.println("Last refreshed at: " + new Date(lastRefreshed));
}
```

### Combined Dashboard Properties

```java
dashboard.setDashboardUrl("https://looker.company.com/dashboards/executive")
         .setLastRefreshed(System.currentTimeMillis());
```

## Complete Example

```java
import datahub.client.v2.DataHubClientV2;
import datahub.client.v2.entity.Dashboard;
import com.linkedin.common.OwnershipType;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

public class DashboardExample {
    public static void main(String[] args) {
        // Create client
        DataHubClientV2 client = DataHubClientV2.builder()
            .server("http://localhost:8080")
            .build();

        try {
            // Build dashboard with all metadata
            Dashboard dashboard = Dashboard.builder()
                .tool("looker")
                .id("sales_performance_dashboard")
                .title("Sales Performance Dashboard")
                .description("Executive dashboard showing key sales metrics and regional performance")
                .build();

            // Add tags
            dashboard.addTag("executive")
                     .addTag("sales")
                     .addTag("production");

            // Add owners
            dashboard.addOwner("urn:li:corpuser:sales_team", OwnershipType.BUSINESS_OWNER)
                     .addOwner("urn:li:corpuser:bi_team", OwnershipType.TECHNICAL_OWNER);

            // Add glossary terms
            dashboard.addTerm("urn:li:glossaryTerm:SalesMetrics")
                     .addTerm("urn:li:glossaryTerm:ExecutiveDashboard");

            // Set domain
            dashboard.setDomain("urn:li:domain:Sales");

            // Add custom properties
            dashboard.addCustomProperty("team", "sales-operations")
                     .addCustomProperty("refresh_schedule", "hourly")
                     .addCustomProperty("data_source", "snowflake");

            // Upsert to DataHub
            client.entities().upsert(dashboard);

            System.out.println("Successfully created dashboard: " + dashboard.getUrn());

        } catch (IOException | ExecutionException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
```

## Updating Existing Dashboards

### Load and Modify

```java
// Load existing dashboard
DashboardUrn urn = new DashboardUrn("looker", "my_dashboard");
Dashboard dashboard = client.entities().get(urn);

// Add new metadata (creates patches)
dashboard.addTag("new-tag")
         .addOwner("urn:li:corpuser:new_owner", OwnershipType.TECHNICAL_OWNER);

// Apply patches
client.entities().update(dashboard);
```

### Incremental Updates

```java
// Just add what you need
dashboard.addTag("real-time");
client.entities().update(dashboard);

// Later, add more
dashboard.addCustomProperty("updated_at", String.valueOf(System.currentTimeMillis()));
client.entities().update(dashboard);
```

## Builder Options Reference

| Method                  | Required | Description                                    |
| ----------------------- | -------- | ---------------------------------------------- |
| `tool(String)`          | ✅ Yes   | BI tool identifier (e.g., "looker", "tableau") |
| `id(String)`            | ✅ Yes   | Dashboard identifier within the tool           |
| `title(String)`         | No       | Dashboard title                                |
| `description(String)`   | No       | Dashboard description                          |
| `customProperties(Map)` | No       | Map of custom key-value properties             |

## Patch-Based Operations

Dashboard uses patch-based updates for metadata operations. All methods like `addTag()`, `addOwner()`, etc. create patches that are accumulated until `upsert()` or `update()` is called.

**Benefits:**

- **Efficient**: Multiple operations batched into fewer API calls
- **Atomic**: All changes succeed or fail together
- **Incremental**: Only specified fields are modified, others remain unchanged

**Example:**

```java
Dashboard dashboard = Dashboard.builder()
    .tool("tableau")
    .id("sales_dashboard")
    .build();

// These create patches (no API calls yet)
dashboard.addTag("production");
dashboard.addOwner("urn:li:corpuser:owner", OwnershipType.BUSINESS_OWNER);
dashboard.setDomain("urn:li:domain:Sales");

// Single API call emits all patches
client.entities().upsert(dashboard);
```

## Common Patterns

### Creating Multiple Dashboards

```java
List<String> dashboardIds = Arrays.asList("dashboard1", "dashboard2", "dashboard3");

for (String dashboardId : dashboardIds) {
    Dashboard dashboard = Dashboard.builder()
        .tool("looker")
        .id(dashboardId)
        .title("Dashboard " + dashboardId)
        .build();

    dashboard.addTag("auto-generated")
             .addCustomProperty("created_by", "sync_job");

    client.entities().upsert(dashboard);
}
```

### Batch Metadata Addition

```java
Dashboard dashboard = Dashboard.builder()
    .tool("tableau")
    .id("executive_dashboard")
    .build();

List<String> tags = Arrays.asList("executive", "kpi", "real-time", "production");
tags.forEach(dashboard::addTag);

client.entities().upsert(dashboard);  // Emits all tags in one call
```

### Conditional Metadata

```java
if (isExecutiveDashboard(dashboard)) {
    dashboard.addTag("executive")
             .addTerm("urn:li:glossaryTerm:ExecutiveMetrics");
}

if (requiresGovernance(dashboard)) {
    dashboard.addOwner("urn:li:corpuser:governance_team", OwnershipType.DATA_STEWARD);
}
```

### Dashboard with Full Lineage Context

```java
// Create dashboard with rich metadata
Dashboard dashboard = Dashboard.builder()
    .tool("looker")
    .id("customer_360_dashboard")
    .title("Customer 360 Dashboard")
    .description("Comprehensive customer analytics dashboard")
    .build();

// Add business context
dashboard.addTerm("urn:li:glossaryTerm:CustomerAnalytics")
         .addTerm("urn:li:glossaryTerm:BusinessIntelligence")
         .setDomain("urn:li:domain:Customer");

// Add input datasets for lineage
dashboard.addInputDataset("urn:li:dataset:(urn:li:dataPlatform:snowflake,customer.profile,PROD)")
         .addInputDataset("urn:li:dataset:(urn:li:dataPlatform:salesforce,Account,PROD)")
         .addInputDataset("urn:li:dataset:(urn:li:dataPlatform:zendesk,Tickets,PROD)");

// Add embedded charts
dashboard.addChart(new ChartUrn("looker", "customer_segmentation_chart"))
         .addChart(new ChartUrn("looker", "lifetime_value_chart"))
         .addChart(new ChartUrn("looker", "support_tickets_chart"));

// Add operational metadata
dashboard.addCustomProperty("data_sources", "snowflake,salesforce,zendesk")
         .addCustomProperty("refresh_schedule", "every_15_minutes")
         .addCustomProperty("sla_tier", "tier1")
         .addCustomProperty("business_criticality", "high");

// Set dashboard properties
dashboard.setDashboardUrl("https://looker.company.com/dashboards/customer-360")
         .setLastRefreshed(System.currentTimeMillis());

// Add ownership and governance
dashboard.addOwner("urn:li:corpuser:product_team", OwnershipType.BUSINESS_OWNER)
         .addOwner("urn:li:corpuser:bi_team", OwnershipType.TECHNICAL_OWNER)
         .addTag("production")
         .addTag("customer-facing");

client.entities().upsert(dashboard);
```

## Comparison with Chart Entity

Dashboard and Chart are similar but serve different purposes:

| Feature          | Dashboard                     | Chart                     |
| ---------------- | ----------------------------- | ------------------------- |
| Purpose          | Collection of visualizations  | Single visualization      |
| URN Pattern      | `(tool,id)`                   | `(tool,id)`               |
| Patch Operations | ✅ Full support               | ✅ Full support           |
| Common Use Cases | Executive dashboards, reports | Individual graphs, charts |

## Next Steps

- **[Chart Entity Guide](./chart-entity.md)** - Working with chart entities
- **[Dataset Entity Guide](./dataset-entity.md)** - Working with dataset entities
- **[Patch Operations](./patch-operations.md)** - Deep dive into patches
- **[Migration Guide](./migration-from-v1.md)** - Upgrading from V1

## Examples

### Basic Dashboard Creation

```java
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardCreateExample.java show_path_as_comment }}
```

### Comprehensive Dashboard with Metadata

```java
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardFullExample.java show_path_as_comment }}
```

### Dashboard with Lineage and Relationships

```java
{{ inline /metadata-integration/java/examples/src/main/java/io/datahubproject/examples/v2/DashboardLineageExample.java show_path_as_comment }}
```
