Pages

Tuesday, December 25, 2012

Creating a TaskScheduler: OIM 11G Style...

With OIM 11G, the way we create scheduled tasks has changed drastically.

Now a scheduler task is a plugin, which has to first imported into OIM before it can created as a Scheduled Job in OIM console.

Though the steps are defined in the OIM Developers Guide, it could be difficult to get it done given the different tasks involved are given in separate sections. So here lets look at the steps involved in creating a scheduled task in OIM 11G.

1) Creating the Scheduler Metadata xml

While creating a scheduled task, we have to create a metadata xml file about the task, which holds the information about the scheduled task, like task name, class name, parameter, etc.

<scheduledTasks xmlns="http://xmlns.oracle.com/oim/scheduler">
<task>
<name>SampleScheduler</name>
<class>com.oim.SampleScheduler</class>
<description>List User Logins</description>
<retry>5</retry>
</task>
</scheduledTasks>

For more info about the XML structure, check the documentation here.

Make sure the file name is the same as the SchedulerName.

Create a folder of storing this xml, say SchedulerMetaData. in that folder create another folder "db". Place the xml file inside this folder.

Now we can import the xml file into the OIM MetaDataStore.

First export thr OIM_ORACLE_HOME
export OIM_ORACLE_HOME=/oracle/Middleware/Oracle_IDM1
Now change directory to $OIM_ORACLE_HOME/server/bin

Make some changes  to the weblogic.properties file.

# Weblogic Server Name on which OIM application is running 
wls_servername=oim_server1
# If you are importing or exporting any out of box event handlers, value is oim. 
# For rest of the out of box metadata, value is OIMMetadata. 
# If you are importing or exporting any custom data, always use application name as OIMMetadata.
application_name=OIMMetadata
# Directory location from which XML file should be imported.
# Lets say I want to import User.xml and it is in the location /scratc/asmaram/temp/oim/file/User.xml, 
# I should give from location value as /scratc/asmaram/temp/oim. Make sure no other files exist 
# in this folder or in its sub folders. Import utility tries to recursively import all the files under the 
# from location folder. This property is only used by weblogicImportMetadata.sh
metadata_from_loc=/oracle/SchedulerMetaData
# Directory location to which XML file should be exported to
metadata_to_loc=@metadata_to_loc
# For example /file/User.xml to export user entity definition. You can specify multiple xml files as comma separated values.
# This property is only used by weblogicExportMetadata.sh and weblogicDeleteMetadata.sh scripts
metadata_files=@metadata_files

Now run the weblogicImportMetadata.sh

While running provide the weblogic details.

Starting import metadata script .... 
Please enter your username :weblogic
Please enter your password :
Please enter your server URL [t3://localhost:7001] :
Connecting to t3://localhost:7001 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'oim_domain'.

Metadata should get imported successfully.


2) Creating the Java file

Now we can write the Scheduler Code. In OIM 11G, the scheduler task java code is slightly different. Here we extend the "oracle.iam.scheduler.vo.TaskSupport" class instead of the SchedulerBaseTask class.

package com.oim;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import oracle.iam.identity.usermgmt.api.UserManager;
import oracle.iam.identity.usermgmt.vo.User;
import oracle.iam.platform.Platform;
import oracle.iam.platform.entitymgr.vo.SearchCriteria;
import oracle.iam.platform.entitymgr.vo.SearchCriteria.Operator;
import oracle.iam.scheduler.vo.TaskSupport;
public class SampleScheduler extends TaskSupport {
@Override
public void execute(HashMap arg0) throws Exception {
UserManager usrMgr = Platform.getService(UserManager.class);
SearchCriteria sc = new SearchCriteria("User Login", "*", Operator.EQUAL);
Set<String> retAttrs = new HashSet<String>();
retAttrs.add("User Login");
List<User> users = usrMgr.search(sc, retAttrs, null);
for(User user : users){
System.out.println(user.getLogin());
}
@Override
public HashMap getAttributes() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAttributes() {
// TODO Auto-generated method stub
}
}

After writing the code, create a jar file of the class, either from eclipse or using the jar command.
We have to now create this into a plugin

Create a new folder for the plugin, say SampleScheduler. Create a folder named lib in it and place the jar file in it.

3) Create the Plugin xml file

Now we have to create a plugin.xml file, specifying the plugin class and pluginpoint.

Create a file named plugin.xml, in the SampleScheduler folder which we created earlier.

Add the following contents in the file.

<?xml version="1.0" encoding="UTF-8"?>
<oimplugins xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<plugins pluginpoint="oracle.iam.scheduler.vo.TaskSupport">
<plugin pluginclass= "com.oim.SampleScheduler"
version="1.0.1" name="SampleScheduler">
</plugin>
</plugins>
</oimplugins>
Now the folder should have the following structure.

./SampleScheduler/
                   plugin.xml
                   lib/
                        SampleScheduler.jar

Create a zip of this folder.


4) Registering the plugin

Now that we have the plugin zip file, we have to register it in OIM.

Change directory to $OIM_SERVER_HOME/server/plugin_utility

