Ramandeep Singh Nanda
Published

Fri 04 January 2013

←Home

Target Reconciliation Scheduler in OIM 11g

In this post i am sharing the process to make your own custom reconciliation connector. The process flow of the scheduler is shown in the below flowchart.

customtargetreconciliation

This flow chart is a simplified version and should serve as a simple aid. The code for the 11g scheduler is shown below, it is a pretty crude implementation and just serves as a POC it does a full target reconciliation.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
public class UserDetailReconTask extends TaskSupport {
    private static final ADFLogger reconLogger =
        ADFLogger.createADFLogger(UserDetailReconTask.class);

    public UserDetailReconTask() {
        super();
    }


    public void execute(HashMap hashMap) {
        String methodName =
            Thread.currentThread().getStackTrace()[1].getMethodName();
        tcITResourceInstanceOperationsIntf itRes =
            Platform.getService(tcITResourceInstanceOperationsIntf.class);
        reconLogger.entering(methodName, hashMap.toString());
        //get it resourcename
        String itResourceName = hashMap.get("ITResource").toString();
        //Get resource object to reconcile
        String resourceObjectName = hashMap.get("ResourceObject").toString();
        //Get table name
        String tableName = hashMap.get("TableName").toString();
        HashMap hashmap = new HashMap();
        if (reconLogger.isLoggable(Level.INFO)) {
            reconLogger.info("[ " + methodName + " ] " +
                             "Got It Resource name " + itResourceName);
        }
        hashmap.put("IT Resources.Name", itResourceName);
        tcResultSet rss;
        tcResultSet parameters;
        HashMap paramsMap = new HashMap();
        try {
            rss = itRes.findITResourceInstances(hashmap);
            Long ll = rss.getLongValue("IT Resource.Key");

            parameters = itRes.getITResourceInstanceParameters(ll);
            for (int i = 0; i < parameters.getRowCount(); i++) {
                parameters.goToRow(i);
                String paramName =
                    parameters.getStringValue("IT Resources Type Parameter.Name");
                if (paramName.trim().equalsIgnoreCase("DatabaseName")) {
                    paramsMap.put("DatabaseName",
                                  parameters.getStringValue("IT Resource.Parameter.Value"));
                } else if (paramName.trim().equalsIgnoreCase("URL")) {
                    paramsMap.put("URL",
                                  parameters.getStringValue("IT Resource.Parameter.Value"));
                } else if (paramName.trim().equalsIgnoreCase("UserID")) {
                    paramsMap.put("UserID",
                                  parameters.getStringValue("IT Resource.Parameter.Value"));
                } else if (paramName.trim().equalsIgnoreCase("Password")) {
                    paramsMap.put("Password",
                                  parameters.getStringValue("IT Resource.Parameter.Value"));
                } else if (paramName.trim().equalsIgnoreCase("Driver")) {
                    paramsMap.put("Driver",
                                  parameters.getStringValue("IT Resource.Parameter.Value"));
                }
            }
        } catch (tcAPIException e) {
            reconLogger.severe("[ " + methodName + " ] " +
                               "error occured during retrieving IT Resource",
                               e);
            throw new RuntimeException("[ " + methodName + " ] " +
                                       "error occured during retrieving IT Resource");
        } catch (tcColumnNotFoundException e) {
            reconLogger.severe("[ " + methodName + " ] " +
                               "error occured during retrieving IT Resource column name",
                               e);
            throw new RuntimeException("[ " + methodName + " ] " +
                                       "error occured during retrieving IT Resource column name");
        } catch (tcITResourceNotFoundException e) {
            reconLogger.severe("[ " + methodName + " ] " +
                               "error occured during retrieving IT Resource by key",
                               e);
            throw new RuntimeException("[ " + methodName + " ] " +
                                       "error occured during retrieving IT Resource by key");
        }
        reconcileAndCreateEvents(paramsMap.get("UserID").toString(),
                                 paramsMap.get("Password").toString(),
                                 paramsMap.get("Driver").toString(),
                                 paramsMap.get("URL").toString(),
                                 resourceObjectName, tableName);

        reconLogger.exiting("UserDetailReconTask", methodName);
    }

