Thursday, July 21, 2011

OIM 11g Notifications

Notifications are one of the multiple features that were improved in OIM 11g release. The previous limitation of sending text based emails (out-of-the-box emails) only is gone.

Out-of-the-box templates for events like 'Reset Password', 'Create User Self Servic', 'User Deleted' are available and custom templates can be defined and used to send notifications out of OIM.

OIM provides a notification framework based on events, notification templates and template resolver. They are defined as follows:
  • Events are defined in a XML file and must be loaded into MDS database in order to be available for use.
  • Notification templates are defined through OIM advance administration console. The template contains the text and the substitution 'variables' that will be substituted by the data provided by the template resolver. Templates support HTML and text based emails and multiple languages.
  • Template resolver is a Java class that is responsible for providing the data to be used to parse the template, it must be deployed as an OIM plugin. The data provided by the resolver class will be used by OIM in the template substitution variables.
The main steps for defining custom notifications in OIM are:

  1. Define the Event that will be used for triggering the notification
  2. Define the Template to be formatted and sent
  3. Create the Template Resolver class
  4. Trigger the event from the relevant spot in OIM

This post explain each of the steps above and give some tips on how to create the notifications.



1. Defining the Event and its metadata

The Notification Event is defined through a XML file that must be loaded into MDS database. Also in MDS, there is a XSD that defines the tags and properties that the event XML may contain. The XSD is available at the following location in the MDS database:

/metadata/iam-features-notification/NotificationEvent.xsd

You can use the weblogicExportMetadata.sh script to export the XSD file.

Below an example of an event metadata definition:

<?xml version="1.0" encoding="UTF-8"?>
<Events xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../metadata/NotificationEvent.xsd">
  <EventType name="Demo Notification Event">
    <StaticData>
      <Attribute DataType="X2-Entity" EntityName="User" Name="User Login"/>
	  <Attribute DataType="91-Entity" EntityName="User Group" Name="User Grp"/>
    </StaticData>
     <Resolver class="com.oracle.demo.oim.notification.DemoNotificationEventResolver">
      <Param DataType="X2-Entity" EntityName="User" Name="usr_login"/>
    </Resolver>
  </EventType>
</Events>

The property name in the tag EventType defines the event name, this is used in the OIM advanced administration UI. The StaticData session defines the entities (and their attributes) that can be used in the notification template, the entities attributes are used to define substitution tokens in the template. The resolver tag defines the Java class that OIM will invoke to provide the data to be used in the notification and the parameters that must be provided to the resolver class.

The XML must be loaded into the MDS database using the weblogicImportMetadata.sh script. You need to define resolver class name, but you don't need the class loaded in OIM just yet (it can be loaded later).

2. Defining the template

With the notification event defined in OIM, it is time to create the notification template based on that event. This action is done from the OIM advanced administration UI. The image below depicts the template created for this post:



Note that the template Demo Notification Event created in the previous step being used as the notification event.

Also note the Available Data dropdown and the Selected Data text field. The contents of the drop down are based on the event XML StaticData tag, the drop down basicly lists all the attributes of the entities defined in that tag. Once you select an element in the drop down, it will show up in the Selected Data text field and then you can just copy it and paste it into either the message subject or the message body fields. The picture below depicts this action:


It is important to mention that the Available Data and Selected Data are used in the substitution tokens definition only, they do not define the final data that will be sent in the notification. OIM will invoke the resolver class to get the data and make the substitutions.


3. Coding the notification resolver

The template resolver must implement the interface oracle.iam.notification.impl.NotificationEventResolver and provide actual implementation for the methods defined in the interface.

package com.oracle.demo.oim.notification;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import oracle.iam.identity.usermgmt.api.UserManager;
import oracle.iam.identity.vo.Identity;
import oracle.iam.notification.api.NotificationService;
import oracle.iam.notification.impl.NotificationEventResolver;
import oracle.iam.notification.vo.NotificationAttribute;
import oracle.iam.platform.Platform;

public class DemoNotificationEventResolver implements NotificationEventResolver{
    
