Changes to Workspace Object Identification

This article was published on the 12th of January 2023.

In an upcoming release we will be making changes to how object IDs work in workspace hierarchies. This could be a breaking change for some of you, which is why we have prepared this short overview of what is going to happen and how you can mitigate any potential problems before they occur.

Are You Going to Be Affected by This Change?

You may be affected if you are using workspace hierarchies / a multitenant environment. You are more likely to be affected if you are using workspace hierarchies in combination with one or more of the following use cases:

  • Dashboard plugins
  • Custom GoodData.UI applications
    • Drilling
    • Dashboard embedding (selectors, commands)
  • Dashboards and Analytical Designer embedding using iframes (postMessages API)
    • Hiding filters via query parameter in Dashboards

What Is the Current State?

One object may be referenced using two different object IDs, depending on whether you are referencing the object from its native workspace or a child workspace.

For example, let’s say that in your workspace, which has an ID my_parent_workspace_id, you create a metric with an object ID my_metric_id. Next, let’s say that you create a child workspace that inherits the metric from the parent workspace. In your parent workspace, you will find the metric under the ID my_metric_id as expected, but in your child workspace, the metric will have a different ID that consists of the original object id, prefixed by the parent workspace id; So its ID will be my_parent_workspace_id:my_metric_id.

The problem with the current state is that if you are developing, for instance, a plugin that references my_metric_id, you need to also handle its my_parent_workspace_id:my_metric_id variant, if you want to run the same plugin in a child workspace. This is not developer friendly and makes maintaining workspace hierarchies and multitenancy needlessly complicated.

What Is Changing?

We will soon remove parent prefixes from all object IDs. Instead, every object now has a new metadata property called origin:

{
  "data": {
    …,
    "meta": {
      "origin": {
         “originType”: “NATIVE”|”PARENT”, 
         “originId”: STRING
      }
    },
  },
}

For details see the Workspace Object Identification article in our documentation.

The origin metadata will contain information on whether the object is inherited from a parent workspace, or whether it is native to the workspace. This will ensure that there is always a reliable way of checking whether an object is native to a given workspace, or whether it is inherited from a parent workspace (and thus, whether the restrictions that apply to inherited objects need to apply to this object or not, for instance).

But wait! What if you already have a metric with an object ID my_metric_id in my child workspace? In such a case we adopt a parent’s object wins strategy; If you use an id that is used for an object in both the parent and child workspaces, the object in the parent workspace will be referenced.

What Should You Do?

Backend: Find Overriding and Overridden Objects

Once the workspace prefix is removed there could be child workspaces with a local and inherited object with the same object type and ID, but the API will show only the parent one, because of the parent wins philosophy; Therefore you will only be able to access the top most parent one and the one defined lower in the hierarchy will be unreachable.

Affected objects are - logical (dataset, attribute, fact, label) and mainly analytics (analyticalDashboard, metric, …).

We are providing you with two new API endpoints:

  • /api/v1/action/workspaces/<workspaceId>/overriddenChildEntities

    List objects in child workspaces that were overridden by objects in the workspace <workspaceId>.

  • /api/v1/actions/workspaces/<workspaceId>/inheritedEntityConflicts

    List objects in parent workspaces that are overriding objects in the workspace <workspaceId>.

With these endpoints you can scan your workspace hierarchy for any conflicting objects that might share the same object type and ID. If none are found, great! You are off the hook! But if there are conflicts, you need to do some editing using declarative API.

To resolve the issue with clashing objects you have to use the declarative API. Depending on the shape of your hierarchy, you have to use the api for the whole organization, or all workspaces, or a single workspace - the analyticsModel or logicalModel. Once you have the document you must find the object with the clashing object ID and decide how to fix it; either change the object ID or delete the object altogether.

Before putting the declarative document back you have to ensure you have updated or removed all references to that object, which includes the free-from json content of analytics objects as json node { “id”: STRING, “type”: metric|dataset|... } and the MAQL expression of metrics {metric|dataset|.../<prefix?:identifier>}. Regarding the logical model, the clash might occur in dataset references and grain definition.

Frontend

After the change the backend will always return object IDs without any parent workspace prefixes. This means that every time your code uses an ID value to perform some client-only logic, it can potentially stop working. In the following sections, we describe the most notable cases that can be affected by this, but depending on your application/plugin logic, you may encounter other types of issues.

Drilling

If you use the identifierMatch or objRefMatch header predicates to specify your custom drills, they might stop working after the change goes live, if the ID you use references an object from a parent workspace. To mitigate this, use localIdentifierMatch or objMatch instead. If this is not feasible, you can either re-run the catalog-export tool or ensure that the ID value for the header predicate does not contain any workspace prefix.

Dashboard Plugins

Using object IDs to reference objects from a parent workspace may start to fail after the change goes live. To prevent this, try using alternative methods of referencing the objects, such as tags. If this is not feasible, you can either re-run the catalog-export tool or ensure that the ID value for the header predicate does not contain any workspace prefix.

isLocked Property

After the change goes live, applications and plugins using GoodData.UI versions older than 8.12.0 will show the isLocked property as always false on certain metadata objects. To address this, it is necessary to upgrade GoodData.UI to version 8.12.0 or newer.

When Is All of This Happening?

In the 15th of December 2022 release of GoodData Cloud, we have already rolled out the new origin property, as well as the API endpoints for listing conflicting objects. You can start using them now.

In GoodData.CN 2.3, and its corresponding GoodData Cloud release, we are rolling out checks to avoid storing any additional objects with clashing IDs. In the following release we will stop supporting prefixes in their current form altogether. These will be the potentially breaking changes.

Please note that the release schedule is subject to change. We will keep you informed in the release notes.

Future Plans

This is just a heads up that after the changes outlined in this article are finalized and released, we plan to implement something we call custom prefixes. This would be an optional feature which lets you define a prefix for all objects that are native to a given workspace; This way it is always going to be immediately clear what workspace any given object comes from. This feature should make working with objects across a workspace hierarchy even easier. Please note that at this point this is merely a planned feature and the details are subject to change.