Introduction

In this tutorial, we'll discuss how to create a custom REST error JSON message in Spring by extending a common error response with a custom field. We can also change the whole error response, but for the sake of this article, we'll just add one field. When we know how to do that, every other error response modification is pretty intuitive.

We'll show how to add the errorCode field to our REST response. For example, this field could be very useful for multilingual applications and translations of your errors. This is how the end result will look like:

{
    "timestamp": 1592848174387,
    "status": 400,
    "error": "Invalid companyNumber length",
    "message": "Invalid companyNumber length",
    "path": "/api/customers",
    "errorCode": "INVALID_COMPANY_NUMBER"
}

Implementation

The first step would be to create a custom Exception class that extends RuntimeException and that contains our errorCode field. We extend this class with multiple Exception classes that would have their own HTTP statuses and use them in the application.
public class ApplicationException extends RuntimeException {

	private static final long serialVersionUID = -7833944617870666386L;

	ErrorCode errorCode;

	public ErrorCode getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(ErrorCode errorCode) {
		this.errorCode = errorCode;
	}

	public ApplicationException() {
		super();
	}

	public ApplicationException(String message, ErrorCode errorCode) {
		super(message);
		this.errorCode = errorCode;
	}

	public ApplicationException(String message, ErrorCode errorCode) {
		super(message);
		this.errorCode = errorCode;
	}
}
The most important part of the code is the following bean that you should add to your main application class:
 @Bean
    public ErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes() {
            @Override
            public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {

                Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);

                Throwable error = getError(webRequest);

                if (error instanceof ApplicationException) {
                    ApplicationException myException = (ApplicationException) error;
                    errorAttributes.put("errorCode", myException.getErrorCode());
                    errorAttributes.put("message", myException.getMessage());
                    errorAttributes.put("error", myException.getLocalizedMessage());
                }
                return errorAttributes;
            }
        };
    }

So, here we check if our error is instance of ApplicationException, and if it is, we fill our custom errorCode field with errorCode provided to this error's constructor.