protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
	logger.info(ex.getClass().getName());
	//
	final List<String> errors = new ArrayList<String>();
	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);
}

        

@ControllerAdvice
public class ApiValidationExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers, 
            HttpStatus status,
            WebRequest request
    ) {
        BindingResult bindingResult = ex
                .getBindingResult();

        List<ApiFieldError> apiFieldErrors = bindingResult
                .getFieldErrors()
                .stream()
                .map(fieldError -> new ApiFieldError(
                        fieldError.getField(),
                        fieldError.getCode(),
                        fieldError.getRejectedValue())
                )
                .collect(toList());

        List<ApiGlobalError> apiGlobalErrors = bindingResult
                .getGlobalErrors()
                .stream()
                .map(globalError -> new ApiGlobalError(
                        globalError.getCode())
                )
                .collect(toList());

        ApiErrorsView apiErrorsView = new ApiErrorsView(apiFieldErrors, apiGlobalErrors);

        return new ResponseEntity<>(apiErrorsView, HttpStatus.UNPROCESSABLE_ENTITY);
    }
}

        

@ExceptionHandler(BindException.class) // (1)
@ResponseStatus(value = HttpStatus.BAD_REQUEST) // (2)
@ResponseBody // (3)
public ErrorResults handleBindException(BindException e, Locale locale) { // (4)
	// (5)
	ErrorResults errorResults = new ErrorResults();
	for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
		errorResults.add(fieldError.getCode(),
				messageSource.getMessage(fieldError, locale),
				fieldError.getField());
	}
	for (ObjectError objectError : e.getBindingResult().getGlobalErrors()) {
		errorResults.add(objectError.getCode(),
				messageSource.getMessage(objectError, locale),
				objectError.getObjectName());
	}
	return errorResults;
}

        

protected ResponseEntity<Object> handleBindException
  (BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    logger.error("400 Status Code", ex);
    BindingResult result = ex.getBindingResult();
    GenericResponse bodyOfResponse = 
      new GenericResponse(result.getFieldErrors(), result.getGlobalErrors());
     
    return handleExceptionInternal(
      ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}

        

protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

	BindingResult bindingResult = ex.getBindingResult();
	List<FieldError> fieldErrors = bindingResult.getFieldErrors();
	List<ApiError> apiErrors = fieldErrors.stream()
			.map(this::createApiError)
			.collect(Collectors.toList());
	List<ObjectError> globalErrors = bindingResult.getGlobalErrors();
	apiErrors.addAll(globalErrors.stream()
			.map(e -> new ApiError(e.getCode(), null, e.getDefaultMessage()))
			.collect(Collectors.toList()));

	return new ResponseEntity(apiErrors, status);
}

        

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorVM processValidationError(MethodArgumentNotValidException ex) {
    BindingResult result = ex.getBindingResult();
    FieldErrorVM dto = new FieldErrorVM(ErrorConstants.ERR_VALIDATION, translate(ErrorConstants.ERR_VALIDATION));
    for (FieldError fieldError : result.getFieldErrors()) {
        dto.add(fieldError.getObjectName(), fieldError.getField(), fieldError.getCode());
    }
    for (ObjectError globalError : result.getGlobalErrors()) {
        dto.add(globalError.getObjectName(), globalError.getObjectName(), globalError.getCode());
    }
    return dto;
}

        

public ApiError createBindingResultApiError(WebRequest request, String errorCode, BindingResult bindingResult, String defaultErrorMessage) {
    ApiError apiError = createApiError(request, errorCode, defaultErrorMessage);
    for (FieldError fieldError : bindingResult.getFieldErrors()) {
        apiError.addDetail(createApiError(request, fieldError, fieldError.getField()));
    }
    for (ObjectError objectError : bindingResult.getGlobalErrors()) {
        apiError.addDetail(createApiError(request, objectError, objectError.getObjectName()));
    }
    return apiError;
}

        

public ValidationErrorMessage createBody(MethodArgumentNotValidException ex, HttpServletRequest req) {
    ErrorMessage tmpl = super.createBody(ex, req);
    ValidationErrorMessage msg = new ValidationErrorMessage(tmpl);
    BindingResult result = ex.getBindingResult();
    for (ObjectError err : result.getGlobalErrors()) {
        msg.addError(err.getDefaultMessage());
    }
    for (FieldError err : result.getFieldErrors()) {
        msg.addError(err.getField(), err.getRejectedValue(), err.getDefaultMessage());
    }
    return msg;
}

        

protected JsonResponse populateJsonValidationErrors(EntityForm form, BindingResult result, JsonResponse json) {
    List<Map<String, Object>> errors = new ArrayList<Map<String, Object>>();
    for (FieldError e : result.getFieldErrors()) {
        Map<String, Object> errorMap = new HashMap<String, Object>();
        errorMap.put("errorType", "field");
        String fieldName = e.getField().substring(e.getField().indexOf("[") + 1, e.getField().indexOf("]")).replace("_", "-");
        errorMap.put("field", fieldName);
        errorMap.put("message", translateErrorMessage(e));
        errorMap.put("code", e.getCode());
        String tabFieldName = fieldName.replaceAll("-+", ".");
        Tab errorTab = form.findTabForField(tabFieldName);
        if (errorTab != null) {
            errorMap.put("tab", errorTab.getTitle());
        }
        errors.add(errorMap);
    }
    for (ObjectError e : result.getGlobalErrors()) {
        Map<String, Object> errorMap = new HashMap<String, Object>();
        errorMap.put("errorType", "global");
        errorMap.put("code", e.getCode());
        errorMap.put("message", translateErrorMessage(e));
        errors.add(errorMap);
    }
    json.with("errors", errors);
    return json;
}

        

public static List<String> getGlobalErrors(MessageSource messageSource, BindingResult bindingResult, Locale locale) {
    List<String> globalErrors = new ArrayList<String>();
    for (ObjectError oe : bindingResult.getGlobalErrors()) {
        String message = getMessage(messageSource, oe, locale);
        globalErrors.add(message);
    }
    return globalErrors;
}        
main