Name

sn_hr_core.ErrorUtil

Description

No description available

Script

/**
* @Constructor
*/
function ErrorUtil() {
  this._formatUtil = new sn_hr_core.FormatUtil();
}

ErrorUtil.ERROR_KEY = '***~Error';
ErrorUtil.HR_METHOD_NAME = 'ErrorMethodName';
ErrorUtil.METHOD_NAME_SEPARATOR = ': ';
ErrorUtil.METHOD_MSG_SEPARATOR = ' ## ';

ErrorUtil.INSERT = 'insert';
ErrorUtil.UPDATE = 'update';
ErrorUtil.DELETE = 'delete';
ErrorUtil.QUERY = 'query';


/**
* Method to be used  when throwing an exception. To get an error object from the message. This method logs the
* message and returns an Error object.
*
* @param {string} message - The error message.
*
* @return {Error} - The error object.
*/
ErrorUtil.prototype.getError = function(message) {
  return new Error(message);
};

/**
* Method to be used in a catch block. This method adds the method name to the log message, logs the error message
* and returns an Error object that the caller can use to throw an exception.
*
* @param {string} methodName - The method name in which this method is being used.
*
* @param {Error} caughtError - The error object that was caught in the exception.
*
* @return {Error} - The error object
*/
ErrorUtil.prototype.handleExceptionMethod = function(methodName, caughtError) {
  return this.handleException(methodName, null, caughtError);
};

/**
* Method to be used in a catch block. This method adds the method name to the log message, logs the error message
* and returns an Error object that the caller can use to throw an exception.
*
* @param {string} methodName - The method name in which this method is being used.
*
* @param {string|null} message - The error message.
*
* @param {Error} caughtError - The error object that was caught in the exception.
*
* @return {Error} - The error object.
*/
ErrorUtil.prototype.handleException = function(methodName, message, caughtError) {

  var origMessage = this.getMessageFromError(caughtError);
  var newMessage = this._getMethodNameMessage(methodName, origMessage);

  // If the message in the caught error already has the keyword, ErrorUtil.ERROR_KEY, then we do not want to use
  // the value of 'message'. We only want to use the error message that was originally set. We do not want to
  // prepend an additional messages that were passed to this method in additional catch blocks
  if (!newMessage.includes(ErrorUtil.ERROR_KEY) && !gs.nil(message))
  	newMessage = ErrorUtil.ERROR_KEY + ': ' + message + '\n' + newMessage;

  newMessage += this._getSourceName(caughtError);
  newMessage += this._getErrorObjKeyValue(caughtError, 'lineNumber');

  return new Error(newMessage);
};

/**
* Method that helps to get error message from he error object. The error object can either be an Error or Java
* Exception. Depending upon the type of the object, the way to retrieve the error message is different.
*
* @param {Error} error - The error object.
*
* @return {string} - The error message.
*/
ErrorUtil.prototype.getMessageFromError = function(error) {
  try {
  	if (!gs.nil(error.message))
  		return error.message + '';
  } catch (error) {
  	// Sometimes error object does not contain message and it throws an exception
  }
  return error + '';
};

/**
* Checks if a record exists for the given glide record.
*
* @param {GlideRecord} glideRecord - Glide record that needs to be checked
*
* Throws an exception if there is an error or if hasNext returned false
*/
ErrorUtil.prototype.validateRecordExist = function(glideRecord) {
  this.validateGrForError(glideRecord);
  this.throwOnRecordNotFound(glideRecord);
};

ErrorUtil.prototype.throwOnRecordNotFound = function(glideRecord) {
  if (!glideRecord.hasNext())
  	throw this.getError('No record found in the table ' + glideRecord.getTableName() + ' for the query string: ' +
  		glideRecord.getEncodedQuery());
};

/**
* Validates if there is any error when querying the glide record or if the record exists or not.
*
* A note about GlideRecord::query method. Even though a query business rule fails, the glide record query hasNext()
* will return true and one get all the values. For example, when the following query is run in the back-ground
* script
*
* 		var glideRecord = new GlideRecord('sys_user');
* 		glideRecord.addQuery('sys_id', 'f6911038530360100999ddeeff7b12b3');
* 		glideRecord.query();
* 		gs.info('HasNext: ' + glideRecord.hasNext())
* 		glideRecord.next();
* 		gs.info('UserName: ' + glideRecord.getValue('user_name'));
*
* Even though a BR validation failed, we still see in the output, the HasNext is true and we are able to do
* glideRecord.next() and then get the value of user_name field.
*
* Background message, type:error, message: Query validation failed.
* Operation against file 'sys_user' was aborted by Business Rule 'SysUserQueryBeforeBr^null'. Business Rule
* Stack:SysUserQueryBeforeBr
* sn_hr_core: HasNext: true sn_hr_core: UserName: arron.ubhi
*
*
* @param {GlideRecord} glideRecord - The glide record object on which the query has been made.
*/
ErrorUtil.prototype.validateGrForQuery = function(glideRecord) {
  this.validateGrForError(glideRecord);
  this.throwOnRecordNotFound(glideRecord);
};

/**
* Validates if glide record has any error or not.
*
* @param {GlideRecord} glideRecord - Glide record that has to be validated
*
* Throws an exception if glide.getLastErrorMessage is not null.
*/
ErrorUtil.prototype.validateGrForError = function(glideRecord) {
  if (gs.nil(glideRecord.getLastErrorMessage()))
  	return;

  throw this.getGrError(glideRecord);

};

ErrorUtil.prototype.throwGrError = function(glideRecord) {
  throw this.getGrError(glideRecord);
};

