Sunday, August 30, 2015

Custom Error Message for Validation Handler

Tested On: Oracle Identity Manager 11.1.2.3.0
Description: Demonstrates how to create custom error messages or use out of the box error messages in a validation event handler.



Adding Custom Message to Logging.properties
1.Determine the path of your OIM application deployed on WebLogic.

Deployments > oim (11.1.2.0.0)

2. Locate the OIMServer.jar that is inside the OIM application directory. In this example, the OIMServer.jar can be found in "$MW_HOME/Oracle_IDM1/server/apps/oim.ear/APP-INF/lib" directory.

3. Make a backup of the OIMServer.jar and move it outside the OIM application directory.

4. Extract the OIMServer.jar file using "jar -xf OIMServer.jar" command. Modify the Logging.properties file that pertains to your use case. For example if you would like a custom error message when validating modification of a user, modify logging.properties and logging_en.properties (for English locale) located in "oracle/iam/identity/resources" directory.

Logging Property File

Note:  Your custom error code and message must be in proper format. An example is given below.

1
2
UIAM-1058201 = Custom error message.
UIAM-1058202 = Custom error message. Current user last name {0} and organization {1}.

#{0} and {1} are arguments you must supply when you are calling the OIM UserManagerUtils.createValidationFailedException.

1
2
3
// Example
UserManagerUtils.createValidationFailedException("UIAM-1058202")
UserManagerUtils.createValidationFailedException("UIAM-1058202", new Object[]{lastName, organization});

5. After modifying the logging files, repackage the OIMServer.jar with th following command "jar -cf OIMServer.jar com/ META-INF/ oracle/ Thor/". Then replace the OIMServer.jar in the OIM application path with the modified one.

6. Restart the OIM managed servers.

Validation Event Handler Example