    public DemoNotificationEventResolver() {}

   }
    public List<NotificationAttribute> getAvailableData(String eventType, Map<String, Object> map) {
        
        List<NotificationAttribute> list = 
new ArrayList<NotificationAttribute>();
        return list;
    }

    public HashMap<String, Object> getReplacedData(String eventType, Map<String, Object> eventParams) throws Exception {
        

        HashMap<String, Object> resolvedNotificationData = new HashMap<String, Object>();
        
        UserManager usrMgr = Platform.getService(UserManager.class);
        
        //getting the notfication parameter
        String userLogin = (String) eventParams.get("user_login");
        
        // Mapping token with their actual value for user attributes.
        if (userLogin != null) {
          
            NotificationService notificationService =  Platform.getService(NotificationService.class);
            //getting the list of all possible notification attributes
            List<NotificationAttribute> notificationAttributes =  notificationService.getStaticData(eventType);
            
            //seting the attributes for user search based on the notification attributes
            Set<String> userRetAttrs = new HashSet<String>();
            for (NotificationAttribute notificationAttribute :  notificationAttributes.get(0).getSubtree()) {
                userRetAttrs.add(notificationAttribute.getName());
            }
            
            //searching the user
            Identity user = usrMgr.getDetails(userLogin, userRetAttrs ,true);
            HashMap<String, Object> userAttributes = user.getAttributes();
            
            //setting the values in the resolved notification data Map
            String key = null;
            for (Map.Entry<String, Object>  entry : userAttributes.entrySet()) {
                
                key = entry.getKey();
                
                if (key != null) {
                    if ((entry.getValue() instanceof java.util.Map) && (key.equalsIgnoreCase(""))) {
                        key = key.replace(' ', '_');
                        resolvedNotificationData.put(key,  ((HashMap)entry.getValue()).get(""));
                    } 
                    else {
                        key = key.replace(' ', '_');
                        resolvedNotificationData.put(key, entry.getValue());
                    }
                }
           }
        }
        //returning the resolved data with all user information
        return resolvedNotificationData;
    }


This code must be deployed as an OIM plugin. The XML file defining the plugin is available below:

<?xml version="1.0" encoding="UTF-8"?>
<oimplugins xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <plugins pluginpoint="oracle.iam.notification.impl.NotificationEventResolver">
        <plugin pluginclass= "com.oracle.demo.oim.notification.DemoNotificationEventResolver" version="1.0" name="Demo Event Resolver"/>     
    </plugins>
</oimplugins>

4. Triggering the event

A notification event can be triggered from different spots in OIM. The logic behind the triggering must be coded and plugged into OIM. Some examples of spots for triggering notifications:
  • Event handlers: post process notifications for specific data updates in OIM users
  • Process tasks: to notify the users that a provisioning task was executed by OIM
  • Scheduled tasks: to notify something related to the task
In this post, a scheduled job was used to trigger the event. The scheduled job has two parameters:
  • Template Name: defines the notification template to be sent
  • User Login: defines the user record that will provide the data to be sent in the notification
 The scheduled job code:
package com.oracle.demo.oim.schedule;

import java.util.HashMap;

import oracle.iam.notification.api.NotificationService;
import oracle.iam.notification.vo.NotificationEvent;
import oracle.iam.platform.Platform;
import oracle.iam.scheduler.vo.TaskSupport;

public class NotificationDemoScheduledTask extends TaskSupport {
    
    public NotificationDemoScheduledTask() {
        super();
    }

    public void execute(HashMap taskParameters) {
  
        String templateName = (String)taskParameters.get("Template Name");
        String userId = (String)taskParameters.get("User Login");
        
        try {
            
            NotificationService notService = Platform.getService(NotificationService.class);
            NotificationEvent eventToSend = this.createNotificationEvent(templateName,userId);
            notService.notify(eventToSend);
            
        } catch (Exception e) {
            e.printStackTrace();
        }         
    }

    private NotificationEvent createNotificationEvent(String poTemplateName, String poUserId) {
        
        NotificationEvent event = new NotificationEvent();
        
        String[] receiverUserIds= {"xelsysadm"};       
        event.setUserIds(receiverUserIds);
        
        event.setTemplateName(poTemplateName);
        
        event.setSender(null);
        
        HashMap<String, Object> templateParams = new HashMap<String, Object>();
        templateParams.put("USER_LOGIN",poUserId);

        event.setParams(templateParams);
        
        return event;
    }

    public HashMap getAttributes() {
        return null;
    }

    public void setAttributes() {}
}

