Wednesday, 4 April 2018

OIM Certification Entity Details using SQL

Using SQL query you can find the details of certification entity by providing certification id as input. There are 3 different queries for Application Instance, Entitlement and Role.

OIM does have certification APIs for getting the entity details from certification id like:

CertificationService -> getIDCEntitlementsByBatch
CertificationService -> getIDCRolesByBatch
CertificationService -> getIDCApplicationInstancesByBatch

But many occasion, these APIs create problem during execution.

Below are the sample queries, which can easily replace the above APIs:

----------------------------------- Entitlement Certification --------------------------------------
SELECT
cert_certs.id AS certification_id,
cert_certs.cert_name AS certificationname,
certs_ent_defn.attr_value AS attribute_value,
certd_ent_defn.glossary_def AS name,
          certd_ent_defn.entity_id AS entitlement_entity_id
FROM
certd_ent_defn certd_ent_defn
INNER JOIN cert_certs cert_certs
ON certd_ent_defn.cert_id = cert_certs.id
INNER JOIN certs_ent_defn certs_ent_defn
ON certd_ent_defn.attr_val_id = certs_ent_defn.id
WHERE
         cert_certs.id = [CERT_ID]

------------------------------------ Application Instance Certification ------------------------
SELECT
certd_app_inst.cert_id AS certification_id,
certs_app_inst.iam_endpoint_id AS applicationid,
certs_app_inst.endpoint_name AS application_name
FROM
certs_app_inst, certd_app_inst,
cert_certs 
WHERE
cert_certs.id = certd_app_inst.cert_id 
AND certs_app_inst.id = certd_app_inst.endpoint_id 
        AND cert_certs.id=[CERT_ID]

------------------------------------------ Role Certification --------------------------------------
SELECT
cert_certs.id AS certification_id,
certs_role.rolename,
certs_role.entity_display_name
FROM
certs_role, certd_role,
cert_certs 
WHERE
cert_certs.id = certd_role.cert_id 
AND certd_role.role_id = certs_role.id
AND  cert_certs.id = [CERT_ID]

Thursday, 22 March 2018

Developing SOA custom escalation task

In this blog I am going the describe how to write a custom escalation task for SOA human Task.

Normally SOA human task does have predefined escalation process to Manager, Director and CEO. Where escalation task will be automatically assigned to the one of the specified Role.

In case of OIM workflow, only Manager role is defined. Some time we have requirements to escalate workflow task to any other user or role and the same is not supported by the composite. So we have to write our own custom escalation task.

Below are the steps to create a new escalation task.

1. In JDeveloper, create a new Generic Project CustomEscalator.
2. Create a java class named CustomEscalator under the below package

           oracle.bpel.services.workflow.assignment.dynamic

     Note: use the above package only.

3. Add the below library to the project classpath
                    BPEL Runtime
                    BPEL Services
                    BPM Workflow

4. Open the CustomEscalator class and implements IDynamicTaskEscalationPattern.



5. Override the method getTaskEscalationUser(Task task) with your own logic and return the escalation manager's user login.


6. Once the code is complete, compile and create a jar file (simple jar file).
7. transfer the jar file to [SOA_HOME]/soa/modules/oracle.soa.ext_11.1.1 directory.
8. set CLASSPATH=$CLASSPATH:[MW_HOME]/modules/net.sf.antcontrib_1.1.0.0_1-0b2/lib/ant-contrib.jar
9. set PATH=$PATH:[MW_HOME]/modules/org.apache.ant_1.7.1/bin
10. set ANT_HOME=[MW_HOME]/modules/org.apache.ant_1.7.1
11. run "ant -buildfile build.xml" *


12. Open the EM console.
13. Right click on soa-infra and select SOA Administration -> Workflow Properties




14. Click on  and Add a new function.
15. Provide the below parameters:

        Function Name: CustomEscalator
        Classpath: oracle.bpel.services.workflow.assignment.dynamic.CustomEscalator



16. Click Ok and Apply.
17. In the SOA composite, open the HumanTask .task file.
18. Go to the Deadlines.
19. Clear the Highest Approver Title field.
20. Update "CustomEscalator" to the Custom Escalation Java Class.
21. Provide the duration of the escalation as required. (for testing i used 1 min).


22. Save and Deploy the composite.
23. Restart the SOA managed servers.
24. Test the functionality.


-------------------------------------------------------------------------------------------------------------
*While ANT building if you face the below error message, then perform the activity as mentioned:

Error: 
        oracle.soa.ext_11.1.1\build.xml:41: Problem: failed to create task or type if

Solution:
Modify the build.xml as below

 locate this line:
    <if>
        <equals arg1="${Extension-Name}" arg2="oracle.soa.workflow.wc" />

