PacificNW_Lover
PacificNW_Lover

Reputation: 5374

Min and maxdate on p:datePicker (or p:calendar) causes ClassCastException or minimum date must be less than maximum date

Am using PrimeFaces 10.0.0. I need to dynamically set the maxdate to be 10 years from now when using p:datePicker with a fixed mindate.

Utility bean to set maxdate:

@Named @ApplicationScoped
public class Dates {

    public LocalDate getLocalDateNow() {
        return LocalDate.now();
    }
}

Date picker:

<p:datePicker pattern="MM/dd/yyyy"
              mindate="1/1/2011"
              maxdate="#{dates.localDateNow.plusYears(10)}"
              .../>

Throws this exception:

javax.servlet.ServletException: java.lang.String cannot be cast to java.time.chrono.ChronoLocalDate
    ...
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.time.chrono.ChronoLocalDate
    at java.time.LocalDate.compareTo(LocalDate.java:137)
    at org.primefaces.component.api.UICalendar.validateMinMax(UICalendar.java:375)
    at org.primefaces.component.calendar.BaseCalendarRenderer.encodeEnd(BaseCalendarRenderer.java:84)
    at org.primefaces.component.datepicker.DatePickerRenderer.encodeEnd(DatePickerRenderer.java:89)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:619)
    ...

When I changed my utility bean to return a String:

public String getLocalDateNow() {
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("M/d/uuuu");
    LocalDate localDateNow = LocalDate.now().plusYears(10);
    return localDateNow.format(dtf);
}

And subsequently:

maxdate="#{dates.localDateNow}"

This is what happens:

javax.servlet.ServletException: DatePicker : "form:startDate" minimum date must be less than maximum date.
    ...
Caused by: javax.faces.FacesException: DatePicker : "form:serviceStart" minimum date must be less than maximum date.
    at org.primefaces.component.api.UICalendar.validateMinMax(UICalendar.java:378)
    at org.primefaces.component.calendar.BaseCalendarRenderer.encodeEnd(BaseCalendarRenderer.java:84)
    at 
    ...

How can I prevent these exceptions?

Upvotes: 2

Views: 3130

Answers (1)

Jasper de Vries
Jasper de Vries

Reputation: 20188

Take a look at the source code of UICalendar.validateMinMax:

public void validateMinMax(FacesContext context) {
    Comparable minDate = (Comparable) getMindate();
    Comparable maxDate = (Comparable) getMaxdate();
    if (minDate != null && maxDate != null && maxDate.compareTo(minDate) < 0) {
        String id = getClientId(context);
        String component = this.getClass().getSimpleName();
        throw new FacesException(component + " : \"" + id + "\" minimum date must be less than maximum date.");
    }
}

It simply checks for Comparable and does not care about the actual type. If you are using LocalDate for one date and String for the other, comparing will lead to an error (as shown in your first stack trace).

Using String for both is also no good, as comparing strings has nothing to do with a date value. It might, if you would use a date pattern like yyyy-MM-dd, but it's better not to use strings.

You should use the same (non-string) type (for example LocalDate) for both min and max dates and it will work.

That being said, the current implementation of validateMinMax is flawed. This has already been reported (and fixed while writing this answer):

Fix will end up in PrimeFaces 11.

By the way, this code is shared with the p:calendar component, so the same principle applies there. Note though that p:calendar is deprecated!

Upvotes: 4

Related Questions