Virtual properties
Properties can be derived from other properties within an object. This lets computed and composite values be created in the object. Such derived properties are named virtual properties. The value of a virtual property can be calculated in two ways:
-
Using a script called by the
onRetrieve
script hook. This script then calculates the current value of the virtual property based on the related properties. -
Using a query to identify the relationship fields to traverse to reach the managed objects whose state is included in the virtual property, and the fields in these managed objects to include in the value of the virtual property.
These properties are called relationship-derived virtual properties.
Virtual properties using onRetrieve
scripts
The onRetrieve
script hook lets you run a script when the object is retrieved. In the case of virtual properties, this script gets the data from related properties and uses it to calculate a value for the virtual property. For more information about running scripts on managed objects, refer to Run scripts on managed objects.
Relationship-derived virtual properties
Virtual properties can be calculated by IDM based on relationships and relationship notifications. This means that, rather than calculating the current state when retrieved, the managed object that contains the virtual property is notified of changes in a related object, and the virtual property is recalculated when this notification is received. To configure virtual properties to use relationship notifications, there are two areas that need to be configured:
-
The related managed objects must be configured to use relationship notifications. This lets IDM know where to send notifications of changes in related objects.
-
To calculate the value of a virtual property, you must configure which relationships to check, and in which order, a notification of a change in a related object is received. You configure this using the
queryConfig
property.
The queryConfig
property tells IDM the sequence of relationship fields it should traverse in order to calculate (or recalculate) a virtual property, and which fields it should return from that related object. This is done using the following fields:
-
referencedRelationshipFields
is an array listing a sequence of relationship fields connecting the current object with the related objects you want to calculate the value of the virtual property from. The first field in the array is a relationship field belonging to the same managed object as the virtual property. The second field is a relationship in the managed object referenced by the first field, and so on.For example, the
referencedRelationshipFields
foreffectiveAssignments
is["roles","assignments"]
. The first field refers to theroles
relationship field inmanaged/user
, which references themanaged/role
object. It then refers to theassignments
relationship inmanaged/role
, which references themanaged/assignment
object. Changes to either related object (managed/role
ormanaged/assignment
) will cause the virtual property value to be recalculated, due to thenotify
,notifySelf
, andnotifyRelationships
configurations on managed user, role, and assignment. These configurations ensure that any changes in the relationships between a user and their roles, or their roles, and their assignments, as well as any relevant changes to the roles or assignments themselves, such as the modification of temporal constraints on roles, or attributes on assignments, will be propagated to connected users, so theireffectiveRoles
andeffectiveAssignments
can be recalculated and potentially synced. -
referencedObjectFields
is an array of object fields that should be returned as part of the virtual property. If this property is not included, the returned properties will be a reference for the related object. To return the entire related object, use*
. -
flattenProperties
is a boolean that specifies whether relationship-derived virtual properties should be returned as plain fields rather than as JSON objects with an_id
and a_rev
. This property isfalse
by default.With
flattenProperties
set tofalse
, andreferencedObjectFields
set toname
, the response to a query on a user’seffectiveAssignments
might look something like this:"effectiveAssignments": [ { "name": "MyFirstAssignment", "_id": "02b166cc-d7ed-46b7-813f-5ed103145e76", "_rev": "2" }, { "name": "MySecondAssignment", "_id": "7162ddd4-591a-413e-a30b-3a5864bee5ec", "_rev": "0" } ]
With
flattenProperties
set totrue
, andreferencedObjectFields
set toname
, the response to the same query looks like this:"effectiveAssignments": [ "MyFirstAssignment", "MySecondAssignment" ]
Setting
flattenProperties
totrue
also lets singleton relationship-derived virtual properties be initialized tonull
.
Using queryConfig
, the virtual property is recalculated when it receives a notice that changes occurred in the related objects. This can be significantly more efficient than recalculating whenever an object is retrieved, while still ensuring the state of the virtual property is correct.
When you change which fields to return using |
The effectiveAssignments
property in managed.json
is an example of a relationship-derived virtual property:
"effectiveAssignments" : {
"type" : "array",
"title" : "Effective Assignments",
"description" : "Effective Assignments",
"viewable" : false,
"returnByDefault" : true,
"isVirtual" : true,
"queryConfig" : {
"referencedRelationshipFields" : [ "roles", "assignments" ],
"referencedObjectFields" : [ "*" ]
},
"usageDescription" : "",
"isPersonal" : false,
"items" : {
"type" : "object",
"title" : "Effective Assignments Items"
}
}
Enhanced signal propagation
By default, managed objects won’t receive relationship graph topology change signals unless the managed objects have defined a relationship-derived-virtual-property
whose state is derived from the graph topology corresponding to the signal.
If graph topology signaling configurations are motivated by requirements other than the correct calculation of relationship-derived virtual properties, you can disable the signal-routing logic in the SignalPropagationCalculator
class that is active by default.
To disable the signal-routing logic, you can set disable.signal.propagation.calculator=true
in revolver/boot.properties
or in system.properties
.
Disabling the routing logic in the |