OIM 11g : Multi-thread approach for writing custom scheduled job

Posted by Saravanan V S on Oracle Blogs See other posts from Oracle Blogs or by Saravanan V S
Published on Thu, 29 Nov 2012 10:38:38 +0000 Indexed on 2012/11/29 11:15 UTC
Read the original article Hit count: 288

Filed under:

In this post I have shared my experience of designing and developing an OIM schedule job that uses multi threaded approach for updating data in OIM using APIs.  I have used thread pool (in particular fixed thread pool) pattern in developing the OIM schedule job. The thread pooling pattern has noted advantages compared to thread per task approach. I have listed few of the advantage here

·         Threads are reused
·         Creation and tear-down cost of thread is reduced
·         Task execution latency is reduced
·         Improved performance
·         Controlled and efficient management of memory and resources used by threads

More about java thread pool http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html

The following diagram depicts the high-level architectural diagram of the schedule job that process input from a flat file to update OIM process form data using fixed thread pool approach 

 

The custom scheduled job shared in this post is developed to meet following requirement

1)      Need to process a CSV extract that contains identity, account identifying key and list of data to be updated on an existing OIM resource account.

2)      CSV file can contain data for multiple resources configured in OIM

3)      List of attribute to update and mapping between CSV column to OIM fields may vary between resources

The following are three Java class developed for this requirement (I have given only prototype of the code that explains how to use thread pools in schedule task)

CustomScheduler.java - Implementation of TaskSupport class that reads and passes the parameters configured on the schedule job to Thread Executor class.

package com.oracle.oim.scheduler;

import java.util.HashMap;
import com.oracle.oim.bo.MultiThreadDataRecon;
import oracle.iam.scheduler.vo.TaskSupport;

public class CustomScheduler extends TaskSupport {

     public void execute(HashMap options) throws Exception {

            /*  Read Schedule Job Parameters */
            String param1 = (String) options.get(“Parameter1”);
            .
            int noOfThread = (int) options.get(“No of Threads”);
 
           .
            String paramn = (int) options.get(“ParamterN”);

/* Provide all the required input configured on schedule job to Thread Pool Executor implementation class like 1) Name of the file, 2) Delimiter 3) Header Row Numer 4) Line Escape character 5) Config and resource map lookup 6) No the thread to create */

new MultiThreadDataRecon(all_required_parameters, noOfThreads).reconcile();

      }

      public HashMap getAttributes() { return null; }

      public void setAttributes() {       }

}

MultiThreadDataRecon.java – Helper class that reads data from input file, initialize the thread executor and builds the task queue.

package com.oracle.oim.bo;

import <required file IO classes>;
import  <required java.util classes>;
import  <required OIM API classes>;
import <csv reader api>;

public class MultiThreadDataRecon {

 private int noOfThreads;
 private ExecutorService threadExecutor = null;

 public MetaDataRecon(<required params>, int noOfThreads)  {
      //Store parameters locally
      .
      .
      this.noOfThread = noOfThread;
 
}

       /**
       *  Initialize 
       */

 private void init() throws Exception {

      try {

            // Initialize CSV file reader API objects
            // Initialize OIM API objects
            /* Initialize Fixed Thread Pool Executor class if no of threads 
               configured is more than 1 */

            if (noOfThreads > 1) {
                  threadExecutor = Executors.newFixedThreadPool(noOfThreads);
            } else {
                  threadExecutor = Executors.newSingleThreadExecutor();
            }

            /* Initialize TaskProcess clas s which will be executing task 
               from the Queue */   

            TaskProcessor.initializeConfig(params);
      } catch (***Exception e) {
                  // TO DO
      }
 }

      /**
       *  Method to reconcile data from CSV to OIM
       */

public void reconcile() throws Exception {
       try {
            init();
            while(<csv file has line>){
                  processRow(line);
            }
            /* Initiate thread shutdown */
            threadExecutor.shutdown();
            while (!threadExecutor.isTerminated()) {
                // Wait for all task to complete.
            }
           } catch (Exception e) {
                  // TO DO
           } finally {
                  try {
                        //Close all the file handles
                  } catch (IOException e) {
                        //TO DO
                  }
            }
      }

      /**
       * Method to process 
       */

      private void processRow(String row) {
            // Create task processor instance with the row data 
            // Following code push the task to work queue and wait for next
               available thread to execute
            threadExecutor.execute(new TaskProcessor(rowData));

      }

}

TaskProcessor.java – Implementation of “Runnable” interface that executes the required business logic to update data in OIM.

package com.oracle.oim.bo;

import <required APIs>

class TaskProcessor implements Runnable {

      //Initialize required member variables
      /**
       * Constructor
       */
      public TaskProcessor(<row data>) {
            // Initialize and parse csv row
      }

      /*
      *  Method to initialize required object for task execution
      */
      public static void initializeConfig(<params>) {
            // Process param and initialize the required configs and object
      }    

      /*
       * (non-Javadoc)
       
       * @see java.lang.Runnable#run()
       */
           public void run() {
            if (<is csv data valid>){
                  processData();
            }
      }

 /**
  * Process the the received CSV input
  */

 private void processData() {

    try{

      //Find the user in OIM using the identity matching key value from CSV
      // Find the account to be update from user’s account based on account identifying key on CSV
      // Update the account with data from CSV
      }catch(***Exception e){
          //TO DO
      }

  }

}

© Oracle Blogs or respective owner

Related posts about /Oracle