I can validate a nested object using an annotation and validator, implementing ConstraintValidator
. The code has a conditional validation statement, where it should validate a nested object.
It is done like so:
@Override
public boolean isValid(ScheduleJobRequest value, ConstraintValidatorContext context) {
if (value.getJobType() != JobType.EXPORT) {
return true; // do not fail
}
final ExportRequestData exportData = value.getExportData();
if (exportData == null) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("NotEmpty")
.addPropertyNode("exportData").addConstraintViolation();
return false;
}
final Set<ConstraintViolation<ExportRequestData>> violations = validator.validate(exportData);
violations.forEach(violation -> context
.buildConstraintViolationWithTemplate(violation.getMessage())
.addConstraintViolation());
return violations.isEmpty();
}
So in case the jobType
enum is EXPORT
, it should evaluate exportData
which is another DTO.
I also have a custom error handler; which works fine on top level validations. This is done by overwriting handleMethodArgumentNotValid
:
I read the BindingResult
there and its FieldErrors
. However, I notice for my nested object in this case, it does not appear in the FieldErrors.
(code snippet):
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
BindingResult bindingResult = ex.getBindingResult();
final List<FieldError> fieldErrors = bindingResult.getFieldErrors();
// this does not show any errors for nested objects
Ideally I want the result to be a path to the property which is invalid. FieldName could be the name itself.
What did I miss?
BTW: whenever I try to set propertyNode
in the validator, like so:
violations.forEach(violation -> context
.buildConstraintViolationWithTemplate(violation.getMessage())
.addPropertyNode(violation.getPropertyPath().toString())
.addConstraintViolation());
I get an error as well (java.lang.IllegalStateException: JSR-303 validated property .... does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)
) which I also can't seem to resolve. (I tried several SO answers).