Spring ConstraintValidator set custom code/rejected value

Viewed 1068

I created a custom class-level ConstraintValidator that validates a certain field if another field has a specific value. Here's the object:

@ValidRequest
public class Request {

  interface ValidationName {}

  @NotBlank(groups = {Default.class})
  private final String fieldName;

  @NotBlank(groups = {ValidationName.class})
  @Length(max = 40, groups = {ValidationName.class})
  private final String fieldValue;

  // Constructor, getters
}

And the class-level ConstraintValidator:

public class ValidRequestImpl implements
  ConstraintValidator<ValidRequest, Request> {

  private Validator validator;

  @Autowired
  public ValidRequestImpl (Validator validator) {
    this.validator = validator;
  }

  @Override
  public void initialize(ValidRequest constraintAnnotation) {}

  @Override
  public boolean isValid(ValidRequest value, ConstraintValidatorContext context) {
    if (!validator.validateProperty(value, "fieldName").isEmpty()) {
      return true;
    }
    if (value.getFieldName().equals("name")) {
      Set<ConstraintViolation<Request>> violations =
        validator.validateProperty(value, "fieldValue", ValidationName.class);
      violations.forEach(violation -> context
        .buildConstraintViolationWithTemplate(violation.getMessage())
        .addPropertyNode("fieldValue")
        .addConstraintViolation());
      context.disableDefaultConstraintViolation();
      return violations.isEmpty();
    }
    return true;
  }
}

This works fine, but the returned errors object isn't very helpful:

"errors": [
  {
    "message": "Please enter a name.",
    "field_name": "request.fieldValue",
    "rejected_value": "com.example.Request@5f017a8c",
    "code": "ValidRequest"
  }
],

Ideally, I would want the rejected_value field to be the actual fieldValue that was passed (in this case empty string), instead of the class-level object. I would also want the code field to be the actual annotation that failed (NotBlank), rather than ValidRequest. context.buildConstraintViolationWithTemplate() doesn't appear to have any methods that allow you to change these fields.

How can I accomplish this?

0 Answers
Related