Как ограничить проверку в мастере Play?

Я использую Play Framework 2.2.1 и реализовал свой собственный мастер из этого образец. Но у меня проблема с проверкой, потому что пользователь определяет больше «адресов» и на разных этапах моего мастера.

Вот мой класс Person:

import javax.validation.Valid;

public class Person {

    @Valid
    private Address permanentAddress;    // restrict the validation to the Step1

    @Valid
    private Address invoiceAddress;      // restrict the validation to the Step2

    // ...
}

Вот мой адресный класс:

import play.data.validation.Constraints.Required;

public class Address {

    @Required(groups = { Step1.class, Step2.class })
    private String street;

    @Required(groups = { Step1.class, Step2.class })
    private String number;

    // ...
}

Проверка на шаге 1 завершается сбоем, так как атрибуты "улица" и "номер" имеют значение NULL/пусты в "invoiceAddress". Вот фрагмент моего контроллера:

private static Result handleStep1Submission() {
    Form<Person> filledForm = form(Person.class, Step1.class).bindFromRequest();

    if (filledForm.hasErrors()) {
         // this now fails because "invoiceAddress.street" and
         // "invoiceAddress.number" are null/empty
    } else {
         // ...
}

Как в этом случае ограничить проверку Шагом 1 или Шагом 2?


person lu_ko    schedule 19.02.2014    source источник


Ответы (1)


Хороший вопрос. Я могу придумать два (неэлегантных) способа обойти вашу проблему. К сожалению, я не думаю, что код проверки Play изначально поддерживает эту ситуацию:

Вариант 1: специальная проверка

Это рекомендуемый подход, если вы хотите применить некоторые изящные правила проверки, которые Play не предоставит вам из коробки (например, проверка между полями). Если вы определите метод validate в своем классе формы, Play найдет его через отражение и вызовет его после обработки всех аннотаций проверки:

public class Person {

    // New field, gets populated by a hidden field in your HTML form
    private int step;

    private Address permanentAddress;    // restrict the validation to the Step1

    private Address invoiceAddress;      // restrict the validation to the Step2

    // ...

    public String validate() {

        if (step == 1) {
            // manually validate permanentAddress
        }

        if (step == 2) {
            // manually validate invoiceAddress
        }
    }
}

Поскольку вся проверка теперь является специальной и не зависит от аннотаций, вы можете удалить свои аннотации из Address:

public class Address {

    private String street;

    private String number;

    // ...
}

Дополнительные сведения о регистрации метода проверки см. в документации.

Вариант 2: Адрес подкласса

Если первый вариант не кажется вам привлекательным, вы можете создать Address подклассов (возможно, извлекая интерфейс в процессе):

public interface Address {

    public String getStreet();

    public String getNumber();

    // ...
}


import play.data.validation.Constraints.Required;

public class PermanentAddress implements Address {

    @Required(groups = {Step1.class})
    private String street;

    @Required(groups = {Step1.class})
    private String number;

    // ...
}


import play.data.validation.Constraints.Required;

public class InvoiceAddress implements Address {

    @Required(groups = {Step2.class})
    private String street;

    @Required(groups = {Step2.class})
    private String number;

    // ...
}


import javax.validation.Valid;

public class Person {

    @Valid
    private PermanentAddress permanentAddress;

    @Valid
    private InvoiceAddress invoiceAddress;

    // ...
}
person avik    schedule 19.02.2014
comment
Спасибо за ответ. Я рассмотрел ваши оба варианта. 1.option: я не хотел разбивать проверку на 2 части (аннотацию и метод validate()). 2.вариант: я не хотел менять свою модель и повторять одни и те же аннотации в одних и тех же полях, но я реализовал этот 2.вариант. :( - person lu_ko; 20.02.2014