In the ant.properties, set the WLS_HOME and the OIM_HOME variable values.
Make sure the wlfullclient.jar is created in the weblogic server lib. Instructions for this can be found in my previous blog.

To register the plugin use the following command.
ant -f pluginregistration.xml register
Make sure ant is added into the PATH already. 

Provide the OIM server details when asked.

    [input] Enter the oim user id: 
xelsysadm
    [input]Enter the oim user password:  
    [input] Enter the server url [t3://<host>:<port>] :
t3://localhost:14000
    [input] Enter name (complete file name with path) of the plugin file: 
/oracle/SampleScheduler.zip
     [echo] 
     [echo] Plugin Registered
BUILD SUCCESSFUL

5) Creating Scheduled Job in OIM console

Login to OIM console.
Goto Advanced>System Management>Scheduler.
Click on the new Scheduled Job icon in the left panel.




In the "Task" field search for the new scheduled task we imported.


Fill the other details and Apply. 




The Scheduled Job is created!!!

Thursday, December 20, 2012

UserManager : Misc (Lock/Unlock/Disable/Enable)

Now lets look at the other important functionalities provided by the UserManager class.

1) Code

public void misc(OIMClient oimclient){
UserManager usrMgr = oimclient.getService(UserManager.class);
try {
usrMgr.lock("65", true, true);
usrMgr.unlock("65", false);
usrMgr.disable("65", false);
usrMgr.enable("65", false);
} catch (ValidationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserLockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchUserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessDeniedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserUnlockException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserDisableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserEnableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

2) Result

User is locked/unlocked/disabled/enabled as expected

3) JavaDoc

You can find more information about the UserManager class and its methods in the javadoc link.

Wednesday, December 19, 2012

UserManager : Delete User

1) Code

public void deleteUser(OIMClient oimclient){
UserManager usrMgr = oimclient.getService(UserManager.class);
try {
usrMgr.delete("65", false); // False because we used usr_key. Use true if using User Login
} catch (ValidationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserDeleteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchUserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessDeniedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

2) Result

User is marked deleted.

3) Alternate methods

    delete(java.util.ArrayList userIDs, boolean isUserLogin)

For bulk delete

delete(java.lanj.String attributeName, java.lang.Object attributeValue)

For delete based on condition.


Tuesday, December 18, 2012

UserManager : Modify User Code

We can now look into modifying existing users.

1) Code

public void modifyUser(OIMClient oimclient){
UserManager usrMgr = oimclient.getService(UserManager.class);
User user = new User("65"); //Pass the user_key while creating [Can be obtained using a search]
user.setAttribute("First Name", "APIUser_FName");
user.setAttribute("Last Name", "APIUser_LName");
try {
usrMgr.modify(user);
} catch (ValidationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserModifyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchUserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessDeniedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

2) Result



3) Alternates

usrMgr.modify("Email", "APIUSER1@MAIL.COM", user);

Where the first two parameters are the search condition. All users who satisfy the condition will be modified.


modify(java.util.ArrayList userIDs, java.util.HashMap args, boolean isUserLogin)

We can pass a list of userIds to be modified. 
The hashmap contains the attribute names and values to be modified.
isUserLogin should be set to true if the userIds list contains the User Logins, else use false if they are user key values.


Monday, December 17, 2012

UserManager : Search User Code

Now that we have created users, we can try to search for users.

1) Code

public void searchUser(OIMClient oimclient){
UserManager usrMgr = oimclient.getService(UserManager.class);
Set retAttrs = new HashSet();
retAttrs.add("First Name");
retAttrs.add("Last Name");
retAttrs.add("User Login");
SearchCriteria sc = new SearchCriteria("First Name", "*",Operator.EQUAL);  // Search can use wildcards
List<oracle.iam.identity.usermgmt.vo.User> userList;
try {
userList = usrMgr.search(sc, retAttrs, null);
for(oracle.iam.identity.usermgmt.vo.User user: userList){
System.out.println(user.getAttributes());
}
} catch (UserSearchException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessDeniedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

2) Result

Connected
{usr_key=1, User Login=XELSYSADM, Last Name=Administrator, First Name=System}
{usr_key=3, User Login=WEBLOGIC, Last Name=WEBLOGIC, First Name=WEBLOGIC}
{usr_key=4, User Login=OIMINTERNAL, Last Name=OIMINTERNAL, First Name=OIMINTERNAL}
{usr_key=65, User Login=APIUSER1@MAIL.COM, Last Name=APIUser1, First Name=APIUser1}
{usr_key=48, User Login=FNAME1_LNAME1@MAIL.COM, Last Name=LName123, First Name=FName123}
{usr_key=66, User Login=APIUSER0.APIUSER0@ORACLE.COM, Last Name=APIUser0, First Name=APIUser0}
{usr_key=67, User Login=APIUSER@MAIL.COM, Last Name=APIUser, First Name=APIUser}
Disconnected

3) Complex SearchCriteria

If there is a need to create complex searchCriteria, there is a way to combine searchCriteria as below:

