Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DefaultErrorAttributes is not working in SpringBoot 2.0.4 #14211

Closed
abhi4151 opened this issue Aug 27, 2018 · 6 comments
Closed

DefaultErrorAttributes is not working in SpringBoot 2.0.4 #14211

abhi4151 opened this issue Aug 27, 2018 · 6 comments
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@abhi4151
Copy link

abhi4151 commented Aug 27, 2018

I'm throwing a CustomException for every incorrect REST URL in my SpringBoot Application. But DefaultErrorAttributes is not getting executed after upgrading Spring Boot 1.5.4 to 2.0.4 release.

Earlier I was using:

import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;

But Spring boot 2 has changed the above class to:

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;

But after upgrading it is returning BLANK JSON Request. Though while debugging, I'm sure we are throwing CDBaseException.

Below is my implementation of DefaultErrorAttributes defined as a Component.

package cd.webservices.exception;

import java.util.Date;
import java.util.Map;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.ServletWebRequest;

import cd.webservices.service.CDStatisticsCodeFilterService;
import cd.webservices.service.CDStatisticsURLCodeFilterService;
import cd.webservices.utility.CDConstants;
import cd.webservices.utility.CDUtilLogger;

/**
 * CDCustomErrorAttributes class is used for custom exception handling scenarios
 * including signon
 *
 */