and replace it with:
    <!--
    <if>
        <equals arg1="${Extension-Name}" arg2="oracle.soa.workflow.wc" />

Locate this line:
      <else>
      <jar destfile="${library.path}"
                update="yes" >

and modify it to
      <else>
      -->
      <jar destfile="${library.path}"
                update="yes" >

Locate this line:
        </else>
    </if>

and modify it to:
        <!--
        </else>
    </if>        
        -->

OIM Plugins auto registration

In OIM, we register plugins for event handler, request data validator etc. We generally copy the plugin zip file contains the jar and plugin.xml, and then we register it manually.

OIM also provided a feature to register the plugin automatically after copying the OIM_HOME/server/plugin folder.

Here are the details of auto-registration process of plugin.


Export the oim-config.xml file.

1. login to weblogic EM console
2. Go to Identity and Access -> OIM -> oim(11.1.2.0.0)
3. Right click on it and click System MBean Browser.
4. Now go the below location





5. Click on the MDSAppRuntime.
6. provide toLocation as /tmp
7. provide docs as /db/oim-config.xml


8. once done click on Invoke
9. check on the /tmp location of the respective server (if select oim server1 then check on the oim1 unix server).

10. a directory named db created, under which you will find oim-config.xml


Modify the oim-config.xml

1. open the oim-config.xml in edit mode.
2. Search for the tag pluginConfig



3. Modify the the value of reloadEnabled and relodaInterval accordingly.
                    reloadEnabled=true means auto registration allowed.
                    reloadInterval=20 means auto registration will occured every 20 sec.

4. After changing the value save the change and close the editor.


Import the modified oim-config.xml

1. 1. login to weblogic EM console
2. Go to Identity and Access -> OIM -> oim(11.1.2.0.0)
3. Right click on it and click System MBean Browser.
4. Now go the same location as export.
5. Select importMetadata, and provide fromLocation and docs as below (same as export).


6. Once done click on Invoke.
7. Restart the oim managed servers.

Wednesday, 21 February 2018

Using GuardedString in OIM custom code.

It was observed in several cases, where we write custom java code for OIM (adapter, event handler, UI code , scheduler etc) with password as string value. If we store the password as java.lang.String, it is kept in memory as a clear text password and stays in memory at least until it is garbage collected. Code reviewer will always reject such code, if they find any password as java.lang.String.

GuardedString class can eliminate this problem by storing the password as characters in memory in an encrypted form. The encryption key will be a randomly-generated key. In their serialized form, Guarded String will be encrypted using a known default key. This is to provide a minimum level of protection regardless of the transport. For communications with the Remote Connector Framework it is recommended that deployments enable SSL for true encryption.

In this example I will explained how you can use Guarded String in OIM custom code.

GuardedString class is the member of  org.identityconnectors.common.security package and can be found in framework-1.3.2.jar. That means in your java project you have to import framework-1.3.2.jar as a library.


Below code sample describe how to store string password in GuardedString.

import org.identityconnectors.common.security.GuardedString;

String password = "abcd1234";
char[] passwordToChar = password.toCharArray();
GuardedString guardedPassword = new GuardedString(passwordToChar);


Below code sample describe how to get the password from GuardedString

          guardedPassword.access(new GuardedString.Accessor() {
                        @Override
                        public void access(char[] clearChars) {
                            System.out.println( "String password::::::::::::::::::::::::"+new String(clearChars)); //print the password.
                            
                        }
                    });
            retrivePassword.dispose(); // dispose the GuardedString after use.


it is always better to dispose the GuardedString after authentication operation is done using dispose() method.



Friday, 9 February 2018

Read OIM ITResource parameter using API

In this blog I am going to explain how to read the OIM IT Resource parameter using API. Here is the code sample you can use to fetch any available IT resource parameter in your java code.


public void getITResourceParameter(String ITResourceName) throws NumberFormatException, tcAPIException, Exception {

final String methodName = "::getITResourceParameter::";
System.out.println("start execution of CallStoredProcedureForDBAT::"+methodName);

Map phAttributeList = new HashMap();
phAttributeList.put("IT Resources.Name", ITResourceName);

HashMap paramMap = new HashMap();

tcITResourceInstanceOperationsIntf ITResourceAPI = (tcITResourceInstanceOperationsIntf)oimClientObj.getService(tcITResourceInstanceOperationsIntf.class);
tcResultSet itresSet = ITResourceAPI.findITResourceInstances(phAttributeList);
itresSet.goToRow(0);
String ITResourceKey = itresSet.getStringValue("IT Resources.Key");
System.out.println("ITResourceKey::"+ITResourceKey);
tcResultSet paramValuesRS = ITResourceAPI.getITResourceInstanceParameters(Long.parseLong(ITResourceKey));

for(int j=0;j<paramValuesRS.getTotalRowCount();j++){

paramValuesRS.goToRow(j);

paramMap.put(paramValuesRS.getStringValue("IT Resources Type Parameter.Name"), paramValuesRS.getStringValue("IT Resources Type Parameter Value.Value"));

}

adminName = (String) paramMap.get("principal"); // "principal" is the IT Resource attribute name
adminPassword = (String) paramMap.get("credentials"); // "credentials" is the IT Resource attribute name
ldapPort = (String) paramMap.get("port"); //"port" is the IT Resource attribute name
HostName = (String) paramMap.get("host"); //"host" is the IT Resource attribute name
searchBase = (String) paramMap.get("baseContexts"); //"baseContexts" is the IT Resource attribute name

System.out.println("adminName ::"+adminName);
System.out.println("adminPassword ::"+adminPassword);
System.out.println("HostName ::"+HostName);
System.out.println("ldapPort ::"+ldapPort);
System.out.println("searchBase ::"+searchBase);

}