ErrorUtil.prototype.getGrError = function(glideRecord) {
  var errorMessage = '';
  var operation = glideRecord.operation();
  if (gs.nil(operation))
  	operation = ErrorUtil.QUERY;

  errorMessage += 'Error with \'' + operation + '\' operation on the table \'' + glideRecord.getTableName() + '\'. ' +
  	this._getGrEncodedQuery(glideRecord) + this._getGrSetValues(operation, glideRecord) +
  	(gs.nil(glideRecord.getLastErrorMessage()) ? '' : '. ' + glideRecord.getLastErrorMessage());

  return this.getError(errorMessage);
};

ErrorUtil.prototype.throwOnEmptyValue = function(paramName, paramValue) {
  if (!gs.nil(paramValue))
  	return;
  throw this.getError(this._formatUtil.format('The value for the \'{0}\' is null.', paramName));
};

ErrorUtil.prototype._getGrEncodedQuery = function(glideRecord) {
  if (gs.nil(glideRecord.getEncodedQuery()))
  	return '';

  return 'Query: \'' + glideRecord.getEncodedQuery() + '\' ';
};

ErrorUtil.prototype._getGrSetValues = function(operation, glideRecord) {
  if (operation == ErrorUtil.DELETE)
  	return '';

  var GR_SYSTEM_FIELDS = ['sys_updated_on', 'sys_class_name', 'sys_id', 'sys_updated_by', 'sys_created_on',
  	'sys_domain', 'sys_name', 'sys_scope', 'sys_created_by', 'sys_mod_count', 'active', 'sys_package',
  	'sys_update_name', 'sys_tags', 'calendar_integration', 'web_service_access_only', 'notification',
  	'enable_multifactor_authn', 'internal_integration_user'
  ];

  var elements = glideRecord.getElements();
  var setValuesStr = '';
  for (var idx = 0; idx < elements.length; ++idx) {
  	var element = elements[idx];
  	if (gs.nil(element.toString()) || GR_SYSTEM_FIELDS.indexOf(element.getName()) != -1)
  		continue;

  	if (!gs.nil(setValuesStr))
  		setValuesStr += ', ';

  	setValuesStr += element.getName() + '=' + element.toString();
  }
  return ', SetValues: \'' + setValuesStr + '\'';
};

ErrorUtil.prototype.type_of = function(value) {
  if (value === null)
  	return 'null';

  var t = typeof value;
  if ((t == 'string') || (t == 'number') || (t == 'boolean') || (t == 'function'))
  	return t;

  if ((value instanceof String) || ('' + value.constructor).match(/^function String\(\)/))
  	return 'string';

  if (value instanceof Number)
  	return 'number';

  if (value instanceof Boolean)
  	return 'boolean';

  return 'object';
};

ErrorUtil.prototype._getErrorObjKeyValue = function(errorObj, keyName) {
  var value = this._getErrorObjValue(errorObj, keyName);
  if (gs.nil(value))
  	return '';

  return ' ' + keyName + ': ' + value;
};

ErrorUtil.prototype._getErrorObjValue = function(errorObj, keyName) {
  if (gs.nil(errorObj) || !(keyName in errorObj) || (typeof (errorObj[keyName]) === 'function'))
  	return '';
  var value = errorObj[keyName];
  if (gs.nil(value) || value === 0)
  	return '';

  return value;
};


ErrorUtil.prototype._getSourceName = function(caughtError) {
  var fileName = this._getErrorObjValue(caughtError, 'fileName');
  var sourceName = this._getErrorObjValue(caughtError, 'sourceName');

  if (gs.nil(fileName) && gs.nil(sourceName))
  	return '';

  return fileName === sourceName ? (' Source: ' + fileName) : (' Source: ' + fileName + ' ' + sourceName);
};

ErrorUtil.prototype._getMethodNameMessage = function(methodName, message) {

  try {
  	// The comments below explains what the messageArray will contain as entries after the split.
  	//
  	// If we consider the following error message:
  	//
  	// ***~Error: Error closing registration
  	// ErrorMethodName: Close Registration->updateRegistrationState->notifyRegistrationState ## Cannot find
  	// function getState in object [object GlideRecord].
  	//
  	// METHOD_MSG_SEPARATOR is ##. If we consider the above example, the messageArray will contain elements:
  	// messageArray[0] =
  	//       ***~Error: Error closing registration
  	//      ErrorMethodName: Close Registration->updateRegistrationState->notifyRegistrationState
  	// messageArray[1] = Cannot find function getState in object [object GlideRecord].
  	var messageArray = message.split(ErrorUtil.METHOD_MSG_SEPARATOR);
  	if (gs.nil(messageArray) || messageArray.length === 0)
  		return message;

  	// If the message array length is one, then it means that we have not added the method name info. until now. So,
  	// add it and return. The method name info is ErrorMethodName: Close Registration->updateRegistrationState->
  	// notifyRegistrationState
  	if (messageArray.length == 1)
  		return ErrorUtil.HR_METHOD_NAME + ErrorUtil.METHOD_NAME_SEPARATOR + methodName +
  			ErrorUtil.METHOD_MSG_SEPARATOR + message;

  	if (messageArray.length !== 2)
  		return ErrorUtil.HR_METHOD_NAME + ErrorUtil.METHOD_NAME_SEPARATOR + methodName +
  			ErrorUtil.METHOD_MSG_SEPARATOR + message;

  	var methodNameStrSplit = messageArray[0].split(ErrorUtil.METHOD_NAME_SEPARATOR);

  	return ErrorUtil.HR_METHOD_NAME + ErrorUtil.METHOD_NAME_SEPARATOR + methodName + '->' + methodNameStrSplit[1] +
  		ErrorUtil.METHOD_MSG_SEPARATOR + messageArray[1];
  } catch (caughtError) {
  	return message;
  }
};

Sys ID

1fecae6ffb8410101d696a7521706923

Offical Documentation

Official Docs: