Search code examples
javaspring-bootbean-validation

How to trigger custom annotated validation rule of an object manually?


I need to trigger my custom validator on an object either manually or during the json-string to object conversion.

My dto looks as follows:

@NotNullable.List({
    @NotNullable(enumMessage = RequiredFieldErrors.NAME_REQUIRED, fieldName = "info.personName")
//More
})

@SpecificValue.List({
    @SpecificValue(enumMessage = BusinessErrors.CONFIDENTIALITY_REQUESTED, fieldName = "info.personName.confidentialityRequested", value = ConstantValue.CONFIDENTIALITY_VALUES)
//More
})

@DependentField.List({
    @DependentField(
            parentFieldName = "info.personDemographics.ssnUnknown", 
            parentFieldValue = "false", 
            childFieldNames = {"info.personDemographics.ssn"},
            childFieldValues = {ConstantValue.SSN_PATTERN},
            includeChildValues = true,
            enumMessage = RequiredFieldErrors.PAYEE_SSN_MUST_BE_NUMERIC)
//More
})

public class MyClass implements Serializable {
    private static final long serialVersionUID = 1L;
    @SpecificValue(enumMessage = BusinessErrors.SOURCE_ID_INVALID, value = ConstantValue.SOURCE_ID)
    private String sourceId;
    @NotNullable(enumMessage = RequiredFieldErrors.INFO_REQUIRED)
    private PersonType info;
//More
}

In above code, PersonType is being composed from other object type. Again there is validation for those object.

This way working fine.

@RequestMapping(value = "/api/rest/uploadefile", method = {RequestMethod.POST}
public ResponseEntity<Object> upload1(@Valid @RequestBody MyClass request, BindingResult bindingResult, HttpServletRequest request) {        
     if(bindingResult.hasErrors()) {
          throw new FieldValidationException(Contstants.INVALID_REQUEST, errors);
    }
}

I need to get the json request as string. I know @Valid @RequestPart...., will work fine for multipart/mixed type. I want something like this:

@RequestMapping(value = "/api/rest/uploadefile", method = {RequestMethod.POST}, headers = {"content-type=multipart/form-data"})
public ResponseEntity<Object> upload1(@RequestPart(value = "request", required = true) String request, @RequestPart(value = "file", required = true) List<MultipartFile> file, Errors errors) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        MyClass myClass = mapper.readValue(request, MyClass.class);
        ValidationUtils.invokeValidator(validator1, myClass, errors);
        if(errors.hasErrors()) {
                  throw new FieldValidationException(Contstants.INVALID_REQUEST, errors);
        }
}

I tried with both springframework validator as well as javax jsr validator. Neither of them is working. I am getting following error:

class java.lang.IllegalStateException JSR-303 validated property 'info.personName' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access

For following request:

curl -i -X POST -myURL -H "Authorization: ABC" -F request={} -F [email protected]

My validator implements javax.validation.ConstraintValidator as follows:

public class DependentFieldValidator implements ConstraintValidator<DependentField, Object> {
 //My code
}

Solution

  • The Errors you're using for validation are not that Errors that should be used.

    It should work if you will use manually created Errors:

    BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(myClass, "myClass");
    ValidationUtils.invokeValidator(validator, myClass, bindingResult);
    

    Note that BeanPropertyBindingResult implements Errors