Группировка ограничений с проверкой на уровне класса - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь использовать группирующие ограничения с аннотациями на уровне класса.

У меня есть вариант использования, когда 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 ().

...