Oracle Identity Manager UI Customizations

by Gaurav Singh

February 2014

Oracle Identity Manager UI Customizations

Tips, Tricks, and Technical Insight into Customizations for the Oracle Identity Manager User Interface

Introduction

Customizing Oracle Identity Manager's (OIM) self-service console ("ID Console") fulfills a number of business requirements, including:

  • Adding custom identity attributes to various screens
  • Creating/managing UI forms to fill in data when a user requests access over an enterprise resource
  • Displaying custom messages/banners on certain screens
  • Hiding certain UI controls from a specific set of users
  • Triggering custom validations when form data is submitted or a field value changes

In this article, we will look at some behind-the-scenes details about how OIM (in sync with some other components) achieves this flexibility on UI. It is assumed here that the reader is familiar with the basic functionality of OIM and has knowledge of various application development framework artifacts, like EO.xml, VO.xml, pageDef.xml, tf.xml, .jsff files and managed beans (mBeans). This article applies to OIM 11gR2 and above.

MDS-Based Customizations

Oracle Metadata Services (MDS) provides an upgrade-safe customization framework over XML files. Let's have a look at the example below to understand what that means:

Example:

Suppose an application provides the following OOTB XML document, with the path /metadata/sample-app-metadata.xmlmanaged by MDS.



<BaseDocument id="base">    
<TagA id="tagA" name="Sample Tag A" prop="30" />  
<TagB id="tagB" name="Sample Tag B" prop="25" /> 
<TagC id="tagC" name="Sample Tag C" prop="10" />  
</BaseDocument>

Now, if the application guarantees that this XML can be customized at runtime, it will provide two strings for that. A customization layer name ("site" in the case of OIM) and a layer value ("site" again for OIM). Using this, a customization XML file can be created in directory /metadata/mdssys/cust/<layer-name>/<layer-value>/sample-app-metadata.xml.xml (note the ".xml.xml" extension), as follows:



<mds:customization version="11.1.1.61.15" xmlns:mds="http://xmlns.oracle.com/mds">  
<mds:modify element="tagB">   
<!-MODIFYING PROP OF TAG-B TO 15 -->  
<mds:attribute name="prop" value="15"/> 
</mds:modify>  
<mds:insert parent="base" position="first">  
<!-INSERTING A CUSTOM ELEMENT AT THE BEGINNING OF ROOT TAG -->    
<Tag0 id="tag0" name="Custom Tag 0" prop="35" /> 
</mds:insert> 
</mds:customization>

At runtime, when the application now asks for sample-app-metadata.xml, the following XML will come into effect (custom changes are in bold):



<BaseDocument id="base?>
<Tag0 id="tag0" name="Custom Tag 0" prop="35" /> 
<TagA id="tagA" name="Sample Tag A" prop="30" />  
<TagB id="tagB" name="Sample Tag B" prop="15" />  
<TagC id="tagC" name="Sample Tag C" prop="10" /> 
</BaseDocument>

Now, since the customization XML is existing independently on its own, replacing the base document while upgrading to the next version will not affect the customizations. It is upgrade-safe.

OIM uses this concept, along with sandboxing from MDS, for UI customizations. Let's walk through a typical use case of adding a custom attribute to the user entity and dropping it onto create and view user pages. Side by side, we will see the artifacts being generated and their significance.

  • 1. Figure 1 shows the new attribute being added to the user entity after activating a sandbox:

 

Figure 1: Adding a new attribute

  • 2. Let's export and see what's inside the sandbox (Figure 2).

 

Figure 2: Inside the sandbox

  • /mdsys/sandbox/active_mdsSandboxMetadata.xml: This file identifies a sandbox zip. It contains the sandbox name, creator, last modifier, and the respective timestamps. If you wish to import the same sandbox with some other name, changing the name of zip file will not help. The name should be changed inside this file. OIM-created sandbox names have the prefix "IdM," which should never be removed when changing the name.
  • oracle/iam/ui/common/model/user/entity[or view]/mdssys/cust/site/site/userEO[or VO].xml.xml: These are two customization XML files over the userEO/VO.xml. They contain the definition of the newly added attribute. Later, we will see how they look.

    Note: you will see similar files under a similar path if you add an attribute to Role or Organization.
  • oracle/iam/ui/runtime/form/model/user/entity[or view]/mdssys/cust/site/site/userEO[or VO].xml.xml: These customization XML files over the userEO/VO.xml are present ONLY for user creation and user modification flows. Since user creation/modification either takes a direct or an approval route based on the current user's authorization, these two flows are integrated behind the scenes with catalog, which transparently handles this.

    Note: You will not see files with a similar path while creating Role and Organization attributes; there will be EO/VO.xml files under a similar path while creating application instance forms since they are also integrated with catalog (non-transparently, though).
  • xliffBundles/oracle/iam/ui/runtime/BizEditorBundle_en_US.xlf: This is the resource bundle file in which the display label of the attribute is kept for localization. By default, this file is generated with the locale suffix of the browser locale under which the attribute was created. So, for example, while creating the attribute, if the label is in French, but your browser locale is English, the label will be used for the English locale browsers.
  • 3. At the ADF Business Components (BC) layer, OIM maintains the attributes for various entities in their designated EO.xml and VO.xml files. These files must be updated with the new attribute. But the actual XMLs are not modified; instead, a customization XML is created over them that does an <mds:insert> operation to insert the attribute definition at the right place at runtime. A sandbox is effectively a zipped collection of such XML files. The following is an example of a userEO.xml.xml file.