<?xml version="1.0" encoding="UTF-8"?>
<eventhandlers xmlns="http://www.oracle.com/schema/oim/platform/kernel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/schema/oim/platform/kernel orchestration-handlers.xsd">
<validation-handler
class="com.blogspot.oraclestack.eventhandlers.ChangePasswordValidationEH"
entity-type="User"
operation="CHANGE_PASSWORD"
name="ChangePasswordValidationEH"
order="1000"/>
</eventhandlers>
<oimplugins xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<plugins pluginpoint="oracle.iam.platform.kernel.spi.EventHandler">
<plugin name="ChangePasswordValidationEH" pluginclass="com.blogspot.oraclestack.eventhandlers.ChangePasswordValidationEH" version="1.0">
</plugin></plugins>
</oimplugins>
view raw plugin.xml hosted with ❤ by GitHub
package com.blogspot.oraclestack.eventhandlers;
import java.io.Serializable;
import java.util.HashMap;
import oracle.core.ojdl.logging.ODLLevel;
import oracle.core.ojdl.logging.ODLLogger;
import oracle.iam.identity.usermgmt.api.UserManagerConstants;
import oracle.iam.identity.usermgmt.utils.UserManagerUtils;
import oracle.iam.platform.context.ContextAware;
import oracle.iam.platform.kernel.ValidationException;
import oracle.iam.platform.kernel.ValidationFailedException;
import oracle.iam.platform.kernel.spi.ConditionalEventHandler;
import oracle.iam.platform.kernel.spi.ValidationHandler;
import oracle.iam.platform.kernel.vo.AbstractGenericOrchestration;
import oracle.iam.platform.kernel.vo.BulkOrchestration;
import oracle.iam.platform.kernel.vo.Orchestration;
/**
* Validates if Telephone Number is in one of the following formats:
* <ul>
* <li>###-###-####</li>
* <li>###-####</li>
* <li>##########</li>
* </ul>
*
* #Custom Message
* UIAM-1058202 = {0} must conform to one of the following formats: {1}
* @author rayedchan
*/
public class TelephoneNumberValidationEH implements ConditionalEventHandler, ValidationHandler
{
// Logger
private static final ODLLogger LOGGER = ODLLogger.getODLLogger(TelephoneNumberValidationEH.class.getName());
/**
* Executes the validate method if Telephone Number is being modified.
* @param ago Orchestration Object
* @return true for executing event handler; false for not executing event handler
*/
@Override
public boolean isApplicable(AbstractGenericOrchestration ago)
{
LOGGER.log(ODLLevel.NOTIFICATION, "Enter isApplicable() with parameter: {0}", new Object[]{ago});
boolean retValue = false;
// Get changed parameters
HashMap<String,Serializable> modParams = ago.getParameters();
LOGGER.log(ODLLevel.NOTIFICATION, "Modified Parameters: {0}", new Object[]{modParams});
if(modParams != null)
{
// Determine if user's Telephone Number changed
retValue = modParams.containsKey(UserManagerConstants.AttributeName.PHONE_NUMBER.getId()); // Telephone Number
}
LOGGER.log(ODLLevel.NOTIFICATION, "Execute TelephoneNumberValidationEH? {0}", new Object[]{retValue});
return retValue;
}
/**
* Performs validation.
* @param processId
* @param eventId
* @param orchestration
* @throws ValidationException
* @throws ValidationFailedException
*/
@Override
public void validate(long processId, long eventId, Orchestration orchestration) throws ValidationException, ValidationFailedException
{
LOGGER.log(ODLLevel.NOTIFICATION, "Enter execute() with parameters: Process Id = [{0}], Event Id = [{1}], Orchestration = [{2}]", new Object[]{processId, eventId, orchestration});
// Get the parameters that changed
HashMap<String,Serializable> modParams = orchestration.getParameters();
LOGGER.log(ODLLevel.NOTIFICATION, "Modified Parameters: {0}", new Object[]{modParams});
// Get Telephone Number
String telephoneNumber = this.getParamaterValue(modParams, UserManagerConstants.AttributeName.PHONE_NUMBER.getId());
LOGGER.log(ODLLevel.NOTIFICATION, "New Telephone Number: {0}", new Object[]{telephoneNumber});
// Empty telephone passes validation
if(telephoneNumber == null || "".equalsIgnoreCase(telephoneNumber))
{
LOGGER.log(ODLLevel.NOTIFICATION, "Validation Passed: Empty telephone number.");
}
else
{
String phoneNumberRegex = "(\\d{3}-){1,2}\\d{4}|\\d{10}"; // ###-###-####, ###-####,##########
boolean isValid = telephoneNumber.matches(phoneNumberRegex); // Perform regular expression check
LOGGER.log(ODLLevel.NOTIFICATION, "Is Telephone Number Valid? {0}", new Object[]{isValid});
if(!isValid)
{
String errorKey = "UIAM-1058202";
String formats = "(1)###-###-#### (2)###-#### (3)##########";
ValidationFailedException ex = UserManagerUtils.createValidationFailedException(errorKey, new Object[]{UserManagerConstants.AttributeName.PHONE_NUMBER.getId(), formats});
LOGGER.log(ODLLevel.ERROR, "", ex);
throw ex;
}
}
}
@Override
public void validate(long processId, long eventId, BulkOrchestration bulkOrchestration) throws ValidationException, ValidationFailedException
{
LOGGER.log(ODLLevel.NOTIFICATION, "Enter execute() with parameters: Process Id = [{0}], Event Id = [{1}], Bulk Orchestration = [{2}]", new Object[]{processId, eventId, bulkOrchestration});
}
@Override
public void initialize(HashMap<String, String> hm)
{
LOGGER.log(ODLLevel.NOTIFICATION, "Enter initialize() with parameter: {0}", new Object[]{hm});
}
/**
* ContextAware object is obtained when the actor is a regular user.
* If the actor is an administrator, the exact value of the attribute is obtained.
* @param parameters parameters from the orchestration object
* @param key name of User Attribute in OIM Profile or column in USR table
* @return value of the corresponding key in parameters
*/
private String getParamaterValue(HashMap<String, Serializable> parameters, String key)
{
String value = (parameters.get(key) instanceof ContextAware)
? (String) ((ContextAware) parameters.get(key)).getObjectValue()
: (String) parameters.get(key);
return value;
}
}

1 comment:

  1. What about modifying that field, do we need to deploy another Eh fr that.

    ReplyDelete