Fixing a pain in the neck with an OIM API – Generic Class

In my early days of playing with OIM’s API, I quickly discovered the cumbersome process of constantly changing your code between your development environment and OIM.

***NOTE: As with all Tips and Tricks we provide on the IDMWorks blog, use the following AT YOUR OWN RISK.  We do not guarantee this will work in your environment and make no warranties***

In my early days of playing with OIM’s API, I quickly discovered the cumbersome process of constantly changing your code between your development environment and OIM.

I use Eclipse for my Java development and I really enjoy the ability to run code right from Eclipse against OIM and to see the results in the console.  This saves me a tremendous amount of development time.  To run code in Eclipse you have to initialize your OIM connection differently than you would if that code was executed from an Adapter.  From Eclipse, you have to initialize  a new tcUtilityFactory passing it the username and password of the account you’re using to test (most likely, xelsysadm).  When you run your code from within OIM, you get your utility factories from the Database Reference object(tcDataProvider).  Thus, if you’re testing code in Eclipse, you have to change your code before exporting the JAR to OIM.  If you go back and forth enough times this will quickly become rather frustrating. So I decided to write a generic class template that doesn’t need this constant switch.

Here’s how it works:

Any time you need to perform an API function, you need to get a copy of that API’s utility, using the getUtility method of either Thor.API.tcUtilityFactory (if you’re executing remotely) or your tcDataProvider (if you’re executing within OIM).

My class has two constructors:

public Generic()


public Generic(tcDataProvider db)

When you run the code in Eclipse,  I create a new Generic() class.

When I create the adapter in OIM,  I use the second constructor and map the Adapter Reference -> Database Adapter object to the constructor’s input.

When I need an API utility object, I call my own getUtility() method which, based on the constructor used, grabs the utility from the correct place.

Here’s the code:

package OIM.Generic;
 //Generic Template class
 //Works both in local and remote environments (OIM and Eclipse)
 import java.util.Hashtable;
 import Thor.API.tcResultSet;
 import Thor.API.tcUtilityFactory;
 import Thor.API.Base.tcUtilityOperationsIntf;
 import Thor.API.Operations.tcUserOperationsIntf;
 import com.thortech.xl.crypto.tcCryptoUtil;
 import com.thortech.xl.crypto.tcSignatureMessage;
 import com.thortech.xl.dataaccess.tcDataProvider;
 import com.thortech.xl.util.config.ConfigurationClient;
 public class Generic {
 	boolean local = false;
 	tcDataProvider db;
 	tcUtilityFactory tcu;
 	public Generic(){
 	public Generic(tcDataProvider db){
 	private tcUtilityOperationsIntf getUtility(String s){
 		tcUtilityOperationsIntf result = null;
 			if (local){
 				return Thor.API.tcUtilityFactory.getUtility(db, s);
 				return tcu.getUtility(s);
 		}catch(Exception e){
 		return result;
 	public void test(){
 			tcUserOperationsIntf moUserUtility = (tcUserOperationsIntf) getUtility("Thor.API.Operations.tcUserOperationsIntf");
 			Hashtable mhSearchCriteria = new Hashtable();
 			mhSearchCriteria.put("Users.Key", "1");
 			tcResultSet moResultSet = moUserUtility.findUsers(mhSearchCriteria);
 			for (int i = 0; i < moResultSet.getRowCount(); i++) {
 				System.out.println(moResultSet.getStringValue("Users.User ID"));
 		}catch(Exception e){
 	private void initLocal(tcDataProvider db){
 		this.db = db;
 	private void initRemote(){
 		this.local = false;
 			ConfigurationClient.ComplexSetting config = ConfigurationClient.getComplexSettingByPath("Discovery.CoreServer");
 			final Hashtable env = config.getAllSettings();
 			tcu = new tcUtilityFactory(env, "xelsysadm","xelsysadm");
 		}catch (Exception e){
 	public static void main(String[] args) {
 		Generic api = new Generic();

As always, we at IDMWorks value our feedback and your ideas.  Feel free to sound off below or contact us here.