    public HashMap getAttributes() {
        return null;
    }

    public void setAttributes() {
    }


    /**
     * This method gets the data from the source table and then creates the events after
     * that OIM applies the rules to check whether the user is there or not
     * @param adminID Source admin user id
     * @param password Source Password
     * @param Driver Driver type
     * @param Url jdbc url of the target database
     * @param resourceObject target resource object
     * @param tableName The target table to reconcile from
     */
    private void reconcileAndCreateEvents(String adminID, String password,
                                          String Driver, String Url,
                                          String resourceObject,
                                          String tableName) {
        String methodName =
            Thread.currentThread().getStackTrace()[1].getMethodName();
        reconLogger.entering("UserDetailReconTask", methodName);
        ResultSet rs = null;
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            Class.forName(Driver);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Unable to find the driver class", e);
        }
        try {
            tcReconciliationOperationsIntf reconService =
                Platform.getService(tcReconciliationOperationsIntf.class);
            HashMap dataMap = new HashMap();
            conn = DriverManager.getConnection(Url, adminID, password);
            ps = conn.prepareStatement("Select * from "+ tableName);
            rs = ps.executeQuery();
            reconLogger.info("[ " + methodName + " ] " +
                             "Executed the query succesfully");
            while (rs.next()) {
                //put data in map
                dataMap.put("UserLogin", rs.getString(1));
                //create reconciliation event
                reconLogger.info("[ " + methodName + " ] " + "Got login Id ",
                                 rs.getString(1));
                try {
                    //create reconciliation event
                    reconService.createReconciliationEvent(resourceObject,
                                                           dataMap, true);
                    reconLogger.info("[ " + methodName + " ] " +
                                     "Created Recon Event", rs.getString(1));

                } catch (tcObjectNotFoundException e) {
                    reconLogger.severe("Unable to find resource object");
                    throw new RuntimeException("Unable to find the driver class",
                                               e);
                } catch (tcAPIException e) {
                    reconLogger.severe("Unable to find resource object");
                    throw new RuntimeException("Unable to createevent", e);
                }
            }

        } catch (SQLException e) {
            throw new RuntimeException("Unable to get connection", e);
        }
    }
}


Here the method of relevance is reconcileAndCreateEvent which actually fetches the details from the target table name and then it is being used to populate a dataMap with reconciliation field names and value, this along with the resource object name is being used to create the reconciliation event which in turn is then processed by OIM Reconciliation engine which finds a reconciliation rule corresponding to the resource object and then applies the rule, in this case UserLogin is matched with User_Login in OIM and the account linking is performed.


The reconciliation API reference link is here.


The scheduler xml is shown below. It is named as UserDetailReconTask.xml and needs to be imported into mds using weblogicImportMetada.sh script.The  path needs to be /db/UserDetailReconTask.xml


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<scheduledtasks xmlns="http://xmlns.oracle.com/oim/scheduler">
<task>
<name>UserDetailReconTask</name>
<class>com.blogspot.ramannanda.schedulers.UserDetailReconTask</class>
<description>Target Reconciliation</description>
<retry>5</retry>
<parameters>
<string-param required="true" encrypted="false" helpText="IT Resource">ITResource</string-param>
<string-param required="true" encrypted="false" helpText="Resource Object name">ResourceObject</string-param>
<string-param required="true" encrypted="false" helpText="Table Name">TableName</string-param>
</parameters>
</task>
</scheduledTasks>

The plugin xml is mentioned below


1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<oimplugins>
<plugins pluginpoint="oracle.iam.scheduler.vo.TaskSupport">
<plugin pluginclass="com.blogspot.ramannanda.schedulers.UserDetailReconTask" version="1.0" name="TrustedSourceReconciliation"/>
</plugins>
</oimplugins>

Note: The actual implementations should filter the data from the target for performance by using something like last modified timestamp.

Go Top
comments powered by Disqus