Wednesday, September 19, 2012

OIM 11g R2 Catalog Customization Example


This post shows how OIM catalog can be customized by using OIM UI capabilities such as managed beans and EL expressions. The post first describes the use case and the solution to address the use case; then it describes the solution details as well as provides links to the artifacts.

In order to have a better understanding of the customization described in this post, one should read the posts about the catalog and about the OIM UI customization.


Use case description


When an end user searches the catalog, he/she can see any catalog item that he/she is allowed to request, including the items already provisioned. In other words, the ‘Add to Cart’ button will always show up for any catalog item. In the shopping cart detail page, the ‘Submit’ action will prevent users from submitting request with catalog items that are already provisioned to them.

With the customization described in this post, the catalog items already provisioned will show up with the ‘Add To Cart’ button replaced and users will not be able to add such items to the shopping cart.

Solution Description


The solution consists of a custom code that will be invoked every time a catalog item is rendered as part of a catalog search result. The code will be deployed as a managed bean in the OIM customization placeholder library (oracle.iam.ui.custom library).

The custom code will check if the catalog item (role, application instance, or entitlement) is already provisioned to the request beneficiary. If the check is 'true', the 'Add to Cart' button will be disabled and a different icon will be shown in the UI. 

The solution also replaces the out-of-the-box 'Add to cart' image by a custom image.

Solution Details


The solution consists of the following steps:
  1. Create a custom application in JDeveloper, code the solution and deploy it to a jar file
  2. Deploy the jar file created in the previous step to the OIM customization placeholder library
  3. Invoking the custom code from OIM UI
  4. Deploy the custom images to WebLogic 

1. Creating the JDeveloper Application:

JDeveloper application will contain all the custom code and the ADF artificts. It will also contain the deployment profile that generates a Jar file.

The general steps are:

  1. Create a new library in JDeveloper with OIM client jar files
  2. Create a new application and select 'Fusion Web Application' as application type. This option will take you through a wizard where you have to provide some basic information. The picture below shows the JDeveloper option you should select
  3.  The new application will have two projects: 'Model' and 'ViewController'. All your work will be done in the 'ViewController' project.
  4. Add library created in step 1 is added to the 'ViewController' project
  5. Create a new deployment profile in the 'ViewController' project. The deployment profile type is 'ADF Library Jar File':
  6. Add a bean declaration to the adf-config.xml file. The bean declaration will tell OIM UI which beans are available and can be invoked. The picture below shows the bean used in this example
  7. Code and compile your bean.
  8. Deploy your bean to a jar file using the profile created in step 2.
The project developed for this post is available here.

2. Deploying the custom jar into the OIM placeholder library

The placeholder library is the file oracle.iam.ui.custom-dev-starter-pack.war. This file is available along with the other OIM application packages (EARs and WARs) at $OIM_ORACLE_HOME/server/apps folder.

Before doing any modification to this file, create a backup of it.

Using a ZIP tool, like 7-Zip, the steps are:
  1. Open the oracle.iam.ui.custom-dev-starter-pack.war
  2. Add the custom jar file to the 'WEB-INF/lib' folder. If the 'lib' folder does not exist, create it
  3. Save the oracle.iam.ui.custom-dev-starter-pack.war file. The picture below shows the war file in the 7-ZIP tool:
  4. Copy the oracle.iam.ui.custom-dev-starter-pack.war file back to its original location under $OIM_ORACLE_HOME/server/apps
  5. Stop OIM managed server
  6. In WebLogic administration console, update the 'oracle.iam.ui.custom' library deployment and activate the changes
  7. Start OIM managed server

3. Invoking the custom managed bean from OIM UI

The first step here is to login to OIM as an administrator and create a new 'SandBox'. The picture below shows the sandbox created for this solution. After creating the sandbox, make sure it is active.


Navigate to the catalog and execute a search (be sure to execute a search that will return results so the 'Add to cart' button shows up). With the results on the page, click on the 'Customize' link on the top right. Then on the top left, hit the 'View' drop-down link, and click on 'Source'. Then move the mouse cursor to the catalog panel, and click over the 'Catalog Items' panel title. Confirm the task flow edit. This action should highlight the 'Column: Catalog Items' element in the source panel. Then scroll the source panel down until you see the element 'commandToolbarButton: Add to Cart'. This is the UI element to be customized. The picture below shows what you should see after all the navigation clicks:


Right click on the 'Add to Cart' button, and then click on 'Edit' link. You should see button the 'Component Properties'. There are three changes to be done: the 'Icon' property, the 'Text' property and the 'Disabled' property. To change the properties values you will use the 'Expression Builder' by clicking on the small arrow on the right of each property, the picture below shows that:



In the 'Icon' property, enter the following expression:

#{catalogResolverBean.resolve[row.entityKey]}


In the 'Disabled' property, enter the following expression:

#{catalogResolverBean.resolve[row.entityKey] != '/images/add_tocart.png'}

In the 'Text' property, delete the current expression and leave it blank.

The picture below shows all the three properties after the change:


Once everything is set, click on 'Ok' button, then on the top-right 'Close' link. The customization is saved in the Sandbox.

4. Deploying the custom images to WebLogic:

The code that checks whether or not a catalog is already provisioning returns an image path. This image will be loaded as any other UI image. Therefore the images files must be available to WebLogic/OIM application.

The images used in this example are available here.

You have to copy the images to the following location:

$DOMAIN_HOME/servers/<oim_server>/tmp/_WL_user/oracle.iam.ui.view/<xxxx>/images

<oim_server>  is the name of the managed server where OIM is running. If you have a cluster you need to copy to all managed servers in the cluster

<xxxx> is a random string. In my environment this string is 'ycwdzs'

A restart is needed after deploying the images.

Results


The modification will make the catalog search result show different icons according to the verification result from the managed bean. The picture below shows an example:


 Disclaimers

  • The content and codes are provided "as is" and without warranties as to performance or merchantability and are just examples and for informational purpose
  • This post does not go deep in details discussing all the technologies involved in the customization, it is more of a ‘how-to’ example.
  • Keep in mind that customizations can always bring performance impact, specially in environments with lots of data. This post does NOT cover any tuning, performance impact or anything like and it was not conceived with performance as an objective
  • There may be cases where the solution described in this post does not fit business requirements, hence the implementation approach should be different