<?xml version='1.0' encoding='UTF-8'?> 
<mds:customization version="11.1.1.64.93" xmlns:mds="http://xmlns.oracle.com/mds" 
motype_local_name="PDefEntityObject" motype_nsuri="http://xmlns.oracle.com/bc4j">   
<!-- INSERT STATEMENT TO BE EXECUTED OVER OOTB USEREO.XML FILE--> 
<mds:insert parent="UserEO" position="last">   
<!-- EO.XML ENTRY FOR ATTRIBUTE. NOTE THAT NAME IS ppNumber__c. -->  
<Attribute Name="ppNumber__c" IsPersistent="false" Precision="60" Scale="0"   
ColumnName="PPNUMBER__C" Type="java.lang.String" ColumnType="VARCHAR2(255)"   
SQLType="VARCHAR" xmlns="http://xmlns.oracle.com/bc4j">   
<Properties> 
<!-- CERTAIN PROPERTIES OF ATTRIBUTE -->     
<Property Name="AttributeType" Value="Text"/>   
<Property Name="DISPLAYWIDTH" Value="60"/>   
<Property Name="ExtnCustom" Value="Y"/>    
<!-- REFERENCE TO BizEditorBundle.xlf FOR DISPLAY LABEL (CONTAINED IN THE SAME SANDBOX) -->    
<Property Name="LABEL_ResId"    
Value="${adfBundle['oracle.adf.businesseditor.model.util.BaseRuntimeResourceBundle']   
     ['oracle.iam.ui.common.model.user.entity.UserEO.ppNumber__c_LABEL']}"/>   
<!-- NAME OF ATTRIBUTE AS KNOWN BY OIM BACKEND -->    
<Property Name="oimRefAttrName" Value="ppNumber"/>  
</Properties>   
<CompOper Name="=" ToDo="2" Oper="=" MinCardinality="1"   
MaxCardinality="1"/>   
<CompOper Name="STARTSWITH" ToDo="2" Oper="STARTSWITH" MinCardinality="1"   
MaxCardinality="1"/>   
<CompOper Name="ENDSWITH" ToDo="2" Oper="ENDSWITH" MinCardinality="1"  
MaxCardinality="1"/>   
<CompOper Name="<>" ToDo="2" Oper="<>" MinCardinality="1"     
MaxCardinality="1"/>   
<CompOper Name="CONTAINS" ToDo="2" Oper="CONTAINS" MinCardinality="1"  
MaxCardinality="1"/>  
<CompOper Name="DOESNOTCONTAIN" ToDo="2" Oper="DOESNOTCONTAIN" MinCardinality="1"  
MaxCardinality="1"/>  
<CompOper Name="Dummy" ToDo="-2" Oper="Dummy" MinCardinality="1" MaxCardinality="1"/>  
</Attribute>   
</mds:insert>   
<mds:modify element="UserEO">   
<mds:attribute name="StaticDef" value="oracle.iam.ui.common.model.user.entity.UserEO"/> 
</mds:modify> 
</mds:customization>
  • 4. We can now publish this sandbox and log back in to the ID console.
  • 5. Let's expose this new field on the user create and user details pages. Figures 3 and 4 illustrate the process. Here, we have another active sandbox.

 

Figure 3: User Create Screen (Data Component Catalog - userVO)


 

Figure 4: User Details Screen (Data Component Manage Users - UserVO1)

  • 6. Technically speaking, we need to add an <af:inputText> component in a .jsff file and bind that to a particular attribute present in the ADF BC layer. This binding should be done through pageDef.xml's <attribute> binding. Let's export the sandbox and verify that this is what we actually have inside it.

 

Figure 5: userCreateForm.jsff.xml


 

Figure 6: userCreateFormPageDef.xml.xml

  • 7. We can now test our changes and, once done, publish the sandbox.

