Introduction
OIM 11g R2 being such a comprehensive provisioning solution,
it provides API’s for almost every aspect of functionality available in the
product. This makes it a little difficult to decide which examples are needed
the most in the documentation. Fortunately, the documentation does supply
samples that can definitely serve as a foundation for more complex pieces of
code. Some of the API’s I found developers using more often than others are the
ones related to the operations associated with users’ requests for resources.
Amongst those the following API’s are mostly required:
- Request Creation/Submission
- Request History Data Access
- Child Table Data Manipulation
- Approval Information Data Access
This blog post will include a few samples on how to
accomplish each one of the above mentioned operations within the context of a
use case described shortly. The intent is to provide some useful API’s code samples
that customers and partners can use to write their own custom code that
requires such functionality.
The Use Case
As a starting point for this article, I figured that the
best way to describe a series of API code samples is by using a use case. Here
is ours:
A Home Building Company requires their Engineers and Site
Managers to carry handheld devices (Smart Phones, Tablets, Radios) to keep
information about their projects and also maintain communication with the
corporate office. These devices are provisioned to their users along with a
specific list of services enabled on the device. The users are provisioned
these resources through the following process:
When the user is on boarded, it gets assigned to an
Organization according to their role (Engineer, Architect, Site Manager,
Designer, Sales Associate, etc). Depending on the organization the users belong
to a certain type of device with specific capabilities can be requested. Users
submit their requests for a device and a set of capabilities through OIM. Now,
the request for provisioning of the resource is not supposed to reach the
administrator that will setup the contract for the device until all the individual
services that will be enabled in the contract are approved. The fact that a
device service is requested doesn’t mean it will be granted to the requester.
Each individual service requires a different set of approvals. Once all the
requested services have been processed (approved or denied) then the request
arrives in the administrator’s queue.
The Design
According to the Use Case described previously, the design
of a solution that addresses the requirements needs to leverage the concept of
Disconnected Application Instance. In
this case in particular, the Disconnected Application Instance will have a Child
Form used to store the Services that will be enabled on the device’s contract
once it is provisioned.
As described above, the services go through approval
individually. In order to accomplish this in a simple way we will represent the
device contract services as roles, which can be assigned their own approval
process and can be tracked individually. Now, suppose the HBC has a new
requirement that expresses the need to provision application entitlements to a
Portal that allows users to manage their own contract’s services and the access
is controlled through AD group membership. Having the design already described
allows for the use of access policies to provision such access automatically
once the role for the individual service is approved, and the evaluation of
access policies has been executed.
In summary, the code samples we provide in this section will
focus on how to create the requests for the disconnected application instances
and the roles representing the services available on the contract for the
device. Then, the focus will be shifted to the API’s used to retrieve the data
for a given request and read it. The user interface that allows the users to
request such devices and services can be implemented as a customization to the
catalog screens in OIM 11g R2. The screens will contain a drop down list of
devices that are available to the users according to their organization. When a
device is selected, a second catalog search will bring back the services that
are tied to the selected device (For an example of cascading searches customization
please refer to the following blog post http://fusionsecurity.blogspot.com/2012/12/oim-11g-r2-ui-customization-tips-and.html).
The Implementation
Now to the fun part, how do we make this happen? As I stated
before, the main focus will be the Request Lifecycle Management API’s so we
will not show the Catalog Search API’s samples neither how to customize the UI
to input the data (a potential implementation of such logic is also discussed
in the post mentioned earlier. Also, for all kinds of samples of UI
customizations and other commonly used OIM API’s make sure to refer to the OIM
11g Academy). So assuming the user has the means to select a device and a
set of services for the selected device the requests for each one will be
created as follows:
The code will traverse the list of services that were added
to the cart first, and then create requests for them and obtain the request ids
by submitting those requests. Then create the request for the actual device and
populate the child table with the requested services. The child table will have
three columns (fields): Service Name, Request ID for the role representing the
service and the status of the Role (Pending/Approved/Rejected).
The first sample presented creates a request for a Role to
be granted to the user. Consider the code in the following listing:
Listing 1-1 Method buildRoleAssignmentRequest |
Two parameters are passed: the item of type Catalog and the
userLogin of type String. The userLogin is necessary to extract the user Key
which will be inserted in the request. The item parameter contains the
information that describes the role as a Catalog Item. The Catalog class
provides the details that can be used to populate the request for the actual
entity. In case of roles as shown in the listing above, there is no need to
populate a form, just create a RequestBeneficiaryEntity and set a couple of attributes
in it. Things get more interesting when creating the request for the
Application Instance. Here is how:
Listing 1-2 Implementation of method buildApplicationInstanceRequest |
Same two parameters are passed but this time there is an
additional call to build the list of attributes for the Application Instance
Form. Below is the listing for the method buildAppInstanceAttributeList:
Listing 1-3 Implementation of method buildAppInstanceAttributeList |
As presented in the listing below, in order to set the
values of fields in the “process form”, what is being used is the field label not the field name. The reason why is because we are
not really populating the form, we are populating the request data set, which
in turn will serve as the source to populate the actual process form. This
gives the ability to determine what information the requesters may see when
submitting requests for resources, which may not be the entire set of fields in
the actual process form. The other interesting thing is how to populate the
Child Table, see below (this is a fragment from the method listing above):
Listing 1-3-1 Section of buildAppInstanceAttributeList method where child records are created |
In typical examples of how to accomplish child table record
insertion that I have come across, all they show is how to insert one value
into the child table; but what about inserting multiple rows in the child table
and each row has multiple attributes. Well this example shows you how to
accomplish insertion of child table records when you need to insert multiple
rows that in turn have multiple columns. As shown in the code above, what needs
to be done is to create an instance of RequestBeneficiaryEntityAttribute that
represents the child table itself. Then you create an instance of
RequestBeneficiaryEntityAttribute for each column in the child table. You set
the values of each individual column and add those attributes to a list (see childAttributesList1). Then you call
the addChildAttributes method on the attribute that represents the Child Form
(see appRolesAttr) and pass the list
containing the values of all the Child Attributes of the row. To insert
multiple rows, you create multiple instances of the RequestBeneficiaryEntityAttribute
that represents the Child Table itself and build the row as already explained.
In the listing above the creation of appRolesAttr
is placed within a loop that in our case traverses the list of Services
(Entitlements) that a device is supposed to have and then creates a child table
row for each service.
That’s it for the request creation, now the requirements for
the use case as designed need the means to monitor the requests for the
individual services (roles) and determines when to resume the Device
Provisioning process flow. For those of you that are new to Disconnected
Application Instances and how they are provisioned, here is a little background:
Disconnected Application Instances are configured just as regular connected applications
that have a Target System (IT Resource/Resource Object combination), the only
difference is that as disconnected Applications the IT Resource, Resource
Object, provisioning process, process form, request data sets, etc are created
by OIM behind the scenes. You can customize these artifacts after they are
created, which in fact is what we need to do to add the services to the
requested device. The process form will be customized to add the child table
that will hold the contract services for the device. The code to populate the
child form has been presented above.
In order to monitor the status of the Requests for Device
Contract Services, we need to read that data and keep a count of Services that
have already been processed versus those that haven’t. As a solution to this
problem we decided to implement an asynchronous Web Service which is
implemented as an Asynchronous BPEL process that invokes a Synchronous Web
Service that monitors all the associated Role requests (contract service
requests) mapped to the device’s request. The asynchronous BPEL process is
presented in the figure below:
Fig 1-1 Asynchronous BPEL process to monitor Role Requests Processing status |
This BPEL process contains a loop task that will break the
loop when the count of pending role requests reaches ‘Zero’. Every invocation of the OIMPendingRequestsCounterService
results in a new count representing the number of requests for Contract
Services (Roles) that are still awaiting approval. This is an easy way to
create an asynchronous Web Service using JDeveloper’s features to create
Asynchronous BPEL processes that can be invoked as asynchronous Web Services.
The implementation of the OIMPendingRequestsCounterService is described next.
Consider the listing presented below:
Listing 2-1 Web Service Method to obtain the count of Roles in Pending status for approval |
The most important components in this implementation are:
- OIMClient oimClient: This is used to obtain instances of OIM’s API’s.
- RequestService reqSvc: The Service used to obtain information about a request and to update the request’s data when appropriate.
- UserManager usrMgr: Used to obtain the User’s Key of the request’s beneficiary along with other information that might be needed.
Notice another new service introduced in OIM 11g R2, the
ApplicationInstanceService. This is used to obtain the names of process and
child forms plus their values. According to the listing above, the process is
actually simple: Obtain the requested Entity from the request data. Find the
Application Instance that is associated with the request by checking the entity
sub type. Once the Application Instance has been found, now we can obtain the
child form that contains the entitlements (contract services). Each row is
represented by an occurrence of an attribute named after the child form’s
table. So if multiple entries are present in the child table, they will be
accounted for as separate instances of the attribute named after the child
form’s table.
These attributes are added to a list that will be traversed to
extract the individual rows one by one. Each row has child attributes (columns)
which contain the value of the corresponding column within the row. All these
information comes from the populated data set not the actual process form. In
order to retrieve the data from the process form, the resources need to have
already been provisioned. That is not the case in this situation because the
Application Instance representing the device can’t be provisioned until all the
services have gone through their approval processes. The following method is
also important for the implementation:
Listing 2-2 Internal method that verifies the Role Requests approval status |
This is the method that reads the child request data to
determine if the Approval has been granted or denied; in other words, whether
or not the child request has been already processed. So, to complete the
implementation all you need to do is to modify the Composite that gets invoked
when a Disconnected Application Instance is provisioned. The following picture
shows this modification:
Fig 2-1 BPEL Process for the SOA Composite invoked when a disconnected Application Instance is provisioned |
As shown in the previous picture, an Invoke activity along
with a Receive activity are employed to call the asynchronous BPEL process that
internally call the synchronous Web Service to monitor the Approval/Rejection
of the requests for the Contract Services (Roles). This mechanism is fairly
simple, but has room for optimization of course. For instance, you might want
to implement an event generation mechanism to send a JMS Message to unblock the
process flow of the Disconnected Application Provisioning SOA Composite and
then process the Human task that will be sent to the Administrator of the
Contract, who will manually carry out the processing for the provisioning of
the device.
Summary
In this article, we have presented the audience with samples
of how to use OIM API’s to programmatically implement a use case that involves
the following Request Lifecycle Management operations:
- Create complex structure requests for Disconnected Application Instances.
- Create requests for Role Assignment.
- Implement Data Retrieval from Child Tables directly from the request data set.
I hope the samples presented in this article are helpful to
your own implementations.
For this and many other useful OIM 11g R2 articles make sure to visit our OIM 11g Academy series.
Thanks for sharing this useful information. There are a lot of powerful features that lack documentation so it takes a lot of time to figure out how to use them.
ReplyDeleteI have a question about your first example 'request for a Role to be granted to the user'. In 11g R1 there are 'template attributes' to allow requester to provide additional information when creating a request to grant role to user. But it looks like they are gone in 11g R2 (because request templates are also gone) and there is nothing similar. But API still has methods to deal with them. Is it possible to add custom field to 'assign roles' request? How to set it with API?
Ivan
DeleteI haven't used that API in particular, but you are right; it is there. To answer your question, yes you can customize the form for roles with additional attributes and by regenerating the view, you can include these attributes in your Data Set. Since the UI is somehow independent now from the actual process and request forms you can choose to add them to the UI pages and manipulate them using Managed Beans to automatically populate the fields or execute some kind of logic upon them, and so forth.
I hope this is helpful.
Regards
Alex