All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.odpi.openmetadata.commonservices.ffdc.RESTExceptionHandler Maven / Gradle / Ivy

There is a newer version: 5.1
Show newest version
/* SPDX-License-Identifier: Apache 2.0 */
/* Copyright Contributors to the ODPi Egeria project. */
package org.odpi.openmetadata.commonservices.ffdc;

import org.odpi.openmetadata.commonservices.ffdc.rest.FFDCResponseBase;
import org.odpi.openmetadata.frameworks.auditlog.AuditLog;
import org.odpi.openmetadata.frameworks.auditlog.MessageFormatter;
import org.odpi.openmetadata.frameworks.auditlog.messagesets.ExceptionMessageDefinition;
import org.odpi.openmetadata.frameworks.connectors.ffdc.InvalidParameterException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.OCFCheckedExceptionBase;
import org.odpi.openmetadata.frameworks.connectors.ffdc.PropertyServerException;
import org.odpi.openmetadata.frameworks.connectors.ffdc.UserNotAuthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * RESTExceptionHandler converts standard exceptions to REST responses.  These responses ensure exception objects
 * (with their stack traces) are not serialized over REST APIs.
 *
 * This class does use developer logging (SLF4J) for components that are not mature enough to have implemented
 * FFDC.  For mature components, this logging is superfluous.
 */
public class RESTExceptionHandler
{
    private static final MessageFormatter messageFormatter = new MessageFormatter();

    private static final Logger log = LoggerFactory.getLogger(RESTExceptionHandler.class);


    /**
     * Constructor
     */
    public RESTExceptionHandler()
    {
    }


    /**
     * Manage an unexpected exception
     *
     * @param userId calling user
     * @param methodName method that caught the exception
     * @param serverName name of the server being called
     * @throws InvalidParameterException exception to report error
     */
    public void handleNoRequestBody(String      userId,
                                    String      methodName,
                                    String      serverName) throws InvalidParameterException
    {
        InvalidParameterException error =
                new InvalidParameterException(OMAGCommonErrorCode.NO_REQUEST_BODY.getMessageDefinition(userId,
                                                                                                       methodName,
                                                                                                       serverName),
                                              this.getClass().getName(),
                                              methodName,
                                              "requestBody");

        log.error("No rest body supplied", error);
        throw error;
    }


    /**
     * Throw an exception if it is encoded in the REST response.
     *
     * @param methodName  name of the method called
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws InvalidParameterException one of the parameters is invalid.
     * @throws UserNotAuthorizedException the user is not authorized to make this request.
     * @throws PropertyServerException something went wrong with the REST call stack.
     */
    public void detectAndThrowStandardExceptions(String           methodName,
                                                 FFDCResponseBase restResult) throws InvalidParameterException,
                                                                                     UserNotAuthorizedException,
                                                                                     PropertyServerException
    {
        final String invalidParameterExceptionClassName  = InvalidParameterException.class.getName();
        final String propertyServerExceptionClassName    = PropertyServerException.class.getName();
        final String userNotAuthorizedExceptionClassName = UserNotAuthorizedException.class.getName();

        if (restResult != null)
        {
            String exceptionClassName = restResult.getExceptionClassName();

            if (exceptionClassName != null)
            {
                log.error("FFDC Response: {}", restResult.toString());
                if (exceptionClassName.equals(invalidParameterExceptionClassName))
                {
                    this.throwInvalidParameterException(restResult);
                }
                else if (exceptionClassName.equals(userNotAuthorizedExceptionClassName))
                {
                    this.throwUserNotAuthorizedException(restResult);
                }
                else if (exceptionClassName.equals(propertyServerExceptionClassName))
                {
                    this.throwPropertyServerException(restResult);
                }
                else
                {
                    this.throwUnexpectedException(methodName, restResult);
                }
            }
            else
            {
                log.debug("FFDC Response: {}", restResult.toString());
            }
        }
    }


    /**
     * Throw an InvalidParameterException if it is encoded in the REST response.
     *
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws InvalidParameterException encoded exception from the server
     */
    public void detectAndThrowInvalidParameterException(FFDCResponseBase restResult) throws InvalidParameterException
    {
        final String   exceptionClassName = InvalidParameterException.class.getName();

        if ((restResult != null) && (exceptionClassName.equals(restResult.getExceptionClassName())))
        {
            this.throwInvalidParameterException(restResult);
        }
    }


