@FacesConverter(forClass = Clazz.class)和p:calendar

时间:2015-07-23 21:52:06

标签: jsf primefaces calendar converter jsf-2.2

基本Joda时间转换器(该代码对于此线程的上下文绝对是多余的):

@Named
@ApplicationScoped
@FacesConverter(forClass = DateTime.class)
public class DateTimeConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }

        try {
            return DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa Z").parseDateTime(value).withZone(DateTimeZone.UTC);
        } catch (IllegalArgumentException | UnsupportedOperationException e) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return "";
        }

        if (!(value instanceof DateTime)) {
            throw new ConverterException("Error");
        }

        try {
            return DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa Z").print(((DateTime) value).withZone(DateTimeZone.forID("zoneId")));
        } catch (IllegalArgumentException e) {
            throw new ConverterException("Error", e); // Not required.
        }
    }
}

为什么它不能与<p:calendar>一起使用,除非/直到使用converter属性明确指定它?

<p:calendar converter="#{dateTimeConverter}" value="{bean.dateTimeValue}" .../>

与其他组件一样,预计在不提及converter属性的情况下工作,因为转换器用

装饰
@FacesConverter(forClass = DateTime.class)

<p:calendar>不支持此功能吗?

使用PrimeFaces 5.2和JSF 2.2.12。

1 个答案:

答案 0 :(得分:4)

基于5.2&#39; CalendarRenderer#encodeEnd(),它使用CalendarUtils#getValueAsString()来获取输出值。如果按类别转换,它确实不会通过Application#createConverter(Class)进行咨询。

51          //first ask the converter
52          if(calendar.getConverter() != null) {
53              return calendar.getConverter().getAsString(context, calendar, value);
54          }
55          //Use built-in converter
56          else {
57              SimpleDateFormat dateFormat = new SimpleDateFormat(calendar.calculatePattern(), calendar.calculateLocale(context));
58              dateFormat.setTimeZone(calendar.calculateTimeZone());
59              
60              return dateFormat.format(value);
61          }

这证实了你观察到的行为。您最好向PrimeFaces人员创建一个问题报告,要求添加instanceof Date检查,相反的情况下,从应用程序中按类获取转换器,如下所示:

Converter converter = context.getApplication().createConverter(value.getClass());
if (converter != null) {
    return converter.getAsString(context, calendar, value);
}
else {
    throw new IllegalArgumentException(value.getClass());
}                    

鉴于越来越多地使用Java8的java.time API,这确实很有意义。顺便提一下CalendarRendererCalendarUtils中可以/应该实现的其他几个地方(以及他们实际执行instanceof检查的地方,但不将其委托给转换器按类别,如果有的话。)