JSF 2 - f: selectItems с картой с датой

Приведенные ниже selectItems подаются из карты с областью действия сеанса. Когда пользователь нажимает кнопку «Отправить», предполагается, что поле даты устанавливается в компоненте поддержки запроса с областью действия и отображается на странице.

    <h:selectOneMenu value="#{dropDown.selectedDate}">
        <f:selectItems value="#{mapValues.dateMap.entrySet()}" var="entry" itemLabel="#{entry.value}" itemValue="#{entry.key}" />
    </h:selectOneMenu>
    <h:commandButton value="Submit" />
You selected Date #{dropDown.selectedDate}

Однако получена следующая ошибка преобразования:

Conversion Error setting value 'Wed Dec 26 15:09:32 EST 2012' for 'null Converter'. 

Я не уверен, почему эта ошибка получена. Я попытался установить конвертер javax.faces.DateTime в теге selectOneMenu, но затем получил еще более загадочную ошибку проверки.

Нашел сообщение, в котором предлагается проверить, доступен ли метод equal(), и что выбор элемента находится в раскрывающемся списке, оба из которых должны быть истинными в этом случае.

Один обходной путь, который я могу придумать, - это изменить мою карту на строку с ключом, где даты сохраняются в виде строк. Но это кажется перебором.

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

Фасоль поддержки:

@Named
@RequestScoped
public class DropDown {

    private Date selectedDate;

    public Date getSelectedDate() {
        return selectedDate;
    }

    public void setSelectedDate(Date selectedDate) {
        this.selectedDate = selectedDate;
    }

}

Компонент карты:

@Named
@SessionScoped
public class MapValues implements Serializable {

    private Map<Date, String> dateMap;

    @PostConstruct
    public void init() {        
        dateMap = new LinkedHashMap<Date, String>();
        dateMap.put(new Date(), "DATEVALUE1");      
    }

    public Map<Date, String> getDateMap() {
        return dateMap;
    }

    public void setDateMap(Map<Date, String> dateMap) {
        this.dateMap = dateMap;
    }
}

Спасибо!


person Ali Cheaito    schedule 26.12.2012    source источник
comment
но затем получил еще более загадочную ошибку проверки. почему вы не сообщаете об этом в своем вопросе?   -  person BalusC    schedule 27.12.2012
comment
Это была форма: местоположение: Ошибка проверки: значение недействительно   -  person Ali Cheaito    schedule 27.12.2012


Ответы (1)


Использование конвертера даты и времени должно было быть правильным решением. Ваша «более загадочная ошибка проверки» оказывается именно такой:

Это было "form:location: Ошибка проверки: значение недействительно

Это произойдет, если проверка Object#equals() выбранного элемента не вернет true ни для одного из доступных элементов. Итак, выбранный Date не соответствует ни одному из доступных экземпляров Date.

И действительно, converter="javax.faces.DateTime" (он же <f:convertDateTime />) по умолчанию игнорирует временную часть. По умолчанию он печатает «краткий» стиль даты, например «27 декабря 2012 г.». Щелкните правой кнопкой мыши страницу в браузере, выберите Просмотр исходного кода, чтобы увидеть ее самостоятельно.

<option value="Dec 27, 2012">DATEVALUE1</option>

Когда JSF преобразует представленное значение строки в этом формате обратно в конкретный экземпляр Date, он становится в основном 2012-12-27 00:00:00.000, в то время как даты, указанные в вашей карте, по-видимому, имеют часть времени, по-видимому, все еще установленную, что приводит к тому, что equals() всегда терпит неудачу, если только карта доступных дат не установлена. совпадение сгенерировано ровно в 00:00:00.000 полночи.

Есть 2 решения этой проблемы:

  1. Удалите временную часть дат в вашем отображении. Вы можете использовать для этого java.util.Calendar (или лучше Joda Time).

  2. Вместо этого используйте <f:convertDateTime pattern="yyyyMMddHHmmssSSS"/>, чтобы преобразовать всю дату/время до последней миллисекунды.

    <h:selectOneMenu value="#{dropDown.selectedDate}">
        <f:selectItems value="#{mapValues.dateMap.entrySet()}" var="entry" itemLabel="#{entry.value}" itemValue="#{entry.key}" />
        <f:convertDateTime pattern="yyyyMMddHHmmssSSS" />
    </h:selectOneMenu>
    

    Таким образом, значение параметра становится

    <option value="20121227114627792">DATEVALUE1</option>
    

    Будьте осторожны с проблемами часового пояса, когда вы настроили JSF для использования часового пояса конкретной платформы вместо GMT в качестве часового пояса <f:convertDateTime>. Тогда вы хотите явно добавить атрибут timeZone="UTC" в конвертер.

person BalusC    schedule 27.12.2012
comment
Второе решение помогло. Спасибо за подробное объяснение! - person Ali Cheaito; 28.12.2012