    /**
     * Throw an InvalidParameterException if it is encoded in the REST response.
     *
     * @param methodName  calling method.
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws InvalidParameterException encoded exception from the server
     */
    @Deprecated
    public void detectAndThrowInvalidParameterException(String methodName, FFDCResponseBase restResult) throws InvalidParameterException
    {
        this.detectAndThrowInvalidParameterException(restResult);
    }


    /**
     * Throw an UserNotAuthorizedException if it is encoded in the REST response.
     *
     * @param methodName  calling method.
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws UserNotAuthorizedException encoded exception from the server
     */
    @Deprecated
    public void detectAndThrowUserNotAuthorizedException(String methodName, FFDCResponseBase restResult) throws UserNotAuthorizedException
    {
        this.detectAndThrowUserNotAuthorizedException(restResult);
    }


    /**
     * Throw an PropertyServerException if it is encoded in the REST response.
     *
     * @param methodName  calling method.
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws PropertyServerException encoded exception from the server
     */
    @Deprecated
    public void detectAndThrowPropertyServerException(String methodName, FFDCResponseBase restResult) throws PropertyServerException
    {
        this.detectAndThrowPropertyServerException(restResult);
    }


    /**
     * Throw an InvalidParameterException if it is encoded in the REST response.
     *
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws InvalidParameterException encoded exception from the server
     */
    private void throwInvalidParameterException(FFDCResponseBase restResult) throws InvalidParameterException
    {
        String parameterName = null;

        Map   exceptionProperties = restResult.getExceptionProperties();

        if (exceptionProperties != null)
        {
            Object  nameObject = exceptionProperties.get("parameterName");

            if (nameObject != null)
            {
                parameterName = (String)nameObject;
            }
        }

        InvalidParameterException error = new InvalidParameterException(restResult.getRelatedHTTPCode(),
                                                                        this.getClass().getName(),
                                                                        restResult.getActionDescription(),
                                                                        restResult.getExceptionErrorMessage(),
                                                                        restResult.getExceptionErrorMessageId(),
                                                                        restResult.getExceptionErrorMessageParameters(),
                                                                        restResult.getExceptionSystemAction(),
                                                                        restResult.getExceptionUserAction(),
                                                                        restResult.getExceptionCausedBy(),
                                                                        parameterName,
                                                                        restResult.getExceptionProperties());

        log.error("Detected Invalid Parameter Exception in REST Response", error);
        throw error;
    }


    /**
     * Throw a PropertyServerException if it is encoded in the REST response.
     *
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws PropertyServerException encoded exception from the server
     */
    public void detectAndThrowPropertyServerException(FFDCResponseBase restResult) throws PropertyServerException
    {
        final String   exceptionClassName = PropertyServerException.class.getName();

        if ((restResult != null) && (exceptionClassName.equals(restResult.getExceptionClassName())))
        {
            this.throwPropertyServerException(restResult);
        }
    }


    /**
     * Throw a PropertyServerException if it is encoded in the REST response.
     *
     * @param restResult  response from the rest call.  This generated in the remote server.
     *
     * @throws PropertyServerException encoded exception from the server
     */
    private void throwPropertyServerException(FFDCResponseBase restResult) throws PropertyServerException
    {
        PropertyServerException error = new PropertyServerException(restResult.getRelatedHTTPCode(),
                                                                    this.getClass().getName(),
                                                                    restResult.getActionDescription(),
                                                                    restResult.getExceptionErrorMessage(),
                                                                    restResult.getExceptionErrorMessageId(),
                                                                    restResult.getExceptionErrorMessageParameters(),
                                                                    restResult.getExceptionSystemAction(),
                                                                    restResult.getExceptionUserAction(),
                                                                    restResult.getExceptionCausedBy(),
                                                                    restResult.getExceptionProperties());

        log.error("Property Server Error Exception returned by REST Call", error);
        throw error;
    }