The XML below that defines the scheduled task plugin:
<?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.oracle.demo.oim.schedule.NotificationDemoScheduledTask" version="1.0" name="Notification Demo Task"/>     
    </plugins>
</oimplugins>

The XML below defines the scheduled task in OIM:
<?xml version='1.0' encoding='UTF-8'?>
<scheduledTasks xmlns="http://xmlns.oracle.com">
  <task>
    <name>Notification Task</name>
    <class>com.oracle.demo.oim.scheduled.NotificationDemoScheduledTask</class>
    <description>Notification Demo Task</description>
    <retry>5</retry>
    <parameters>
      <string-param required="true" helpText="Notification Template Name">Template Name</string-param>
    </parameters>
   </task>
</scheduledTasks>

5. Final comments
  • You should be able to easily deploy the samples above and get the custom OIM notification example working
  • Don't forget to configure the Email Server IT Resource instance in OIM. This configuration is required to send out  emails
  • If you develop from a Windows based laptop/desktop, you can install the Test Mail Server Tool. Then configure OIM Email Server IT Resource instance to point to it and it will show the notifications.
This post is part of the OIM 11g Academy. Check here for other OIM 11g posts.

13 comments:

  1. I don't understand, how did you create (define) new event?
    How did you import new xml event definition?
    Which paths did you use for importing?

    ReplyDelete
  2. It is all on step number #1

    You define the new event through the XML file. The XML will contain,among other things, the event name and the event resolver class.

    Then you use weblogicImportMetadata.sh script to load the XML into MDS database. The weblogicImportMetadata.sh script is available at $OIM_HOME/server/bin.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
    Replies
    1. There is a system property you can try:

      Request Notification Level

      Hope this helps

      Delete
    2. i am learning OIM . so would please let me what exactly the above program is doing..?
      i mean the workflow

      Thank you

      Delete
    3. The solution described above is an approach to send notifications out of OIM. There is a notification event definition, the notification resolver (which is the piece of code that provides the data to OIM put in the notification), and a scheduled task that actually triggers the notification.

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Thanks for this post..it is very useful...

    I am trying to configure it, but while sending the notification, getting following error:

    [2012-03-26T15:33:38.575+05:30] [oim_server1] [ERROR] [] [HIG.LOGGER] [tid: [ACTIVE].ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: oiminternal] [ecid: 0000JPETW23Fg4WFLzrI8A1FS1BF00006Y,0] [APP: oim#11.1.1.3.0] [dcid: f0ed2a6d7fb07688:d3f276a:1364dcb5d26:-7ffd-00000000000001f0] oracle.iam.notification.exception.NotificationException: Cannot load the email service provider.[[
    at oracle.iam.notification.impl.NotificationServiceImpl.sendEmailNotification(NotificationServiceImpl.java:530)
    at oracle.iam.notification.impl.NotificationServiceImpl.notify(NotificationServiceImpl.java:319)
    at oracle.iam.notification.api.NotificationServiceEJB.notifyx(Unknown Source)


    Any idea about this error?

    ReplyDelete
    Replies
    1. I have not seen this error before. A few things to check:

      - Make sure that the Email Server IT resources is correctly configured
      - Make sure that OIM box can connect to SMTP server
      - Also, if you have OAM integration, make sure that OIM is capable of communicating with OAM

      Hope this helps

      Delete
  6. Hi,

    Looks like the above steps only applies to email notification. How can we configure OIM 11g to send an SMS notification?

    Does it supported?

    ReplyDelete
    Replies
    1. I do not think OIM natively supports SMS integration. But nothing prevents you from communicating with SMS gateways using Java APIs, and I do not think that would be a lot of work. Also I think some SMS providers accept incoming email messages and forward them as SMS messages, so I would check the specific SMS gateway you have to use for this feature.

      Delete
  7. Hi, I am trying to put large HTML content in the body of Email Template. But I am unable to save the content. When the content is small it get stored in body of Email Template.

    Question here is "Is there any Body Size restriction in the Email Template"?

    Suppose I want to put 2000 lines of Email Body..is it possible?
    Also, is there any character restriction while entering contents in the mail body? For Example: Assume like it does not support "#" etc

    ReplyDelete
    Replies
    1. I am not aware of any char restriction.

      But the size is limited to 4000 chars. That is the column size in the database.

      You can try to use custom notification resolvers and from there you can 'add' content to the email replacing the tokens for long texts.

      Delete