@Component
@SuppressWarnings({ "squid:S3776", "squid:S1854" })
public class CDCustomErrorAttributes extends DefaultErrorAttributes {
    private static Logger logger = CDUtilLogger.getInstance();
    @Autowired
    CDStatisticsURLCodeFilterService statisticsURLCodeFilterService;
    @Autowired
    CDStatisticsCodeFilterService statisticsCodeFilterService;

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest requestAttributes, boolean includeStackTrace) {
        CDUtilLogger.error(logger, "Custom exception handling");
        Date timeStamp = null;
        String error = null;
        String exceptionClass = null;
        String exceptionMessage = null;
        String errorURLPath = null;
        Integer status = null;
        Throwable cause = null;
        String causeMessage = null;
        String causeClassName = null;
        Object causeClass = null;
        Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
        Throwable throwable = getError(requestAttributes);
        String[] localexMsg;

        // fetching parent generic exception handling attributes
        if (errorAttributes.keySet() != null) {
            CDUtilLogger.error(logger, "Extracting custom error attributes");
            // key value extraction from error attribute map
            timeStamp = (Date) errorAttributes.get(CDConstants.EXCEPTION_TIMESTAMP);
            status = (Integer) errorAttributes.get(CDConstants.EXCEPTION_STATUS);
            error = (String) errorAttributes.get(CDConstants.EXCEPTION_ERROR);
            exceptionClass = (String) errorAttributes.get(CDConstants.EXCEPTION);
            exceptionMessage = (String) errorAttributes.get(CDConstants.MESSAGELOOKUP_KEYWORD);
            errorURLPath = (String) errorAttributes.get(CDConstants.PATH);
            CDUtilLogger.error(logger, "Respective attributes :");
            CDUtilLogger.error(logger, "Timestamp :" + timeStamp);
            CDUtilLogger.error(logger, "Exception class :" + exceptionClass);
            CDUtilLogger.error(logger, "Status :" + status);
            CDUtilLogger.error(logger, "Error :" + error);
            CDUtilLogger.error(logger, "Exception message :" + exceptionMessage);
            CDUtilLogger.error(logger, "Error URL path :" + errorURLPath);
            // removing unnecessary attributes from generic exception
            errorAttributes.remove(CDConstants.EXCEPTION_TIMESTAMP);
            errorAttributes.remove(CDConstants.EXCEPTION_STATUS);
            errorAttributes.remove(CDConstants.EXCEPTION_ERROR);
            errorAttributes.remove(CDConstants.EXCEPTION);
            errorAttributes.remove(CDConstants.EXCEPTION_PATH);
            errorAttributes.remove(CDConstants.MESSAGELOOKUP_KEYWORD);
        }
        int throwableerrocode = 0;
        // fetching throwable attributes for respective child exceptions
        if (null != throwable && null != throwable.getCause()) {
            cause = throwable.getCause();
            if (cause.getClass() != null && cause.getClass().getSimpleName() != null && throwable.getMessage() != null
                    && throwable.getMessage().length() > 0) {
                causeMessage = throwable.getMessage();
                causeClass = cause.getClass();
                causeClassName = cause.getClass().getSimpleName();
                CDUtilLogger.error(logger, "Respective throwable attributes");
                CDUtilLogger.error(logger, "Cause class :" + causeClassName);
                CDUtilLogger.error(logger, "Cause message :" + causeMessage);
                CDUtilLogger.error(logger, "Cause class :" + causeClass);
                CDUtilLogger.error(logger, "Error URL path :" + errorURLPath);
            }
        }
        if (throwable != null && (throwable instanceof CDBaseException)) {
            throwableerrocode = ((CDBaseException) throwable).getCode();
        }
        if (exceptionClass != null) {
            if (exceptionClass.equalsIgnoreCase(CDConstants.BASE_EXCEPTION_CLASS)) {
                if (exceptionMessage != null && exceptionMessage.length() > 0) {
                    int errorCode = 400;
                    // extraction of custom error message from parent exception
                    if (exceptionMessage.contains(CDConstants.COLON)) {
                        if (exceptionMessage.contains("\"errorMessage\"")) {
                            exceptionMessage = exceptionMessage
                                    .substring(exceptionMessage.indexOf("\"errorMessage\" : \""),
                                            exceptionMessage.lastIndexOf('\"'))
                                    .replace("\"errorMessage\" : \"", "");
                        } else {
                            exceptionMessage = exceptionMessage
                                    .substring(exceptionMessage.lastIndexOf(CDConstants.COLON) + 2);
                        }
                        if (throwableerrocode != 0) {
                            errorCode = throwableerrocode;
                        } else {
                            errorCode = CDConstants.BAD_REQUEST_CODE;
                        }

                        CDCustomExceptionCodes cdExceptionCode = CDCustomExceptionCodes.valueOf(errorCode);
                        localexMsg = exceptionMessage.split(CDConstants.EXCEPTION_MSG_SPLITER);
                        if (localexMsg.length > 1) {
                            errorAttributes.put(CDConstants.ERROR_CODE, Integer.parseInt(localexMsg[1].trim()));
                            errorAttributes.put(CDConstants.ERROR_MESSAGE, localexMsg[0]);
                            errorCode = Integer.parseInt(localexMsg[1].trim());
                        } else {
                            if (throwableerrocode != 0)
                                errorCode = throwableerrocode;
                            errorAttributes.put(CDConstants.ERROR_CODE, errorCode);
                            errorAttributes.put(CDConstants.ERROR_MESSAGE, localexMsg[0]);
                        }
                        CDUtilLogger.error(logger, localexMsg[0]);
                        switch (cdExceptionCode) {
                        case BAD_REQUEST:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.BAD_REQUEST.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case UNAUTHORIZED:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.UNAUTHORIZED.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case FORBIDDEN:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.FORBIDDEN.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case NOT_FOUND:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.NOT_FOUND.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case CONFLICT:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.CONFLICT.value(),
                                    WebRequest.SCOPE_REQUEST);
                            break;
                        case INTERNAL_SERVER_ERROR:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.INTERNAL_SERVER_ERROR.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case NOT_IMPLEMENTED:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.NOT_IMPLEMENTED.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case METHOD_NOT_ALLOWED:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.METHOD_NOT_ALLOWED.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case NO_CONTENT:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.NO_CONTENT.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case NOT_ACCEPTABLE:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.NOT_ACCEPTABLE.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case PAYLOAD_TOO_LARGE:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.PAYLOAD_TOO_LARGE.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case REQUEST_TIMEOUT:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.REQUEST_TIMEOUT.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case URI_TOO_LONG:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.URI_TOO_LONG.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        case TOO_MANY_REQUESTS:
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.TOO_MANY_REQUESTS.value(), WebRequest.SCOPE_REQUEST);
                            break;
                        default:
                            errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
                            errorAttributes.put(CDConstants.ERROR_MESSAGE,
                                    CDConstants.REQUEST_NOT_COMPLETED_ERROR_MESSAGE);
                            CDUtilLogger.error(logger, CDConstants.INVALID_PORT_LOG);
                            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                    HttpStatus.NOT_IMPLEMENTED.value(), WebRequest.SCOPE_REQUEST);
                        }
                    } else {
                        errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.BAD_REQUEST.value());
                        errorAttributes.put(CDConstants.ERROR_MESSAGE, exceptionMessage);
                        CDUtilLogger.error(logger, exceptionMessage);
                        requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.BAD_REQUEST.value(),
                                WebRequest.SCOPE_REQUEST);
                    }
                } else {
                    errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
                    errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                    CDUtilLogger.error(logger, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                    requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.NOT_IMPLEMENTED.value(),
                            WebRequest.SCOPE_REQUEST);
                }
            } else if (exceptionClass.contains(CDConstants.ILLEGAL_ARGUMENT_EXCEPTION)) {
                if (exceptionMessage != null && exceptionMessage.length() > 0) {
                    if (exceptionMessage.contains(CDConstants.BASE_ENCODING_DECODING_TOKEN_ERROR)) {
                        errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.FORBIDDEN.value());
                        errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.INVALID_ACCESS_TOKEN);
                        CDUtilLogger.error(logger, CDConstants.INVALID_ACCESS_TOKEN);
                        requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.FORBIDDEN.value(),
                                WebRequest.SCOPE_REQUEST);
                    } else {
                        errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
                        errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                        CDUtilLogger.error(logger, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                        requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                                HttpStatus.NOT_IMPLEMENTED.value(), WebRequest.SCOPE_REQUEST);
                    }
                } else {
                    errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
                    errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                    CDUtilLogger.error(logger, CDConstants.NULL_MESSAGE_ENCOUNTER_ERROR);
                    requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.NOT_IMPLEMENTED.value(),
                            WebRequest.SCOPE_REQUEST);
                }

            }

            else if (exceptionClass.contains(CDConstants.HTTP_MEDIA_TYPE_EXCEPTION)) {
                errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.UNSUPPORTED_MEDIA_TYPE.value());
                errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.CONTENT_TYPE_ERROR_MESSAGE);
                CDUtilLogger.error(logger, "Unsupported media type encountered for given request");
                requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE,
                        HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), WebRequest.SCOPE_REQUEST);
            }

            else if (exceptionClass.contains(CDConstants.REDIS_CONNECTION_FAILURE_EXCEPTION)) {
                errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.SERVICE_UNAVAILABLE.value());
                errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.REDIS_CONNECTION_REFUSE_MSG);
                CDUtilLogger.error(logger, CDConstants.REDIS_CONNECTION_REFUSE_MSG);
                requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.SERVICE_UNAVAILABLE.value(),
                        WebRequest.SCOPE_REQUEST);
            }

            else {
                errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
                errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.REQUEST_NOT_COMPLETED_ERROR_MESSAGE);
                CDUtilLogger.error(logger, CDConstants.INVALID_PORT_LOG);
                requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.NOT_IMPLEMENTED.value(),
                        WebRequest.SCOPE_REQUEST);
            }
        } else if (errorURLPath.equalsIgnoreCase(CDConstants.SIGN_ON_URL)
                && exceptionMessage.equalsIgnoreCase(CDConstants.SIGNON_ERROR)) {
            errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.METHOD_NOT_ALLOWED.value());
            errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.HTTP_METHOD_NOT_ALLOWED_ERROR_MESSAGE);
            CDUtilLogger.error(logger, "Http method not supported");
            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.METHOD_NOT_ALLOWED.value(),
                    WebRequest.SCOPE_REQUEST);
        } else if (exceptionMessage.contains(CDConstants.CSRF_VALUE)) {
            errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.UNAUTHORIZED.value());
            errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.INVALID_CSRF_MESSAGE);
            CDUtilLogger.error(logger, "Unauthorized: Invalid CSRF token");
            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.UNAUTHORIZED.value(),
                    WebRequest.SCOPE_REQUEST);
        } else {
            errorAttributes.put(CDConstants.ERROR_CODE, HttpStatus.NOT_IMPLEMENTED.value());
            errorAttributes.put(CDConstants.ERROR_MESSAGE, CDConstants.REQUEST_NOT_COMPLETED_ERROR_MESSAGE);
            CDUtilLogger.error(logger, CDConstants.INVALID_PORT_LOG);
            requestAttributes.setAttribute(CDConstants.SERVLET_STATUS_CODE, HttpStatus.NOT_IMPLEMENTED.value(),
                    WebRequest.SCOPE_REQUEST);
        }

        String errorcode = null;
        String pathurl = (((ServletWebRequest) requestAttributes).getRequest()).getMethod() + " " + errorURLPath;

        if (null != errorAttributes && errorAttributes.get(CDConstants.ERROR_CODE) != null) {
            errorcode = errorAttributes.get(CDConstants.ERROR_CODE).toString();
        } else {
            CDCustomExceptionCodes a = CDCustomExceptionCodes.INTERNAL_SERVER_ERROR;
            errorcode = a.getCodeAsString();
        }
        CDUtilLogger.info(logger, "Calling method to increment Statistics Counter");
        statisticsURLCodeFilterService.increaseCount(pathurl, Integer.parseInt(errorcode));
        statisticsCodeFilterService.increaseCount(pathurl, Integer.parseInt(errorcode));
        return errorAttributes;
    }
}

