Как вручную запустить пользовательское аннотированное правило проверки объекта? - PullRequest
0 голосов
/ 17 января 2019

Мне нужно запустить мой пользовательский валидатор на объекте вручную или во время преобразования строки json-string в объект.

Мой dto выглядит следующим образом:

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

В приведенном выше коде PersonType составляется из объекта другого типа. Опять же, есть проверка для этого объекта.

Таким образом, работает нормально.

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

Мне нужно получить запрос json в виде строки. Я знаю @Valid @RequestPart ...., отлично подойдет для составного / смешанного типа. Я хочу что-то вроде этого:

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

Я пробовал как с валидатором springframework, так и с валидатором javax jsr. Ни один из них не работает. Я получаю следующую ошибку:

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

Для следующего запроса:

curl -i -X POST -myURL -H "Authorization: ABC" -F request={} -F file=@view.pdf

Мой валидатор реализует javax.validation.ConstraintValidator следующим образом:

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

Ответы [ 2 ]

0 голосов
/ 09 августа 2019

Поскольку у меня есть другой тип валидатора на основе аннотаций в MyClass или в его полях, я просто использовал следующее:

//org.springframework.validation.SmartValidator
@Autowired
SmartValidator smartValidator
public ResponseEntity<ResponseType> generateResponseExample(@RequestPart(value = "jsonString", required = true) String jsonString, @RequestPart(value = "file", required = true) List<MultipartFile> file){
  //Custom deserializer i did here but not relevant to this question, extra info
  ObjectMapper mapper = new ObjectMapper();
  SimpleModule module = new SimpleModule();
  module.addDeserializer(String.class, new StringDeserializer());
  mapper.registerModule(module);
  MyClass myClass = mapper.readValue(jsonString, MyClass.class);
  BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(myClass, "myClass");
  //This triggers all the annotation of class
  smartValidator.validate(myClass, bindingResult, MyClass.annotationgroup1.class);
  if (bindingResult.hasErrors()) {
        throw new FieldValidationException("Field validation error!", bindingResult);
  }
  //more work..
  return new ResponseEntity<>();
}
0 голосов
/ 17 января 2019

Errors, который вы используете для проверки, не , а Errors, который следует использовать.

Должно работать, если вы будете использовать созданный вручную Errors:

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

Обратите внимание, что BeanPropertyBindingResult реализует Errors

...