Я пытаюсь использовать группирующие ограничения с аннотациями на уровне класса.
У меня есть вариант использования, когда 2 объекта относятся к одному и тому же типу "Пример".
public class MyUseCase {
@Valid
private final Example sourceDetail;
@Valid
private final Example destinationDetail;
}
Пример и BaseExample (родительский элемент примера) определены ниже. «Пример» содержит поля с именами field1 и field2. Проверка для sourceDetail зависит только от field1, тогда как проверка для destinationDetail зависит как от field1, так и от field2. Другая проблема - сообщение об ошибке. Для проверки объектов sourceDetail и destinationDetail разные сообщения об ошибках.
public class BaseExample {
@AlphaNumeric(message = "sample error 1")
private String field1;
}
public class Example extends BaseExample {
@AlphaNumeric(min = 9, max = 9, message = "sample error 2")
private final String field2;
@NotNull(message="sample error 3", groups = SomeOtherGroup.class)
private final String anotherRandomField;
}
Чтобы решить эту проблему, я попытался сделать несколько вещей.
Создано два пользовательских ограничения на уровне класса с пропущенными группами.
@DestinationCheck(groups={DestinationGroup.class})
@SourceCheck(groups={SourceGroup.class})
public class Example extends BaseExample {
// code
}
public @interface SourceCheck {
String message() default "some message";
Class<?>[] groups(); // no default group
Class<? extends Payload>[] payload() default {};
}
public @interface DestinationCheck {
String message() default "some other message";
Class<?>[] groups(); // no default group
Class<? extends Payload>[] payload() default {};
}
public class SourceCheckValidator implements ConstraintValidator<SourceCheck, Example> {
@Override
public void initialize(SourceCheck sourceCheck) {
}
@Override
public boolean isValid(Example example, ConstraintValidatorContext context) {
// validation check to ensure just field1 is compulsory
}
}
public class DestinationCheckValidator implements ConstraintValidator<DestinationCheck, Example> {
@Override
public void initialize(DestinationCheck destinationCheck) {
}
@Override
public boolean isValid(Example example, ConstraintValidatorContext context) {
// validation check to ensure only one of field1 or field2 is present
}
}
Наконец, я протестировал проверку в своем десериализаторе, используя:
// exampleName can be either "sourceDetail" or "destinationDetail"
// jsonParser and jsonNode are available via deserializer
example = jsonParser.getCodec().treeToValue(jsonNode.get(exampleName),
Example.class);
if ("sourceDetail".equals(exampleName))
validator.validate(example, SourceGroup.class);
if ("destinationDetail".equals(exampleName))
validator.validate(example, DestinationGroup.class);
Я ожидалэто для проверки исходного объекта 'example' exampleD, но вместо этого он генерирует исключение NullPointerException на шаге validator.validate ().
a. Что здесь пропало? Я передаю группу, как и ожидалось, к аннотации. Есть ли проблема с передачей группы?
b. Способны ли группы использоваться таким образом? Если нет, то каков будет идеальный способ решения этой проблемы, если модель не может быть изменена?
Я также попытался использовать только одну аннотацию для проверки объектов sourceDetail и destinationDetail. Моя аннотация:
@OverallCheck(groups={SourceGroup.class, DestinationGroup.class})
И в валидаторе ограничений у меня было:
@Override
public void initialize(OverallCheck overallCheck) {
String group = overallCheck.groups(). <---- ????
}
Однако проблема в том, что нет способа получить используемую группу валидации то есть, используется ли SourceGroup.class или DestinationGroup.class, в противном случае я мог бы обработать групповую логику в методе isValid ().