Below is my implementation of CustomException:

public class CDBaseException extends RuntimeException {
public CDBaseException(int code,String message,Exception ex) {
        super(message,ex);
        this.message=message;
        this.code=code;
    }
}

And here is how I'm throwing this Exception:

private static void isUriInvalid(boolean isValidUri) {
        if (!isValidUri) {
            throw new CDBaseException(HttpStatus.BAD_REQUEST.value(), CDConstants.URL_NOT_FOUND_MSG);

        }
    }

My only concern is, before upgrading SpringBoot it was working fine. But not working now. Am I doing anything wrong?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 27, 2018
@philwebb
Copy link
Member

It's hard to tell from the code snippets what's happening. Please can you share a minimal project that reproduces the issue.

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Aug 27, 2018
@abhi4151
Copy link
Author

I'm afraid but I don't have any minimal project to reproduce this issue, or may be could you help me with any working example of Spring boot 2 default error attributes?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 29, 2018
@abhi4151
Copy link
Author

@philwebb today I again downgraded my application to 1.5.15 and it is again working. But as soon I upgrade to 2.0.x it doesn't work. Any Idea what could be the possible issue?

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Aug 30, 2018
@snicoll
Copy link
Member

snicoll commented Aug 30, 2018

@abhi4151 if you want us to take the time to look at this, please take the time to assemble a small sample that we can run ourselves.

@abhi4151 abhi4151 closed this as completed Sep 5, 2018
@abhi4151
Copy link
Author

abhi4151 commented Sep 5, 2018

I'm sorry but I didn't get the time to provide you a sample one. I'm continuing with 1.5.15 version.

@philwebb philwebb added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged labels Sep 5, 2018
@otidh
Copy link

otidh commented Sep 14, 2018

I'm facing the same issue. I solved it by following the workaround in this link spring-projects/spring-security#4467

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

5 participants