【问题标题】:@FacesConverter(forClass = Clazz.class) and p:calendar@FacesConverter(forClass = Clazz.class) 和 p:calendar
【发布时间】:2023-12-28 04:06:01
【问题描述】:

基本的 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)

&lt;p:calendar&gt;不支持这个功能吗?

使用 PrimeFaces 5.2 和 JSF 2.2.12。

【问题讨论】:

    标签: jsf primefaces calendar converter jsf-2.2


    【解决方案1】:

    基于5.2的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 检查,但不按类将其委托给转换器,如果有的话) .

    【讨论】:

    • :D 我只是想回答:你检查过来源吗……想知道为什么人们不这样做。源是开放的,原因不止一个
    • @Kukeltje :在这种特殊情况下,我以前并不知道答案,但我通常会坚持提出影响内部框架功能的问题,即使我事先知道答案。我个人认为来自不同人的意见是必不可少的。我不会掉以轻心。 (顺便说一句,它可以追溯到很久以前。我很久以前就观察到了这种行为,但我只是忽略了它,因为提到带有 &lt;p:calendar&gt; 的单个 converter 属性并不是手指痛苦:)。
    • @Tiny:(不是咆哮,只是评论 ;-) 好的,但是如果您事先知道答案,那么为什么不这么说并问一个问题,例如:“有没有特定的行为和实现是这样那样的原因。您仍然会得到不同的意见,甚至可能更多,因为在这种情况下,我会回答“我看不出这种行为是正常的原因,我认为这是一个错误/遗漏”。将其与我上面的“评论”进行比较......对我来说(我知道你不是他们中的一员),如果他们提出可以通过“简单”分析开源代码找到的问题,他们似乎是“懒惰的”。干杯...
    • 我在GitHub 上创建了一个问题。