# Object Model Extensibility

Type definitions provide a data structure for all types of data that you are moving through the various resources of the ABB Ability™ Platform. It makes your data follow a specified contract, which in most of the cases is a good thing. However, in some specific situations you might want to extend what your contract/type defines to include a new parameter. Object model extensibility allow that functionality. To configure the extensibility functionality, or determine if the type you are planning to use is extensible, you should ensure that the isExtensible property is set to true in your type definition, like in the example below:

  "model" : "myModel",
  "typeId" : "myType",
  "version" : "1.0.0",
  "isExtensible" : true

An object model that is an instance of an extensible type definition is allowed to define additional information. These new properties can be any of the following:

  • Properties
  • Variables
  • Methods
  • Attributes

These new properties follow the same syntax and must adhere to the same rules as the existing properties from the original type definition to be considered valid and accepted by the platform. The new properties for an extensible type defined in an object model must also adhere to the same rules laid out for type inheritance.

# Extending a Type Definition

A series of Ability API endpoints exist to facilitate the creation, updates, and retrieval of type extensions in the platform. The technical details of those APIs can be found by following the above link. The following content will show examples of usage for these APIs.

# Create A New Type Extension

This is a PUT endpoint that requires the object model objectId and the model definition modelId:

PUT /objects​/{objectId}​/models​/{modelId}​/extension

Let's start with a very basic type definition that is marked as extensible:

{
  "typeId": "myType",
  "version": "1.0.0",
  "model": "myModel",
  "isExtensible": true,
  "properties": {
    "length": {
      "dataType": "integer"
    }
  }
}

Now that you have an extensible type definition, let's look at an example object model payload that does not extend the type yet. You would first create this object model with the POST /objects endpoint like the one shown below, but that is beyond the scope of this article, please find directions for that in the type definition overview article.

{
  "objectId": "ec9581d3-8ff6-4542-85b1-059db23242d5",
  "type": "myType@1",
  "model": "myModel",
  "properties": {
    "length": {
      "value": 775
    },
  }
}

You can then make a call to the PUT /objects​/{objectId}​/models​/{modelId}​/extension endpoint to extend the type definition associated with this object model with the new elements by copying the objectId and modelId into the endpoint URL. Keep in mind that the extended type and the new elements defined in this API request will only be available for this single, specified object model. In case default values are added in extension, then they should be updated in the respective object model on PUT /objects/{objectId}/models/{modelId}/

Please note that only a partial payload is allowed for this endpoint. None of the type definition root properties (objectId, type, model, isExtensible, etc.) or the relatedModels and references sections can be changed or extended through this endpoint.

PUT /objects/ec9581d3-8ff6-4542-85b1-059db23242d5/models/myModel/extension

{
  "properties": {
    "velocity": {
      "dataType": "string"
    },
    "width": {
      "dataType": "integer",
      "value": 30
    }
  }
}

With this successful request made above, the stored extension will look like this in the database:

{
  "Type": "myType@1",
  "ObjectId": "ec9581d3-8ff6-4542-85b1-059db23242d5",
  "Model": "myModel",
  "Version": 10,
  "LastModified": "2019-07-16T08:17:05Z",
  "properties": {
    "width": {
      "dataType": "integer",
      "value": 30
    },
    "velocity": {
      "dataType": "string"
    }
  }
}

NEW EXTENSION VERSIONS

Newer extensions do not have to be backwards compatible with older versions. The updates made from this endpoint are only validated with the type definition and the latest extension.

If the object model already has a type extension then a new version of the extension is created and designated as the current extension for this object model. The older version is maintained and can be accessed through one of the other endpoints. All historical extensions are preserved within the platform storage resources for telemetry checking purposes.

These object model extensions are all stored in the type definition database for retrieval. The extended object models are validated twice, once before they are saved, and then once again when they are stored in the database.

DELETED TYPES

It is possible to create extensions for objects of soft-deleted types!

# Semantic Versioning Impact

Since only types that are configured to be extensible via the isExtensible property are able to be extended semantic versioning is not applicable to extended object models and their types. The version for the extended type and object model will only increase the major version value. Typedefinitions with “isExtensible”: true can now be updated with minor and patch versions for some components and attributes. The version for the extended type and object model will follow the rules while updating the semantic version of isExtensible TypeDefinition

S.No Scenario Version Required
1 Addition of optional property Major
2 Addition of mandatory property Major
3 Deletion of a property Major
4 Adding the default value of the optional or mandatory property Patch
5 Changing the default value of the optional or mandatory property Minor
6 Adding/Changing description Patch
7 Adding / Changing tag of global or property level Minor
8 Changing datatype of a property Major

Example Consider the following examples of valid and invalid scenarios for extensible typedefinition version upgrade

Type definition:

{
  "typeId": "motor",
  "version": "1.0.0",
  "model": "abb.ability.device",
  "isExtensible": true,
  "properties": {
    "length": {
      "dataType": "integer"
    }
  }
}

# Valid Scenarios

1.Adding/Updating the description of the property requires a patch update

Type definition:

{
  "typeId": "motor",
  "version": "1.0.1", //patch update
  "model": "abb.ability.device",
  "isExtensible": true,
  "properties": {
    "length": {
      "dataType": "integer",
      "description": "Length of model"
    }
  }
}

