Ошибка "Ошибка проверки: значение недействительна" от f: datetimeConverter

Следующий код создает два переключателя. Каждая опция содержит значение даты, которое успешно преобразуется в метку формата "yyyy-MM-dd". Как только я сделаю выбор и нажмите следующую кнопку, я получаю следующую ошибку: "j_idt12: comDateChoice: Ошибка проверки: значение недействительно". Это кажется простым, но что-то не так. Может ли кто-нибудь из вас определить это?

Я использую JSF 2.0 в стеклянной рыбке.

Поддержка bean

public List<SelectItem> getComDateList() {
    List<SelectItem> items = new ArrayList<SelectItem>();
    Calendar cal = GregorianCalendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, 1);
    cal.add(Calendar.MONTH, 1);
    Date nextFirst = cal.getTime();
    cal.add(Calendar.MONTH, 1);
    Date followingFirst = cal.getTime();
    items.add(new SelectItem(nextFirst, new SimpleDateFormat("yyyy-MM-dd").format(nextFirst)));
    items.add(new SelectItem(followingFirst, new SimpleDateFormat("yyyy-MM-dd").format(followingFirst)));
    return items;
}

Код JSF

<h:panelGrid columns="2">
                    <h:outputLabel value="#{msg.FinanceCommencementDate}" for="comDateChoice"/>
                    <h:selectOneRadio id="comDateChoice" value="#{signUpBean.current.commencementDate}" layout="pageDirection">
                        <f:convertDateTime type="date" dateStyle="short"/>
                        <f:selectItems  value="#{signUpBean.comDateList}"/>
                    </h:selectOneRadio>
                </h:panelGrid>

Ответы

Ответ 1

Эта ошибка возникает, если выбранное значение элемента не прошло проверку Object#equals() на любом из доступных значений элемента выбора. Это может произойти, если геттер вернул другой список во время фазы запроса запроса запроса запроса формы, чем во время первоначального запроса, чтобы отобразить форму.

Поскольку вы реконструируете список в getter вместо того, чтобы один раз создавать конструктор области с видимым bean, объекты Date получат другую метку времени при каждом вызове, это будет несколько минут/секунд в будущее по сравнению с исходными объектами Date. Следовательно, equals() не работает.

Переместите эту логику в конструктор bean и перепишите геттер, чтобы он выполнял то, что он должен был делать: вернуть только данные. Не выполняйте логику загрузки в приемнике. Вы также должны поместить bean в область вида, чтобы конструктор не возвращался повторно при отправке формы.

@ManagedBean
@ViewScoped
public class SignUpBean {

    private List<SelectItem> comDateList;

    public SignUpBean() {
        comDateList = new ArrayList<SelectItem>();
        // Fill it here.
    }

    public List<SelectItem> getComDateList() {
        return comDateList; // In getters, do nothing else than returning data!
    }

}

Обновить: конвертер также является потенциальным источником проблемы. Вы в основном поручили ему отменить время рендеринга HTML-страницы. Поэтому при обращении к Date используется время по умолчанию. Либо используйте

<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss.SSS Z" />

или reset время и часовой пояс на Calendar заранее:

cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT"));

таким образом вы можете использовать только <f:convertDateTime type="date" />