    /**
     * Throw an UserNotAuthorizedException if it is encoded in the REST response.
     *
     * @param restResult  response from UserNotAuthorizedException encoded exception from the server.
     *
     * @throws UserNotAuthorizedException encoded exception from the server
     */
    public void detectAndThrowUserNotAuthorizedException(FFDCResponseBase restResult) throws UserNotAuthorizedException
    {
        final String   exceptionClassName = UserNotAuthorizedException.class.getName();

        if ((restResult != null) && (exceptionClassName.equals(restResult.getExceptionClassName())))
        {
            this.throwUserNotAuthorizedException(restResult);
        }
    }


    /**
     * Throw an UserNotAuthorizedException if it is encoded in the REST response.
     *
     * @param restResult  response from UserNotAuthorizedException encoded exception from the server.
     *
     * @throws UserNotAuthorizedException encoded exception from the server
     */
    private void throwUserNotAuthorizedException(FFDCResponseBase restResult) throws UserNotAuthorizedException
    {
        String userId = null;

        Map   exceptionProperties = restResult. getExceptionProperties();

        if (exceptionProperties != null)
        {
            Object  userIdObject = exceptionProperties.get("userId");

            if (userIdObject != null)
            {
                userId = (String)userIdObject;
            }
        }

        UserNotAuthorizedException error = new UserNotAuthorizedException(restResult.getRelatedHTTPCode(),
                                                                          this.getClass().getName(),
                                                                          restResult.getActionDescription(),
                                                                          restResult.getExceptionErrorMessage(),
                                                                          restResult.getExceptionErrorMessageId(),
                                                                          restResult.getExceptionErrorMessageParameters(),
                                                                          restResult.getExceptionSystemAction(),
                                                                          restResult.getExceptionUserAction(),
                                                                          restResult.getExceptionCausedBy(),
                                                                          userId,
                                                                          restResult.getExceptionProperties());

        log.error("User Not Authorized Exception", error);
        throw error;
    }


    /**
     * Manage an unexpected exception
     *
     * @param error unexpected exception
     * @param methodName method that caught the exception
     * @param serverName name of the server being called
     * @param serverURL platform URL
     * @throws PropertyServerException wrapping exception for the caught exception
     */
    public void handleUnexpectedException(Throwable   error,
                                          String      methodName,
                                          String      serverName,
                                          String      serverURL) throws PropertyServerException
    {
        log.error("Unexpected runtime exception returned from REST Call", error);

        throw new PropertyServerException(OMAGCommonErrorCode.CLIENT_SIDE_REST_API_ERROR.getMessageDefinition(methodName,
                                                                                                              serverName,
                                                                                                              serverURL,
                                                                                                              error.getMessage()),
                                          this.getClass().getName(),
                                          methodName,
                                          error);
    }


