Question

The following code creates a two radio buttons. Each option contains a date value that is successfully converted to a label of the format "yyyy-MM-dd". Once I make a selection and click the next button I get the following error "j_idt12:comDateChoice: Validation Error: Value is not valid". It seems simple enough but somethings wrong. Can any of you spot it?

I'm using JSF 2.0 in glassfish.

Backing bean

public List<SelectItem> getComDateList() {
    List<SelectItem> items = new ArrayList<SelectItem>();
    Calendar cal = GregorianCalendar.getInstance();
    cal.set(Calendar.DAY_OF_MONTH, 1);
    cal.add(Calendar.MONTH, 1);
    Date nextFirst = cal.getTime();
    cal.add(Calendar.MONTH, 1);
    Date followingFirst = cal.getTime();
    items.add(new SelectItem(nextFirst, new SimpleDateFormat("yyyy-MM-dd").format(nextFirst)));
    items.add(new SelectItem(followingFirst, new SimpleDateFormat("yyyy-MM-dd").format(followingFirst)));
    return items;
}

JSF Code

<h:panelGrid columns="2">
                    <h:outputLabel value="#{msg.FinanceCommencementDate}" for="comDateChoice"/>
                    <h:selectOneRadio id="comDateChoice" value="#{signUpBean.current.commencementDate}" layout="pageDirection">
                        <f:convertDateTime type="date" dateStyle="short"/>
                        <f:selectItems  value="#{signUpBean.comDateList}"/>
                    </h:selectOneRadio>
                </h:panelGrid>
Was it helpful?

Solution

This error will occur if the selected item value didn't pass the Object#equals() check on any of the available select item values. This can happen if the getter returned a different list during the apply request values phase of the form submit request than it did during the initial request to display the form.

Because you're reconstructing the list in the getter instead of constructing once in the constructor of a view scoped bean, the Date objects will get a different timestamp on every call, it will be some minutes/seconds in the future as compared to the initial Date objects. Hence the equals() will fail.

Move this logic into the constructor of the bean and rewrite the getter so that it does what it is supposed to do: return only the data. Do not do loading logic in a getter. You should also put the bean in the view scope so that the constructor doesn't re-run when you submit the form.

@ManagedBean
@ViewScoped
public class SignUpBean {

    private List<SelectItem> comDateList;

    public SignUpBean() {
        comDateList = new ArrayList<SelectItem>();
        // Fill it here.
    }

    public List<SelectItem> getComDateList() {
        return comDateList; // In getters, do nothing else than returning data!
    }

}

Update: the converter is also a potential source of the problem. You've basically instructed it to strip off the time when rendering the HTML page. So it uses the default time when converting back to Date. Either use

<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss.SSS Z" />

or reset the time and timezone on the Calendar beforehand:

cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT"));

this way you can use just a <f:convertDateTime type="date" />

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top