SearchCriteria sc1 = new SearchCriteria("First Name", "*",Operator.EQUAL);
SearchCriteria sc2 = new SearchCriteria("Last Name", "*",Operator.EQUAL);
SearchCriteria sc = new SearchCriteria(sc1, sc2, Operator.AND);

UserManager : Create User Code

Lets start into more mainstream stuff.

We will look at the UserManager class which is used for the User operations. This is similar in operation with the tcUserOperationsIntf class, which is still present in 11G.

1) Creating a new Class for UserOperations



2) Writing code

package com.oim;
import oracle.iam.identity.exception.UserAlreadyExistsException;
import oracle.iam.identity.exception.UserCreateException;
import oracle.iam.identity.exception.ValidationFailedException;
import oracle.iam.identity.usermgmt.api.UserManager;
import oracle.iam.identity.usermgmt.vo.User;
import oracle.iam.platform.OIMClient;
import oracle.iam.platform.authz.exception.AccessDeniedException;

public class UserOperations {
public void createUser(OIMClient oimclient){
UserManager usrMgr = oimclient.getService(UserManager.class);
/*
* Mandatory fields are LastName, act_key, Role, Xellerate Type
*/
User user = new User(null); //Pass null while creating
user.setAttribute("First Name", "APIUser");
user.setAttribute("Last Name", "APIUser");
user.setAttribute("Email", "APIUser@mail.com");
user.setAttribute("act_key",1L); // Replace 1L with the organization key long value
user.setAttribute("Role","Full-Time");
user.setAttribute("Xellerate Type","End-User");
try {
usrMgr.create(user);
} catch (ValidationFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserCreateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AccessDeniedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
OIMConnect conn = new OIMConnect();
conn.connect();
UserOperations userOps = new UserOperations();
userOps.createUser(conn.client);
conn.disconnect();
}
}
 3) Output

User is created in OIM.



4) Possible errors


  • oracle.iam.identity.exception.ValidationFailedException: IAM-3050028:The mandatory attributes act_key were not provided.:act_key
    • act_key has net been set as attribute in the User object
  • oracle.iam.identity.exception.ValidationFailedException: IAM-3050028:The mandatory attributes [Role, Last Name, Xellerate Type] were not provided.:[Role, Last Name, Xellerate Type]
    • Mandatory attributes have not be given values


Saturday, December 15, 2012

Starting with the basics : Connecting and disconnecting

Lets start with the first and foremost thing anybody who is looking to write OIM API code will require to know: Connecting to and disconnecting from the OIM server.

We will also take a look at how to setup our eclipse project for developing OIM API code.

So lets begin...

1) Creating an eclipse project.



2) Setting up the project with required libraries
  • Extract the oimclient.zip file present in the $OIM_CLIENT_HOME/server/client/
  • It will have a oimclient.jar and a lib, conf, sample folders within the extracted folder
  • Copy the wlfullclient.jar from the $WL_HOME/server/lib into the lib folder of the extracted oimclient.zip
    • If wlfullclient is not present in the $WL_HOME/server/lib folder, you have to build it manually using the follo\wing command
      • cd $WL_HOME/server/lib
      • java -jar wljarbuilder.jar
      • The wlfullclient.jar is created now
  • Copy the oimclient.jar and the contents of the lib folder of the extracted oimclient.zip, including the wlfullclient.jar



3) Writing code




package com.oim;
import java.util.Hashtable;
import javax.security.auth.login.LoginException;
import oracle.iam.platform.OIMClient;

public class OIMConnect {
OIMClient client;
public void connect(){
System.setProperty("java.security.auth.login.config","<oimclient.zip extracted folder>/config/authwl.conf");
Hashtable oimenv= new Hashtable();
oimenv.put(OIMClient.JAVA_NAMING_FACTORY_INITIAL,"weblogic.jndi.WLInitialContextFactory" );
oimenv.put(OIMClient.JAVA_NAMING_PROVIDER_URL,"t3://<host>:<port>");
client= new OIMClient(oimenv);
try {
client.login("<Username>", "<Password>".toCharArray());
System.out.println("Connected");
} catch (LoginException e) {
e.printStackTrace();
}
}
public void disconnect(){
client.logout();
System.out.println("Disconnected");
}
public static void main(String[] args) {
OIMConnect oimConn = new OIMConnect();
oimConn.connect();
oimConn.disconnect();
}
}

4) Running and testing

         Test results:
Connected   
Disconnected
5) Possible errors
  • javax.security.auth.login.LoginException: unable to find LoginModule class: weblogic.security.auth.login.UsernamePasswordLoginModule
    • wlfullclient.jar is missing in the buildpath
  • javax.security.auth.login.LoginException: java.net.ConnectException: t3://localhost:14000: Destination unreachable; nested exception is: 
    • java.net.ConnectException: Connection refused; No available router to destination
    • OIM server is not up and running
    • hostname or port may be wrong

  • Exception in thread "main" java.lang.SecurityException: /oracle/Middleware/Oracle_IDM1/server1/config/authwl.conf (No such file or directory)
    • at com.sun.security.auth.login.ConfigFile.<init>(ConfigFile.java:110)
    • Wrong path specified for the authwl.conf file