Проверка правильности метода или конструктора Hibernate Validator

Как я могу использовать валидатор Hibernate для проверки аргументов внутри конструктора или метода? Я хочу, чтобы проверка происходила до создания ValueObject, чтобы я мог выдать исключение и не создавать объект, если все параметры не являются действительными.

В основном я пытаюсь использовать аннотации вместо того, чтобы делать что-то вроде этого, если это возможно:

public class ConditionalPerson {
    private String name;
    private String surname;
    private int age;

    public ConditionalPerson(String name, String surname, int age){
        if (name == null || surname == null || age < 1) {
            throw new IllegalArgumentException();
        }
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
}

Я пытался следовать этим документам, которые, кажется, работают, но все же приводят к созданию объекта.

public class Person {
    @NotNull(message = "Name can't be null")
    @NotEmpty(message = "Name can't be empty")
    @Length(min=1)
    private String name;

    @NotNull(message = "Surname can't be null")
    @NotEmpty(message = "Surname can't be empty")
    @Length(min=1)
    private String surname;

    @Range(min=100, max=200)
    private int age;

    public Person(String name, String surname, int age){
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
}

Добавление аннотаций к аргументам конструктора, кажется, не имеет никакого эффекта

public Person(@NotNull String name, 
              @NotNull String surname, 
              @Range(min=100, max=200) int age) { 
    ...
}

Как я создаю объекты:

public class Example {
    Person person;
    ConditionalPerson person2;

    public static void main(String[] args) {
        Example example = new Example();
        example.makePerson();
        example.makeConditionalPerson();
    }

    public void makePerson() {
        person = new Person(null, "", 12);
        Validator validator = ValidatorSingleton.getValidator();

        Set<ConstraintViolation<Person>> violations = validator.validate(person);

        if (violations.size() > 0) {
            throw new IllegalArgumentException();
        }
    }

    public void makeConditionalPerson() {
        person2 = new ConditionalPerson(null, "", 123);
    }
}

Оценщик:

public class ValidatorSingleton {
    private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private static final javax.validation.Validator validator = factory.getValidator();

    private ValidatorSingleton(){}

    public static Validator getValidator() {
        return validator;
    }
}

2 ответа

Решение

Для всех, кто найдет этот пост. Я немного изменил свой подход и получил это, используя OVal Validation & AspectJ вместо Hibernate.

В основном тот же пример, что и выше, но мне нужно было добавить @Guarded выше класса:

@Guarded
public class Person {
    private String name;
    private String surname;
    private int age;

    public Person(@NotNull String name, @NotNull String surname, @Range(min=100, max=200) int age){
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
}

Затем в свой build.gradle добавьте:

buildscript {
    repositories {
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.10'
    }
}
dependencies {
    compile 'org.aspectj:aspectjrt:1.8.1'
    compile 'net.sf.oval:oval:1.86'
}

tasks.withType(JavaCompile) {
    doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", destinationDir.toString(),
                         "-aspectpath", classpath.asPath,
                         "-d", destinationDir.toString(),
                         "-classpath", classpath.asPath]

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler)
    }

Вы можете сделать это с помощью hibernate validator, используя refection для проверки аргументов:

public class PersonTest {

private static ExecutableValidator executableValidator;

@BeforeClass
public static void setUp() {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    executableValidator = factory.getValidator().forExecutables();
}
@Test
public void test() throws NoSuchMethodException {
    Constructor<Person> constructor = 
           Person.class.getConstructor(String.class, String.class, int.class);

    Set<ConstraintViolation<Person>> violations = 
         executableValidator.validateConstructorParameters(constructor, new Object[]{null, "", 12});
         assertEquals(2, violations.size());
    }
}
Другие вопросы по тегам