cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Leveraging the custom object in IdentityIQ

Leveraging the custom object in IdentityIQ

 

Overview

Often times it is necessary to create a mapping of keys to values in IdentityIQ. While most of IdentityIQ's data models are fairly flexible and allow attributes to be placed on them; other needs can arise to have these data structures exist independently of other objects. Fortunately, in IdentityIQ this is possible through usage of the Custom object.

 

What is a custom object?

Simply put, it is a simple object that has an attribute map, which can be serialized / deserialized into IdentityIQ.  This is an example of what one looks like:

 

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE Custom PUBLIC "sailpoint.dtd" "sailpoint.dtd">

<Custom name="Some Custom Object">

  <Attributes>

    <Map>

      <entry key="someKey1" value="someValue"/>

      <entry key="someKey2">

        <value>

          <List>

            <String>listValue1</String>

            <String>listValue2</String>

            <String>listValue3</String>

          </List>

        </value>

      </entry>

      <entry key="someKey3">

        <value>

          <Boolean>true</Boolean>

        </value>

      </entry>

    </Map>

  </Attributes>

</Custom>

 

You can create these structures in XML outside of IdentityIQ and import them into the system.  Once they are there they can be used by rules, workflows, or even custom code.

 

How do I interact with these in the API?

Example 1: Getting a Custom object.

 

Custom custom = context.getObject( Custom.class, "Some Custom Object" );

 

System.out.println( custom.toXml() );

 

Example 2: Updating a Custom object.

 

// See if there is already a custom object, and lock it if there is.

Custom custom = (Custom) ObjectUtil.lockObject(

     context, // SailPointContext              

     Custom.class, // Object Class - Custom.class in our case

     null, // The object ID in String form

     "Some Custom Object", // The object Name in String form

     PersistenceManager.LOCK_TYPE_TRANSACTION  // The type of lock we want - either persistent or transaction. 

     );

 

// There was not a Custom object already in the database, let's create a new one.

if ( custom == null ) {

  custom = new Custom();

  custom.setName( "Some Custom Object" );

}

 

// Now add some attributes:

custom.put( "someKey1", "someValue" );

custom.put( "someKey2", Arrays.asList( new String[] {"listValue1", "listValue2", "listValue3"} ) );

custom.put( "someKey3", true );

 

// Do more stuff...

 

// Save it and commit it.

context.saveObject( custom );

context.commitTransaction();

 

System.out.println( custom.toXml() );

 

Thats it! Enjoy your new found flexibility with the custom object!

 

Note: Keep in mind that these are objects stored in the database. Most times when you look up or edit these objects will result in additional call(s) to the database. Use your best judgement when to utilize these API calls to avoid any potential self-inflicted performance issues.

Labels (2)
Comments

Hi Neil McGlennon,

Could you explain a bit more about the differences between the Custom object and the Configuration object? The JavaDocs already explain that they are quite similar and something about name clashes and being exportable. I also notice that Configuration implements sailpoint.object.Cachable, while Custom does not. Does that mean that Custom is less efficient than Configuration when it is retrieved multiple times?

Thanks,

Menno

Structurally, the Custom object and the Configuration object are fairly similar.  It is a separate namespace that won't be affected.  It is bad practice to put implementation into Configuration objects, as this could be affected by patches, upgrades, etc.   From a best practice standpoint, leave Configuration objects to SailPoint, and leverage Custom objects to implementation.

Great Feature to know of....Thanks Neil

Neil,

Thanks for the great article.  In your example you show locking the Custom object.  Does the Custom object support locking?  In our tests in 6.1p2 it doesn't seem to prevent the updating of a Custom object that has been locked.

Thanks,

Scott

Scott Frederick

There are actually two types of locking done by IdentityIQ, and a good description can be found in the JavaDocs for the PersistenceManager interface:

LOCK_TYPE_TRANSACTION

static final java.lang.String LOCK_TYPE_TRANSACTION

A value for the LOCK_TYPE option that selects a transaction lock.

A transaction lock is held only for the duration of the current transaction, it corresponds to a Hibernate fetch with LockMode.UPGRADE, which in turn corresponds to a SQL select with the "for update" option.

If another transaction has locked this object, the calling thread will suspend until the other transaction completes (or the request times out).

This type of lock is appropriate for internal background tasks that need exclusive access to an object for a short duration and don't need the overhead of a persistent lock.

LOCK_TYPE_PERSISTENT

static final java.lang.String LOCK_TYPE_PERSISTENT

A value for the LOCK_TYPE option that selects a persistent lock.

A persistent lock is an application-level locking convention that uses a special column in the object table to indicate the lock status. A persistent lock may span transactions.

Persistent locks are appropriate if you need to lock an object for a long period of time, or keep an object locked accross a transaction boundary.

This type of lock is most appropriate for editing sessions in the UI. Because it must modify the locked object it has more overhead than a transaction lock which makes it less suitable for background tasks that scan many objects.

Basically, the only type of lock that is relevant for a Custom object is the transactional lock.  The Custom object does not support a persistent lock, as you will notice there is no "iiqlock" column in the database like there is for Identity objects.

Make sense?

If an edit is made and saved to the custom object at runtime through the GUI debug pages, is this reflected immediately for all objects that use it?

Yes, ignoring any caching, it should be.

Hello,

I know this is an old post, but I still have a small question about it. After locking the object with a transaction type lock does the "context.commitTransaction" do the unlocking of the object for you? Thanks.

David,

As long as you have a transactional lock (See PersistenceManager.LOCK_TYPE_TRANSACTION), once you commit the transaction, it releases the lock.

Thanks for providing information on how to update XML.  How does one read the contents of your XML data that's provided?  Get the value for someKey1, someKey2, someKey3?  What if there was one more level under someKey1 like subsomeKey1?  Get the values of "Administrators" in the example below?

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE Custom PUBLIC "sailpoint.dtd" "sailpoint.dtd">

<Custom name="Some Custom Object">

  <Attributes>

    <Map>

      <entry key="someKey1">

        <value>

          <Map>

            <entry key="subsomeKey1">

              <value>

                <Attributes>

                  <Map>

                    <entry key="Administrators" value="Elevated"/>

                    <entry key="Domain Admins" value="Elevated"/>

                    <entry key="Enterprise Admins" value="Elevated"/>

                  </Map>

                </Attributes>

              </value>

            </entry>

          </Map>

        </value>

      </entry>

    </Map>

  </Attributes>

</Custom>

Version history
Revision #:
2 of 2
Last update:
‎Jun 28, 2023 02:07 PM
Updated by:
 
Contributors