Plug-In Framework


  1. Overview in User manual


  1. OIM 11G Hacking the UserNamePolicy or User Name Policies
  2. OIM 11G Custom UserNamePolicy Build,Deploy and Test 1A
  3. OIM 11G Custom UserNamePolicy Build,Deploy and Test 1B
  4. OIM 11G Custom PreProcess Event Handler 1
  5. OIM 11G Custom PreProcess Event Handler 2
  6. OIM 11G Custom PreProcess Event Handler 3
  7. OIM 11G Custom PreProcess Event Handler 4

Sample UserNamePolicy plugin.

We start with the plugin.xml file The plugin.xml file defines the plugin point and the name of the custom plugin class for each plugin. multiple plugins can be
defined in one plugin file. the list of valid plugin points are listed in the OIM Developers Guide. Note here that we are using the UserNamePolicy plugin point to define our custom UserNamePolicy class.

<?xml version="1.0" encoding="UTF-8"?>
    <plugins pluginpoint="oracle.iam.identity.usermgmt.api.UserNamePolicy">
        <plugin pluginclass="org.yourpackage.plugins.FirstInitialLastNamePolicy" version="1.0" name="Custom UserNamePolicy"/>

The next step is to create the actual UserNamePolicy class. To do that we implement the UserNamePolicy interface.

public class FirstInitialLastNamePolicy implements UserNamePolicy

When we look at the API we can see what the Interface expects us to define. So without further ado here is the source. The main part of the plugin is the getUserNameFromPolicy method.

This plugin will generate a unique username based on the OIM USR table. The last name is appended to the first initial. if a duplicate is found a numeric increment is appended to the userid until a unique id is created.

public class FirstInitialLastNamePolicy implements UserNamePolicy {

    private Logger logger = Logger.getLogger(this.getClass().getName());

    public String getUserNameFromPolicy(Map<String, String> reqData) throws UserNameGenerationException {

        logger.debug("Custom FirstInitialLastNamePolicy.getUserNameFromPolicy");
        String userName = null;

        String firstName = (String)reqData.get("First Name");
        String lastName = (String)reqData.get("Last Name");

        if ((firstName == null) || (firstName.length() == 0)) {

            UserNameGenerationException exception = new UserNameGenerationException("First Name is Invalid", "INVALIDFIRSTNAME");
            throw exception;

        if ((lastName == null) || (lastName.length() == 0)) {
            UserNameGenerationException exception = new UserNameGenerationException("Last Name is Invalid", "INVALIDLASTNAME");
            throw exception;

        String firstInitial = firstName.substring(0, 1);
        userName = firstInitial.concat(lastName);
        userName = UserNameGenerationUtil.trimWhiteSpaces(userName);

        if ((UserNamePolicyUtil.isUserExists(userName)) || (UserNamePolicyUtil.isUserNameReserved(userName))) {
            String baseName = userName;
            boolean userNameGenerated = false;

            for (int i = 1; i < 2147483647; i++) {
                userName = generateNextUserName(baseName, i);
                if (UserNameGenerationUtil.isUserNameExistingOrReserved(userName)) {
                userNameGenerated = true;

            if (!userNameGenerated) {
                throw new UserNameGenerationException("Failed To Generate Unique User Name", "GENERATEUSERNAMEFAILED");

        return userName;

    public boolean isUserNameValid(String userName, Map<String, String> reqData) {
        return isUserNameLexicallyValid(userName, reqData);

    public String getDescription(Locale locale) {
        return "First Initial Last Name No Random Character UserNamePolicy";

    private String generateNextUserName(String baseName, int index) {
        String userName = "";
        if (baseName.indexOf("@") != -1) {
            String emailId = baseName.substring(0, baseName.indexOf("@"));
            String domain = baseName.substring(baseName.indexOf("@"), baseName.length());

            userName = emailId + index + domain;
        } else {
            userName = baseName + index;
        return userName;

    private boolean isUserNameLexicallyValid(String userName, Map<String, String> reqData) {
        boolean isUserNameValid = false;

        if ((userName == null) || (userName.length() == 0)) {
            return isUserNameValid;

        String firstName = (String) reqData.get("First Name");
        if ((firstName == null) || (firstName.length() == 0)) {
            return isUserNameValid;

        String lastName = (String) reqData.get("Last Name");
        if ((lastName == null) || (lastName.length() == 0)) {
            return isUserNameValid;

        if (lastName.length() >= userName.length()) {
            return isUserNameValid;

        String middleName = userName.substring(1, userName.length() - lastName.length());

        if (!areAllValidCharacters(middleName)) {
            return isUserNameValid;

        String extractedFirstInitial = userName.substring(0, 1);
        String extractedLastName = userName.substring(userName.length() - lastName.length());

        if (!Character.isLetter(extractedFirstInitial.charAt(0))) {
            return isUserNameValid;

        if ((extractedFirstInitial.equalsIgnoreCase(firstName.substring(0, 1))) && (extractedLastName.equalsIgnoreCase(lastName))) {
            isUserNameValid = true;
        return isUserNameValid;

    private boolean areAllValidCharacters(String middleName) {
        boolean areAllCharacters = true;
        for (int i = 0; i < middleName.length(); i++) {
            if (!Character.isLetter(middleName.charAt(i))) {
                areAllCharacters = false;
        return areAllCharacters;

Packaging the Plugin

This is an excerpt from the Developers Guide.
6.3.3 Developing Plug-ins

An Oracle Identity Manager plug-in is distributed as a ZIP file with a specified directory structure. The directory structure is as follows:

The plugin.xml file: The XML file contains the metadata associated with all the plug-ins such as the plug-in point it extends, the class implementing the plug-in, name, and the version number. All the fields in the XML are mandatory except the name. If the name is not given, then plugin class name is used as the name.

The lib/ directory: The lib/ directory consists of JAR files that contains the classes implementing the plug-in logic and the dependent library JAR files. In most instances, this directory consists of a single JAR file with the implementation of all the plug-ins that are specified in plugin.xml.

The resources/ directory: Contains resource files required by the plug-in, such as property files, resource bundles, and image files.

There are many ways to create the zip package. The way I have been doing it is to

1) Create a new directory called plugin
2) Create the plugin/lib directory and the plugin/resource directory
3) create the jar file with Netbeans clean and build then copy the jar file from dist to plugin/lib
4) copy the plugin.xml to the plugin directory
5) zip the plugin directory from inside the directory as
cd plugin
zip -r *

Registering the Plugin

The plugin needs to be registered before you can run it. Follow the instructions in the OIM Developers Guide

After the plugin is registered you should restart the OIM Managed Server.

See also

Register/unregister plugin

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License