Let's take a look at some components that are consumed by OIM for customizing the UI through MDS.

  • Sandbox: Allows a set of metadata or customization artifacts to be tested in runtime without affecting the sessions of other users. Any metadata file (or customization XML file) present inside a sandbox is applicable only to the user session where the sandbox is active. Roughly, a sandbox in OIM follows the lifecycle below:

     

    Figure 7: OIM Sandbox Lifecycle

    • Created/Imported: Sandbox has an entry in the MDS_SANDBOXES table that may or may not contain metadata files associated with it. Even if it has metadata, none of it is taking effect at runtime.
    • Activated: The metadata files contained within the sandbox will come into effect at runtime only for the user session where it was activated. If that user logs out or the session expires, that metadata will again become ineffective.
    • Published: One of the end states of the sandbox lifecycle. Once published, the metadata files get persisted into MDS at their respective paths and thus will be available at runtime for all subsequent user sessions.
    • Deleted: One of the end states of the sandbox lifecycle. Once in this state, the sandbox becomes non-recoverable and all the metadata files inside it are lost.
  • WebCenter Composer: A separate product from Oracle, it provides a UI to edit ADF pages at runtime. Bullet No. 5 in the use-case walkthrough, above, shows the screenshot for the same. Effectively, it generates the customization XML files over the page being edited; these XML files contain the additional components being added/modified/removed from the page. These files are then pushed into the current ADF context's MDS session to be managed by MDS. (MDS session can be obtained by the ADFContext.getCurrent.getMDSSessionAsObject() method.)
  • ADF Business Editor: Business Editor (BE) is an ADF component that can create or edit ADF BC artifacts at runtime (EO.xml, VO.xml and AM.xml). While creating a custom attribute for user/role/organization, BE is responsible for generating customization XML files over the corresponding EO/VO containing the new attribute. Again, these files get pushed to the current ADF context's MDS session to be managed by MDS. BE also comes into play when an application instance form is created. In that case, a new EO.xmland VO.xml is created at runtime and OOTB CatalogAM.xml is edited to include the new VO.
Sandbox Best Practices
  • Re-importing a sandbox with the same name replaces the existing one. Backup all the sandboxes before doing any manual XML editing.
  • A single page should always be edited in a single sandbox to avoid conflicts (and confusion) later on.
  • For any OOTB artifact (a jsff page or EO or VO), there exists one and only one customization file containing the customer's site customizations. Any successive customizations on the same artifact lead to editing of the same file. Thus, parallel sessions performing customizations must be avoided. Changes published from one session will override any changes published from the other session.
  • Because there is only one customization file present for, say, userEO, the sandbox in which a user attribute is being added may also contain any previously published user attributes.

Injecting Custom ADF Artifacts into OIM

 

Apart from MDS-based customization framework, OIM provides a way to build custom ADF task flows and managed beans. These are generally used for custom validations, handling the action of custom links and buttons, or even building completely new screens and launching them through certain links. Here is the deployment process for such changes:

Create ADF Model and ADF View Controller projects in the jdev containing your artifacts. OIM Client, OIM Model and OIM View Controller shared libraries must be included in your custom projects. These libraries can be found in the IDM_HOME/server/jdev.lib directory.

Prepare ADF Library JAR files from the jdev projects. An ADF Library JAR deployment profile needs to be created in jdev to prepare these jars.

Package the ADF Library JAR files into oracle.iam.ui.custom-dev-starter-pack.war (file present in IDM_HOME/server/apps) inside WEB-INF/lib folder. Create a lib folder if not present OOTB inside WEB-INF.

Locate the oracle.iam.ui.custom library in the WebLogic console to see the deployment path (which might not be deployed from IDM_HOME/server/apps).


 

Figure 8: oracle.iam.ui.custom Library in the WebLogic Console

Replace that web archive (war) in the file system with the one you have newly repackaged.

Stop the two active applications shown Figure 8. These are ID console and sysadmin console applications, respectively, and have a dependency over custom library.

Update the oracle.iam.ui.custom library deployment. Once the update is complete, start the two applications stopped previously.

A few points must be kept in mind when developing custom mBeans:

  • Do not use pageFlowScope or backingBeanScope while registering a bean directly to adfc-config.xml. Use session and request scopes instead. If you have built your own task flow, registering your bean in there can be done with any required scope.
  • Inside a bean's code, a handle to an OOTB bean can be obtained using evaluation of Expression Language (EL) expressions through EL-context APIs. The bean scope and name to be used can be found attached to some field/component in the web center composer UI (displayed by clicking "Customize" on the ID console).
  • Getting a handle to an OOTB bean can be dangerous, though, because a custom bean cannot be sure when the OOTB bean is getting initialized-which could lead to null pointer exceptions in custom code.
  • Performing the custom code injection almost always goes hand in hand with MDS customizations. Whenever a custom bean or task flow is developed, some changes must be performed through the web center composer to invoke your bean's code or the task flow.

Conclusion

This article provides technical insight into the possible customizations over OIM UI, and walks through the most common use case—adding a new user attribute to the create and view details pages—and describes what happens behind the scenes. It also provides the basic steps that must be performed to inject into OIM UI custom ADF code that is available at runtime.

About the Author

Gaurav Singh is part of the Oracle Identity Manager Developers' group. Since the very beginning of his career he has been interested in UI technologies and has been exploring Oracle ADF, Oracle Metadata Services, Oracle Composer, and similar tools to deliver next-generation user interfaces.