    /**
     * Manage an unexpected exception
     *
     * @param methodName  name of the method called.
     * @param restResult  response from the encoded exception from the server.
     * @throws PropertyServerException wrapping exception for the caught exception
     */
    private void throwUnexpectedException(String           methodName,
                                          FFDCResponseBase restResult) throws PropertyServerException
    {
        log.error(methodName + " returned unexpected exception", restResult);

        throw new PropertyServerException(
                OMAGCommonErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(restResult.getExceptionClassName(),
                                                                              methodName,
                                                                              restResult.getExceptionErrorMessage()),
                this.getClass().getName(),
                methodName);
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response.
     * @param exceptionClassName  class name of the exception to recreate
     */
    protected  void captureCheckedException(FFDCResponseBase        response,
                                            OCFCheckedExceptionBase error,
                                            String                  exceptionClassName)
    {
        this.captureCheckedException(response, error, exceptionClassName, null);
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response.
     * @param exceptionClassName  class name of the exception to recreate
     * @param exceptionProperties map of properties stored in the exception to help with diagnostics
     */
    protected  void captureCheckedException(FFDCResponseBase             response,
                                            OCFCheckedExceptionBase      error,
                                            String                       exceptionClassName,
                                            Map          exceptionProperties)
    {
        response.setRelatedHTTPCode(error.getReportedHTTPCode());
        response.setExceptionClassName(exceptionClassName);
        if (error.getReportedCaughtException() != null)
        {
            response.setExceptionCausedBy(error.getReportedCaughtException().getClass().getName());
        }
        response.setActionDescription(error.getReportingActionDescription());
        response.setExceptionErrorMessage(error.getReportedErrorMessage());
        response.setExceptionErrorMessageId(error.getReportedErrorMessageId());
        response.setExceptionErrorMessageParameters(error.getReportedErrorMessageParameters());
        response.setExceptionSystemAction(error.getReportedSystemAction());
        response.setExceptionUserAction(error.getReportedUserAction());
        response.setExceptionProperties(exceptionProperties);
    }



    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response
     * @param methodName calling method
     */
    public  void captureThrowable(FFDCResponseBase             response,
                                  Throwable                    error,
                                  String                       methodName)
    {
        this.captureThrowable(response, error, methodName, null);
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response
     * @param methodName calling method
     * @param auditLog log location for recording an unexpected exception
     */
    public  void captureThrowable(FFDCResponseBase   response,
                                  Throwable          error,
                                  String             methodName,
                                  AuditLog           auditLog)
    {
        log.error("Exception from " + methodName + " being packaged for return on REST call", error);

        if (error instanceof PropertyServerException)
        {
            capturePropertyServerException(response, (PropertyServerException)error);
        }
        else if (error instanceof UserNotAuthorizedException)
        {
            captureUserNotAuthorizedException(response, (UserNotAuthorizedException)error);
        }
        else if (error instanceof InvalidParameterException)
        {
            captureInvalidParameterException(response, (InvalidParameterException)error);
        }
        else
        {
            String message = error.getMessage();

            if (message == null)
            {
                message = "null";
            }

            ExceptionMessageDefinition messageDefinition = OMAGCommonErrorCode.UNEXPECTED_EXCEPTION.getMessageDefinition(error.getClass().getName(),
                                                                                                                         methodName,
                                                                                                                         message);

            response.setRelatedHTTPCode(messageDefinition.getHttpErrorCode());
            response.setExceptionClassName(PropertyServerException.class.getName());
            response.setExceptionCausedBy(error.getClass().getName());
            response.setActionDescription(methodName);
            response.setExceptionErrorMessage(messageFormatter.getFormattedMessage(messageDefinition));
            response.setExceptionErrorMessageId(messageDefinition.getMessageId());
            response.setExceptionErrorMessageParameters(messageDefinition.getMessageParams());
            response.setExceptionSystemAction(messageDefinition.getSystemAction());
            response.setExceptionUserAction(messageDefinition.getUserAction());
            response.setExceptionProperties(null);


            if (auditLog != null)
            {
                auditLog.logException(methodName,
                                      OMAGCommonAuditCode.UNEXPECTED_EXCEPTION.getMessageDefinition(error.getClass().getName(), methodName, message),
                                      error);
            }
        }
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response.
     */
    public  void captureInvalidParameterException(FFDCResponseBase          response,
                                                  InvalidParameterException error)
    {
        Map  exceptionProperties = error.getRelatedProperties();

        String  parameterName = error.getParameterName();

        if (parameterName != null)
        {
            if (exceptionProperties == null)
            {
                exceptionProperties = new HashMap<>();
            }

            exceptionProperties.put("parameterName", parameterName);
        }

        if (exceptionProperties != null)
        {
            captureCheckedException(response, error, InvalidParameterException.class.getName(), exceptionProperties);
        }
        else
        {
            captureCheckedException(response, error, InvalidParameterException.class.getName());
        }
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response.
     */
    public  void capturePropertyServerException(FFDCResponseBase        response,
                                                PropertyServerException error)
    {
        captureCheckedException(response, error, PropertyServerException.class.getName());
    }


    /**
     * Set the exception information into the response.
     *
     * @param response  REST Response
     * @param error returned response.
     */
    public  void captureUserNotAuthorizedException(FFDCResponseBase           response,
                                                   UserNotAuthorizedException error)
    {
        Map  exceptionProperties = error.getRelatedProperties();

        String  userId = error.getUserId();

        if (userId != null)
        {
            if (exceptionProperties == null)
            {
                exceptionProperties = new HashMap<>();
            }

            exceptionProperties.put("userId", userId);
        }

        if (exceptionProperties != null)
        {
            captureCheckedException(response, error, UserNotAuthorizedException.class.getName(), exceptionProperties);
        }
        else
        {
            captureCheckedException(response, error, UserNotAuthorizedException.class.getName());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy