Monday Apr 28, 2014

OIM11gR2: How to handle child data in a custom ICF connector

This blog entry explains how to perform child table operations in custom ICF connector code.This blog does not explains in detail about how to write ICF connectors. This is just to help set up and perform child table operations through ICF.  

We will only discuss here what APIs to use to perform child table operations in your custom ICF code. Second section of this blog entry will discuss a typical requirement of setting up reconciliation for a resource with multi-column child table through custom ICF. 

SECTION 1 - Child table operation APIs in custom ICF connector

We may want to perform different provisioning operations such as add, remove, update on a child table through our custom ICF code.  

Operation Add/ Remove operations on child table:

To perform child table operations in custom ICF connector, you need to implement UpdateAttributeValuesOp interface in your connector code. The methods addAttributeValues & removeAttributeValues deal with adding and removing child table data.

addAttributeValues(objectClass, uid, attributes, operationOptions);

removeAttributeValues(objectClass, uid, attributes, operationOptions);

Here one should note that, UpdateOp is used for updating only Parent form attributes. To handle parent form updates & child form creation/updation/deletion we have to implement both the interfaces i.e., UpdateOp and UpdateAttributeValuesOp.

UpdateOp interface:

UpdateAttributeValuesOp interface:

Update operations on child table:

1)     You may have a question as to "How is update to childtable data handled in ICF"? This is how it works :-

        When child table row is updated, OIM triggers removeAttributeValues(oldValue) followed by addAttributeValues(newValue) in the connector.

  Now how do we pass values to following methods:

public String addChildTableValue(String objectType, String childTableName, long childPrimaryKey)

public String removeChildTableValue(String objectType, String childTableName, Integer taskInstanceKey)

 Here, objectType will be User, ChildTableName should be the name of child table process form of your implementation and refer below images for mapping childPrimaryKey and taskInstanceKey:

 childPrimaryKey Mapping

taskInstanceKey Mapping

Using above information you can perform different provisioning operations on child table through custom ICF connector code.

SECTION 2:  Setting up reconciliation for Multi-column child table in custom ICF connector

We often see requirements where multi-column child data has to be processed using custom ICF. We had a requirement where we were required to reconcile a resource with more than one column in its child form.

 We could not find enough information about how to achieve this in any of the blogs/ product documentation or even training docs. Training guide, though talks about Flat file custom ICF with child table, but that only is for child tables which have single column. 

 Handling multi-column child table in custom ICF is different from how you would see for single-column in lab guides or product documentation ( Developer guide: 

Below is what was done in our case:

Requirement: To Provision and Reconcile multi column child table data using custom ICF

Below is how the parent and child form data looked in our case:

Child table Data Reconciliation Implementation:

 The recon lookup for our implementation was set up as below:

  1. Recon Lookup :

 2.  Apart from implementing  addAttributeValues & removeAttributeValues methods in your code, you also need to have executeQuery(), schema(), getEmbeddedObjAttributeInfo() and addAttrInObjClass() methods in your custom ICF code.

Below is the code snippet of different methods that we implemented for child table:

Here,  APPS = ‘apps’ and APPLICATIONS = ‘Applications’  (from lookup entry above) in the code below.

‘Applications’ and ‘UserName’ in getEmbeddedObjAttributeInfo method are the child table columns

   3.  Below is the snippet from executeQuery method for child table data wrapping

Here too,  APPS = ‘apps’ and APPLICATIONS = ‘Applications’  (from lookup entry above) in the code below.

4.  Below is how we had set up Reconciliation Field Mapping in Process Definition:

Monday Nov 19, 2012

How do you test an ICF based connector using Connector Facade Standalone?

The following code helps in writing a standalone java program to test an ICF based connector. The sample code in this example takes into account an ICF based flatfile connector. It is possible to test various operations like create, update, delete, search etc... It is also possible to set values to the connector configuration parameters, add/remove attributes and their values.

public class FlatFile {

private static final java.lang.String BUNDLE_NAME = "<PACKAGE_NAME>";


private static final java.lang.String BUNDLE_VERSION = "1.0.0";

private static final java.lang.String CONNECTOR_NAME = "";

// Name of connector class i.e. the class implemting the connector SPI operations

public ConnectorFacade getFacade() throws IOException {

ConnectorInfoManagerFactory fact = ConnectorInfoManagerFactory


File bundleDirectory = new File("<BUNDLE_LOCATION>");

//Ex: /usr/oracle/connector_bundles/

URL url = IOUtil.makeURL(bundleDirectory,


ConnectorInfoManager manager = fact.getLocalManager(url);

ConnectorKey key = new ConnectorKey(BUNDLE_NAME, BUNDLE_VERSION,


ConnectorInfo info = manager.findConnectorInfo(key);

// From the ConnectorInfo object, create the default APIConfiguration.

APIConfiguration apiConfig = info.createDefaultAPIConfiguration();

// From the default APIConfiguration, retrieve the

// ConfigurationProperties.

ConfigurationProperties properties = apiConfig


// Print out what the properties are (not necessary)

List propertyNames = properties.getPropertyNames();

for (String propName : propertyNames) {

ConfigurationProperty prop = properties.getProperty(propName);

System.out.println("Property Name: " + prop.getName()

+ "\tProperty Type: " + prop.getType());





// Set all of the ConfigurationProperties needed by the connector.

// properties.setPropertyValue("host", FOOBAR_HOST);

// properties.setPropertyValue("adminName", FOOBAR_ADMIN);

// properties.setPropertyValue("adminPassword", FOOBAR_PASSWORD);

// properties.setPropertyValue("useSSL", false);

// Use the ConnectorFacadeFactory's newInstance() method to get a new

// connector.

ConnectorFacade connFacade = ConnectorFacadeFactory.getInstance()


// Make sure we have set up the Configuration properly


return connFacade;


public static void main(String[] args) throws IOException {

FlatFile file = new FlatFile();

ConnectorFacade cfac = file.getFacade();

Set attrSet = new HashSet();

attrSet.add(, "Test01"));

attrSet.add("FIRST_NAME", "Test_First"));

attrSet.add("LAST_NAME", "Test_Last"));


Uid uid = cfac.create(ObjectClass.ACCOUNT, attrSet, null);


Uid uidP = new Uid("Test01");

cfac.delete(ObjectClass.ACCOUNT, uidP, null);




OIM11gR2 Blog by NA-TAG Offshore IDAM team


« March 2015