Friday, 26 January 2018

Trigger SOA workflow from java

In this blog I am going to explain how SOA workflow can be triggered from Java application. SOA workflow contains BPEL process and Human Task. BPEL process initiate the workflow and complete the workflow, where as Human Task represent the action of the workflow like assigning task for approval. From java based application, we can call the BPLE process to initiate the workflow. While calling the BPEL process, we have to provide input as payload. In this example, I am explaining the one way calling of SOA composite, where Java will only call the workflow, but will not expect any return.

Before proceed with the development work, some constraints need to be followed.

1. Usually BPEL process is linked with WebService binding exposed service. If we need to call the composite from java, we need to add Direct Binding service. But we also have to make sure that Direct Binding service is not feeding the payload data to BPEL process. Here is the section we need to add in composite.xml

1. Click on the Exposed Service and click on Insert
2. Select Direct Binding


3. Give a name (e.g. DService1).
4. Select the WSDL same as the web service binding (e.g. ManualAction.wsdl in my example).
5. Choose the port type as the non-callback service (e.g. ManualAction in my example).
6. Choose the Callback Port Type as callback service (e.g. ManualActionCallback.wsdl in my example).
7. Click ok to create the binding.


8. Once the Direct Binding is created, it will look something like below:


9. Now, you have to make the wiring so that Direct binding will point to the Web Service binding. Below xml tag needs to be added in the composite.xml

   <wire>
    <source.uri>DService1</source.uri>
    <target.uri>ManualAction/manualaction_client</target.uri>
  </wire>



   After adding the wire, it should looks like below
 10. Now you can modify the BPEL file according to your business case. Here in this example I have added a Human Task named ManualActionUser.



11. Now the SOA composite is ready. We have to create a java call for this composite.
12. Create a simple java project and below libs to the classpath

Febric-common.jar
Soa-infra-mgmt.jar
Wsclient-extended.jar
Wlfulclient.jar
Common-logging.jar


13. Use the below code to a new class file.

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.naming.Context;
import oracle.soa.api.JNDIDirectConnectionFactory;
import oracle.soa.api.PayloadFactory;
import oracle.soa.api.XMLMessageFactory;
import oracle.soa.api.invocation.DirectConnection;
import oracle.soa.api.invocation.DirectConnectionFactory;
import oracle.soa.api.message.Message;
import oracle.soa.api.message.Payload;
import oracle.xml.parser.v2.XMLPrintDriver;
import org.xml.sax.InputSource;

public class TestWF1 {
    public TestWF1() {
        super();
    }
    
