0

I want to create custom message for my custom validation annotation. If this validation failed, it throws MethodArgumentNotValidException. Because I put @Valid for the @RequestBody.

I create @ControllerAdvice to handle/ override MethodArgumentNotValidException message. I have this enum error class separately. So every error that throws this kind of exception will throws the same message as Invalid Param

My question is is it possible to exclude my custom validation message and throws different message instead? How to make this @MyCustomAnnotation throws different exception message? Not fall under MethodArgumentNotValidException message.

My custom validation interface

@Documented
@Constraint(validatedBy = myValidator.class)
@Target({FIELD, METHOD, ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckMyCode{
    String message() default "{my custom string message}";
    Class<?> [] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

My controller advice method to handle all MethodArgumentNotValidException exception

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException exception, HttpHeaders headers, HttpStatus status, WebRequest request){
        CustomClassError<Object> error = CustomClassError.failure(ErrCode.INVALID_PARAM);
        return new ResponseEntity<Object>(error, new HttpHeaders(), HttpStatus.OK);
}
chronos14
  • 321
  • 1
  • 5
  • 20

1 Answers1

1

You could override the handleMethodArgumentNotValid method in controller advice like (seems this is the use case you need ):

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    List<String> details = new ArrayList<>();
    for(ObjectError error : ex.getBindingResult().getAllErrors()) {
        details.add(error.getDefaultMessage());
    }
    ErrorResponse error = new ErrorResponse("Validation Failed", details);
    return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
}

Or otherwise in your controller class you could handle it by throwing a custom exception and then handling it separately in your controller advice (not for validation exception but for all other run time exceptions this approach is preferable for handling the exception):

@PostMapping("/addValidate")
public String submitForm(@Valid ValidatedData validatedData,
  BindingResult result, Model m) {
    if(result.hasErrors()) {
         List<FieldError> errors = bindingResult.getFieldErrors(); // provided only for your information
         for (FieldError error : errors ) {
             System.out.println (error.getObjectName() + " - " +error.getDefaultMessage());
          }
        throw new CustomExceptionClass("Your could assign the field error custom message here");
    }
    m.addAttribute("message", "Success"
      + validatedData.toString());
    return "Home";
} 

and then in your controller advice class you could use this message passed to the exception like :

@ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
    List<String> details = new ArrayList<>();
    details.add(ex.getLocalizedMessage()); //just call the message method to get the message in the exception
    ErrorResponse error = new ErrorResponse("Server Error", details); //Custom error response class to return json response
    return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39