2

Basic Joda Time converter (the code is absolutely superfluous for the context of this thread) :

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

Why does it not work with a <p:calendar> unless/until it is explicitly specified by using the converter attribute?

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

Like other components, it is expected to work without mentioning the converter attribute because the converter is decorated with

@FacesConverter(forClass = DateTime.class)

Is this feature not supported by <p:calendar>?

Using PrimeFaces 5.2 and JSF 2.2.12.

Tiny
  • 27,221
  • 105
  • 339
  • 599

1 Answers1

4

Based on 5.2's CalendarRenderer#encodeEnd(), it uses CalendarUtils#getValueAsString() to obtain the value for output. It indeed doesn't consult via Application#createConverter(Class) if there's a converter by 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          }

That confirms the behavior you observed. You'd best create an issue report to PrimeFaces guys which requests adding an instanceof Date check in place, and in the opposite case obtain the converter by class from the application something like below:

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

This would indeed make sense given the increasing use of Java8's java.time API. There are by the way a few other places in CalendarRenderer and CalendarUtils where this could/should be implemented (and where they are actually performing an instanceof check, but not delegating it to the converter by class, if any).

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • :D I was just going to answer: did you check the source… wondering why people don't do that. The source is open, for more than one reason – Kukeltje Jul 24 '15 at 05:59
  • @Kukeltje : Not in this particular case I knew the answer before but I would usually insist upon asking questions affecting the internal framework functionality even though I were to know the answer beforehand. I personally believe opinions from different people are essential. I do not take this kind of things lightly. (BTW, It dates back to a long time ago. I observed this behaviour a long back but I simply ignored it because mentioning a single `converter` attribute with a `` was not a pain in fingers :) ). – Tiny Jul 24 '15 at 11:28
  • @Tiny: (not a rant, just a comment ;-) Ok, but If you kind of knew the answer beforehand, than why not state so and ask a question like: 'Is there a specific reason why the behaviour and implementation is such and so'. You'll still get different opinions, maybe even more so, because in this case I would have answered "I see not reason this behaviour is normal, I assume a bug/omission'. Compare that to my 'comment' above... For me (and I know you are not one of them) people seem to be 'lazy' if they ask questions that can be found by 'simply' analysing the open source code. Cheers... – Kukeltje Jul 24 '15 at 12:26
  • 1
    I have created an issue on [GitHub](https://github.com/primefaces/primefaces/issues/579). – Tiny Jul 29 '15 at 09:29