    public static void main(String[] args) throws Exception {
        String operation = "process";

        // This is the request message XML
        String ns = "http://xmlns.oracle.com/TestWLWS/ManualAction/ManualAction";
        String payloadXML = "<process anualaction="" estwlws="" http:="" xmlns.oracle.com="" xmlns="\">" +
                            "<oldvalue>1</oldvalue>" +
                            "<newvalue>Testing</newvalue>" +
                            "<approverusername>REQUAP9</approverusername>" +
                            "<approverrolename>2</approverrolename>" +
                            "<workflowrequired>3</workflowrequired>" +
                            "<processinstancekey>4</processinstancekey>" +
                            "<targetprocesstaskname>5</targetprocesstaskname>" +
                            "<currentprocesstaskinstancekey>6</currentprocesstaskinstancekey>" +
                            "<applicationname>7</applicationname>" +
                            "<beneficiaryuserlogin>8</beneficiaryuserlogin>" +
                            "<beneficiaryuserkey>123654789</beneficiaryuserkey>" +
                            "<processformfieldname>10</processformfieldname>" +
                            "</process>"; 

        String serviceAddress = "soadirect:/default/ManualAction!1.0/DService1";

        // Specify the direct binding connection properties
        Map<string object=""> props = new HashMap<string object="">();
        props.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
        props.put(Context.PROVIDER_URL, "t3://" + "localhost" + ':' + "8001");
        props.put(Context.SECURITY_PRINCIPAL,"weblogic");
        props.put(Context.SECURITY_CREDENTIALS, "Welcome1");

        // Create the direct binding connection, using those context properties
        DirectConnectionFactory factory = JNDIDirectConnectionFactory.newInstance();
        DirectConnection dc = null;
        try {
           dc = factory.createConnection(serviceAddress, props);
            
            oracle.xml.parser.v2.DOMParser op = new oracle.xml.parser.v2.DOMParser();
            op.parse(new InputSource(new StringReader(payloadXML)));
            XMLPrintDriver pd = new XMLPrintDriver(System.out);
            pd.setFormatPrettyPrint(true);
            pd.printDocument(op.getDocument());
            
            Map partData = new HashMap();
            partData.put("payload", op.getDocument().getDocumentElement());
            Payload payload = PayloadFactory.createXMLPayload(partData); 
            
            Message request = XMLMessageFactory.getInstance().createMessage();
            request.setPayload(payload); 
            
            String uuid = "uuid:" + UUID.randomUUID(); 
            System.out.println("uuid = "+ uuid); 
            request.setProperty(request.CONVERSATION_ID, uuid); 
            dc.post("process", request); 

        } catch(Exception e){
            e.printStackTrace();
        }finally {
            dc.close();
        }
    }

}

14. After running the code check from the Weblogic EM console, by checking in instance of the composite


Friday, 1 December 2017

Change SOA Human Task email header

I am writing this blog to show how Email subject header can be change for a SOA human task. I believe you have observed, that when human task is assigned to any approve, email message header contains "Action Required". If you need to change this to any other value, you cannot do it from composite level. By default all this header values are coming from bpm-services.jar file, which can be find from [SOA_HOME]/soa/modules/oracle.soa.workflow_11.1.1

If you want to change this default header value with some other, you have to make a custom bundle. Follow the below steps to create a custom bundle for email header modification:

1. Copy the bpm-services.jar from [SOA_HOME]/soa/modules/oracle.soa.workflow_11.1.1 to /tmp location
2. Unjar the contents and copy the "oracle\bpel\services\workflow\resource" directory to a seperate location.
3. Make sure that you are maintaining the same directory structure as mentioned above.
4. Under the "oracle\bpel\services\workflow\resource" directory, delete i18NUtil.class file.
5. Change the appropriate properties file according to your need and language supports.
6. For example I need to change the email subject header "Action Required" with "Need your Attention", so I will change the value of TASK_VIEW_CONTEXT_ASSIGNEE_ASSIGNED attribute in WorkflowLabels.properties and WorkflowLabels_en.properties.
7. Once you are done with your changes, make a jar file of "oracle\bpel\services\workflow\resource" directory. in my case it is custombundle.jar
8. Copy the jar to any shared location.
9. Now you have to change the SOA MBean properties "WorkflowCustomClasspathURL" with the path of the bundle jar.
10. You cane do the change using two methods a) Using EM console UI, b) Using WLST command

Changing "WorkflowCustomClasspathURL" using EM console UI
1. Open EM console.
2. Expand SOA, and right click on soa-infra and select Administration->System MBean Browser.
3. Navigate to oracle.as.soainfra.config->Server:[SERVER_NAME]->WorkflowConfig->human-workflow.
4. Click on the human-workflow and change the value of WorkflowCustomClasspathURL with bundle jar filepath.
5. Once done click on Apply.
6. No restart required.



Changing "WorkflowCustomClasspathURL" using WLST command
1. Run [OIM_HOME]/common/bin/wlst.sh
2. Enter the WLST command as bellow:

 wls:/offline> connect('$WL_USER', '$WL_PASSWORD', '$SOA1_URL[t3://localhost:8001]')
 wls:/iam/serverConfig> custom()
 wls:/iam/custom> cd ('oracle.as.soainfra.config:name=human-workflow,type=WorkflowConfig,Application=soa-infra')
 wls:/iam/custom/oracle.as.soainfra.config/oracle.as.soainfra.config:name=human-workflow,type=WorkflowConfig,Application=soa-infra> set('WorkflowCustomClasspathURL','file://FILE_PATH//')
 wls:/iam/custom/oracle.as.soainfra.config/oracle.as.soainfra.config:name=human-workflow,type=WorkflowConfig,Application=soa-infra> disconnect()
 wls:/offline> exit()

Now you can see the email header has been changed with your defined value.

Followers

OIM API for adding process task and retry failed task

 In this blog you can find how to add new process task and retry any failed/rejected tasks using API. Adding new process task: /************...