JSF 2 - f:带有Date键控Map的selectItems

时间:2012-12-26 21:11:34

标签: java validation jsf-2 converter selectonemenu

以下selectItems来自Session Scoped Map。当用户单击Submit按钮时,它应该在Request Scoped支持bean中设置一个日期字段并将其显示在页面上。

    <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'. 

我不确定为什么会收到这个错误。我尝试在selectOneMenu标记上设置javax.faces.DateTime转换器,但后来又收到了更加神秘的验证错误。

发现a post建议检查equal()方法是否可用,以及项目选择是否在下拉列表中,在这种情况下两者都应该为true。

我能想到的一个解决方法是将我的地图更改为String键,其中日期作为字符串保存。但这似乎有点矫枉过正。

有关如何使此设置正常工作的任何建议吗?

支持bean:

@Named
@RequestScoped
public class DropDown {

    private Date selectedDate;

    public Date getSelectedDate() {
        return selectedDate;
    }

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

}

Map bean:

@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;
    }
}

谢谢!

1 个答案:

答案 0 :(得分:5)

使用日期时间转换器应该是正确的解决方案。你的更加神秘的验证错误&#34;原来就是这样:

  

它是&#34;形式:位置:验证错误:值无效

如果所选项目的Object#equals()测试未针对任何可用项目返回true,则会发生这种情况。因此,选定的Date与任何可用的Date实例都不匹配。

事实上,converter="javax.faces.DateTime"(又名<f:convertDateTime />)默认忽略时间部分。它默认打印&#34;短&#34;日期风格如&#34; 2012年12月27日&#34;在浏览器中右键单击页面,选择查看源以自行查看。

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

当JSF将该格式的字符串提交值转换回具体的Date实例时,它基本上变为2012-12-27 00:00:00.000,而地图中提供的日期显然仍然设置了时间部分,导致{ {1}}始终失败,除非可用日期的地图是在恰好equals()午夜生成的巧合。

此问题有两种解决方案:

  1. 删除映射中日期的时间部分。您可以使用00:00:00.000(或更好的Joda时间)。

  2. 使用java.util.Calendar代替将整个日期/时间转换为最后一毫秒。

    <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>
    

    当您将JSF配置为使用平台特定时区而非GMT作为<option value="20121227114627792">DATEVALUE1</option> 时区时,请注意时区问题。您希望明确将<f:convertDateTime>属性添加到转换器中。