13 comments:

  1. This is a good example.
    However, in step #4, deploying custom images to Weblogic, instead of copying images to oracle.iam.ui.view under tmp directory, cleaner way would be to add the image in your adf shared library and this shared library would be copied to custom-dev-starter-pack.

    ReplyDelete
    Replies
    1. Abishek, I have not tried to add the images to the place holder library. But if it works that way, indeed it is a better option.

      Delete
  2. This is an excellent example. I would like to ask you if you know if it is possible to have instead of the Catalog "Input text" search field, a drop-down list - based on the selection from the drop-down the catalog items would display only the roles corresponding to the selected value.

    For example, in the drop-down I have 2 options: "Administrators" and "Users". If I select "Users", I should get in the catalog items all the roles containing "Users" in the name.

    ReplyDelete
    Replies
    1. Claire, it may be possible to customize something like that. OIM relies on ADF+WebCenter, so the sky is the limit. Now, before start trying, you may want to ask yourself things like: how the drop-down content would be managed? in which sort of information the content would be based? what would happen if the catalog grows to thousands of items?

      As I mentioned in the post above, catalog customizations must be done carefully and must have performance as an important thing to consider.

      Unfortunately at this point I have no similar examples to what you described. But it is my list of things to consider.

      Good luck!

      Delete
    2. Daniel, in your example, for the entitlements that the user already has, is it possible to deselect them and to trigger the provisioning update?

      For example if a user has A,B,C as entitlements I would like to remove B and add D,E. Considering this kind of updates how would the catalog work? I guess that an option would be to have A,B,C by default in the cart.

      Delete
  3. Hi Daniel,

    First of all thank you for your answers - I'm new to R2 and some of the new features are confusing.
    I have performed an interface customization for implementing cascading list of values (I have to display all the managers in a list of values and based on the selected value from this list, the second list should display the job titles of the direct reports of the selected manager). As a start I took http://www.oracle.com/technetwork/middleware/id-mgmt/overview/oim-11g-assets-504842.html
    I've created a new Model implementing my two list of values and in the ViewController project I made the panel that includes my fields and the valueChangeListener method. I deployed the projects, copy them to oracle.iam.ui.custom-dev-starter-pack.war in the lib folder under WEB-INF folder and repack the archive. I copied the new .war file to the server and restart the server.
    In OIM, I logged in, activate a sandbox, navigate to my page, bind the inputText to the UIComponent from my class in Jdeveloper and when I try to invoke my MBean in the ValueChangeListener property (using the EL #{backingBeanScope.customBean}) the following error occurs:


    <ADF_FACES-60098:Faces lifecycle receives unhandled exceptions in phase RESTORE_VIEW 1
    javax.faces.application.ViewExpiredException: viewId:/signin - ADF_FACES-30107:The view state of the page has expired. Reload the page.

    Do you have any idea what could be the cause of such behaviour?

    ReplyDelete
    Replies
    1. Claire,

      Unfortunately, it is difficult for me to say what could be wrong.

      One thing that is missing in your description above is the re-deployment. Copying the archive and restarting the servers sometimes is not enough to get the custom code deployed. You have to login into WL console and update the library deployment.

      Hope this helps.

      Delete
  4. Hi Daniel,

    Excellent post, I was able to follow most of the steps and facing one small issue explained below

    Downloaded your application and added oimclient.jar dependency but the application gives compile error for missing "oracle.iam.ui.platform.model.common.OIMClientFactory". Which JAR will have this class and where to get that JAR.

    Please point the JAR location.

    -Thanks
    Tanmai

    ReplyDelete
    Replies
    1. The following post can help you: http://fusionsecurity.blogspot.com/2011/02/finding-which-jar-contains-class-one.html

      Delete
  5. Hi Daniel,

    Please help me to how to add custom link/page in oim 11gr2 selfservice page as same under the Request branch same like Catalog.

    Thanks in Advance

    KD

    ReplyDelete
    Replies
    1. Kuldeep,

      That may become a post in the future (no idea on when it will happen though). Keep watching following the blog.

      Thanks

      Daniel

      Delete
  6. Hello thanks for the good job!
    We are a facing a customer requirement where some of the entitlements must be hidden (not even requestable) from HelpDesk administrators. The standard features based on organization scope cannot be used (for some good reasons). So we are looking for a way to filter out entitlements that have an attribute set to "private", so they never show up in the catalog.
    The questions are: does this sounds possible based on the method you are using? Do we have to use some other customization features to achieve that (like developing our own javabean to fetch only the entitlement to be returned (sounds heavy) instead of using the default one called in the binding backingBeanScope.catReqBean.catalogSearchResultTable)? Should we make the customer change his requirement because this is not possible to achieve with the current version of OIM?
    Thanks in advance.
    Didier.

    ReplyDelete
    Replies
    1. Didier

      OOTB, catalog search result is filtered by two things: the text you enter in the search and the organization scope. The method used in this post just shows how to prevent users from adding specific items to the shopping cart based on previous provisioning activity. Users are still able to see them, but they are not able to request them. Whether or not this suffices your customer's requirement I cannot say.

      If you need a different way of searching, you have to replace the OOTB search with your own. Alex Lopez blogged about it: http://fusionsecurity.blogspot.com/2012/12/oim-11g-r2-ui-customization-tips-and.html

      Hope this helps

      Delete

Note: Only a member of this blog may post a comment.