2.Adding the default value in a property requires a patch update

Type definition:

{
  "typeId": "motor",
  "version": "1.0.2", //patch update
  "model": "abb.ability.device",
  "isExtensible": true,
  "properties": {
    "length": {
      "dataType": "integer",
      "description": "Length of model",
      "value":10
    }
  }
}

3.Updating the default value, and tag of the property requires a minor update

Type definition:

{
  "typeId": "motor",
  "version": "1.1.2", //minor update
  "model": "abb.ability.device",
  "isExtensible": true,
  "tags":["global length"],
  "properties": {
    "length": {
      "dataType": "integer",
      "description": "Length of model",
      "tags":["length"],
      "value":20
    }
  }
}

# Failed Validations

During the second validation step when the extended object model is being saved to the database the operation will either be successful and say so accordingly, or it will fail. When the validation fails, it indicates that the object model was either:

  • updated concurrently with another extension update or object model/type update and is no longer compatible with the object model/type.
  • The target extension or object model/type was removed from the database and no longer exists.

The API will return a 409 error in this case indicating that a conflict exists and needs to be resolved in the new extension update.

# Retrieving An Extended Object Model

Get specific version endpoint deprecated

As of 20.09 Platform release the endpoint to retrieve a specific extension version has been deprecated and not replaced. If pinged it will return a 404 error.

To see what this extension looks like together with the original type definition you can call the GET /objects/{objectId} endpoint and make a request for the holistic view of the type by setting the isHolistic query parameter to true as seen below.

GET /objects/ec9581d3-8ff6-4542-85b1-059db23242d5?isHolistic=true

{
  "Type": "myType@1",
  "ObjectId": "ec9581d3-8ff6-4542-85b1-059db23242d5",
  "Model": "myModel",
  "Version": 10,
  "LastModified": "2019-07-16T08:17:05Z",
  "properties": {
    "length": {
      "dataType": "integer",
      "value": 775
    },
    "velocity": {
      "dataType": "string"
    },
    "width": {
      "dataType": "integer",
      "value": 30
    }
  }
}

The object model will then reflect all the elements of its original type (properties: length with value 775) and the extension (properties: velocity, width with value 30) together in one complete object model. This consolidation can be understood by this equation representation: orignal type definition + type extension.

# Get The Latest Object Model Extension

This is a GET endpoint that will retrieve only the latest version of the object model extension associated with the given object model objectId you request.

GET ​/objects​/{objectId}​/models​/{modelId}​/extension

You can request the extension for the model you created above. All we need to do this is pass the object model objectId and the model definition modelId through to the endpoint for the object model of interest.

GET /objects/ec9581d3-8ff6-4542-85b1-059db23242d5/models/MyModel/extension

This request will return ONLY the latest type extension for the specified object model based on whichever extension has the most recent version number as seen below.

The version number will only increment if changes occur to the extension in a PUT request. If multiple PUT requests are made to the same type extension but no changes exist in the payload, the version number will not change.

{
  "Type" : "myType@1",
  "ObjectId" : "ec9581d3-8ff6-4542-85b1-059db23242d5",
  "Model" : "myModel",
  "Version": 11, //indicates an incremented change
  "LastModified" : "2019-07-16T08:17:05Z",
  "properties": {
    "length": {
      "dataType": "integer",
      "value": 775
    },
    "velocity": {
      "dataType": "string"
    },
    "width": {
      "dataType": "integer",
      "value": 30
    }
  }
}

If we try requesting the same object model from IM service GET object model endpoint, we will not receive the extension information. Only the model values from the original type definition.

GET /objects/ec9581d3-8ff6-4542-85b1-059db23242d5/models/MyModel

{
  "Type": "myType@1",
  "ObjectId": "ec9581d3-8ff6-4542-85b1-059db23242d5",
  "Model": "myModel",
  "Version": 10,
  "LastModified": "2019-07-16T08:17:05Z",
  "properties": {
    "length": {
      "dataType": "integer",
      "value": 775
    }
  }
}

Make sure to ping the extension endpoint to get the extension information or perform a holistic GET request as outlined above.

# Deleting An Object Model Extension

If you have reached the point where an object model extension is no longer useful to you for any reason, you would want ot use the DELETE extension endpoint. Requests to this endpoint will completely remove the extension from the specified object model from the database. The endpoint accepts the objectId and modelId parameters to identify the extension of interest.

DELETE /objects/{objectId}/models/{modelId}/extension

Also, if an object model is deleted all or its extensions will be dropped accordingly.

# Deleted Original Object Models

Keep in mind that if an original object model is deleted all it's extensions will subsequently be deleted as well. They will no longer be accessible.

# Invalid Extensions

There are a handful of rules to keep in mind when building a type extension to ensure your extension will be accepted by the platform. If you are experiencing any errors check to see if you may have neglected to abide by these rules:

  • The type definition is not designed to be extensible, "isExtensible" = false
  • The object model you are requesting must have an extension otherwise you will get a 404 error
  • Type's references and relatedModels sections can not be part of an extension
Last updated: 7/26/2024, 7:00:24 AM
Feedback