Search code examples
javaspring-bootvalidationbean-validation

How to get rid of propertyPath in title attribute Error Response of ConstraintValidatorContext - SpringBoot Custom Validation


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;
}

Solution

  • 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();