0

I implemented custom validation annotation for a request in Spring Rest Controller which validates if field2 is available in the input request body, then field1 should not be empty. My question is how do I get rid of Field UserInputDTO.userInputDTO in my error response (before passing it to the ExceptionHandler)?

Note: I need this because I don't want to expose sensitive data(Class name and Instance name) in the error response. I debugged this and tried but failed to remove the default path or base path(from PathImpl) from the object ConstraintValidatorContextImpl.

Error Response

{
status : 400
title : Bad Request: Field 'UserInputDTO.userInputDTO' : field1 should not be empty if Field2 is present
}

Annotation Class

@Documented
@Constraint(validatedBy = UserInputValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UserInputConstraint {
    String message() default "Invalid request";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

Validator Class

public class UserInputValidator implements
  ConstraintValidator<UserInputConstraint, UserInputDTO> {

    @Override
    public void initialize(UserInputConstraint userInputConstraint) {
    }

    @Override
    public boolean isValid(UserInputDTO userInputDTO,
      ConstraintValidatorContext cxt) {
        boolean isValid=true;
        String errorMessage = null;
        if (userInputDTO.field2 != null && userInputDTO.field1 == null) {
               isValid = false;
              context.buildConstraintViolationWithTemplate("field1 should not be empty if Field2 is presen").addConstraintViolation();
    }
       return isValid;
}
  • Are you handle `ConstraintViolationExecption` in your exception handler ? – Eklavya Jun 20 '20 at 07:55
  • Yes but it is being handled by the core framework libraries from our project. So I have to get rid of it before handling the exception. I found this one very straightforward and applied the same. [link](https://stackoverflow.com/a/37747771/6286156) – befocused47 Jun 21 '20 at 08:07
  • You can override the the exception handler, see my answer for details – Eklavya Jun 21 '20 at 08:09

1 Answers1

1

You can @Override handleMethodArgumentNotValid and customize your error response body.

Example:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

  @Override
  public ResponseEntity<Object> handleMethodArgumentNotValid(
      MethodArgumentNotValidException exception, HttpHeaders headers, HttpStatus status,
      WebRequest request) {   
    List<Object> errors = new ArrayList<Object>();
    for (FieldError fielderror : exception.getBindingResult().getFieldErrors()) {
      Map<String, Object> error = new HashMap<>();
      error.put("code", fielderror.getCode());
      error.put("message", fielderror.getDefaultMessage());
      errors.add(error);
    }
    return new ResponseEntity<>(errors, apiError.getStatus());
  }
} 

And disable DefaultConstraintViolation in annotation validator

context.disableDefaultConstraintViolation();
Eklavya
  • 17,618
  • 4
  • 28
  • 57
  • 1
    Worth mentioning that depending on WHAT he's trying to validate a ConstraintViolationExecption is thrown instead of a MethodArgumentNotValidException. Request body validation will throw a MethodArgumentNotValidException but at many other places the ConstraintValidator will throw a ConstraintViolationExecption and the exception won't be caught in the "handleMethodArgumentNotValid" method. –  Dec 16 '21 at 15:09