package org.baeldung.web; import java.util.ArrayList; import java.util.List; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import org.springframework.beans.TypeMismatchException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; @ControllerAdvice public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler { // 400 @Override protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final List errors = new ArrayList(); for (final FieldError error : ex.getBindingResult().getFieldErrors()) { errors.add(error.getField() + ": " + error.getDefaultMessage()); } for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) { errors.add(error.getObjectName() + ": " + error.getDefaultMessage()); } final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request); } @Override protected ResponseEntity handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final List errors = new ArrayList(); for (final FieldError error : ex.getBindingResult().getFieldErrors()) { errors.add(error.getField() + ": " + error.getDefaultMessage()); } for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) { errors.add(error.getObjectName() + ": " + error.getDefaultMessage()); } final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request); } @Override protected ResponseEntity handleTypeMismatch(final TypeMismatchException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final String error = ex.getValue() + " value for " + ex.getPropertyName() + " should be of type " + ex.getRequiredType(); final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } @Override protected ResponseEntity handleMissingServletRequestPart(final MissingServletRequestPartException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final String error = ex.getRequestPartName() + " part is missing"; final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } @Override protected ResponseEntity handleMissingServletRequestParameter(final MissingServletRequestParameterException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final String error = ex.getParameterName() + " parameter is missing"; final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } // @ExceptionHandler({ MethodArgumentTypeMismatchException.class }) public ResponseEntity handleMethodArgumentTypeMismatch(final MethodArgumentTypeMismatchException ex, final WebRequest request) { logger.info(ex.getClass().getName()); // final String error = ex.getName() + " should be of type " + ex.getRequiredType().getName(); final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } @ExceptionHandler({ ConstraintViolationException.class }) public ResponseEntity handleConstraintViolation(final ConstraintViolationException ex, final WebRequest request) { logger.info(ex.getClass().getName()); // final List errors = new ArrayList(); for (final ConstraintViolation violation : ex.getConstraintViolations()) { errors.add(violation.getRootBeanClass().getName() + " " + violation.getPropertyPath() + ": " + violation.getMessage()); } final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } // 404 @Override protected ResponseEntity handleNoHandlerFoundException(final NoHandlerFoundException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final String error = "No handler found for " + ex.getHttpMethod() + " " + ex.getRequestURL(); final ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, ex.getLocalizedMessage(), error); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } // 405 @Override protected ResponseEntity handleHttpRequestMethodNotSupported(final HttpRequestMethodNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final StringBuilder builder = new StringBuilder(); builder.append(ex.getMethod()); builder.append(" method is not supported for this request. Supported methods are "); ex.getSupportedHttpMethods().forEach(t -> builder.append(t + " ")); final ApiError apiError = new ApiError(HttpStatus.METHOD_NOT_ALLOWED, ex.getLocalizedMessage(), builder.toString()); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } // 415 @Override protected ResponseEntity handleHttpMediaTypeNotSupported(final HttpMediaTypeNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { logger.info(ex.getClass().getName()); // final StringBuilder builder = new StringBuilder(); builder.append(ex.getContentType()); builder.append(" media type is not supported. Supported media types are "); ex.getSupportedMediaTypes().forEach(t -> builder.append(t + " ")); final ApiError apiError = new ApiError(HttpStatus.UNSUPPORTED_MEDIA_TYPE, ex.getLocalizedMessage(), builder.substring(0, builder.length() - 2)); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } // 500 @ExceptionHandler({ Exception.class }) public ResponseEntity handleAll(final Exception ex, final WebRequest request) { logger.info(ex.getClass().getName()); logger.error("error", ex); // final ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred"); return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); } }