h:selectOneMenu bound to int incorrectly errors "Validation error: Value is not valid"

2.8k views Asked by At

I'm stuck with JSF RI 1.1_02 and seeing this problem.

Here's the Facelet code I'm expecting to work:

<h:form>
    <h:selectOneMenu value="#{bean.num}" converter="javax.faces.Integer">
        <f:selectItem itemLabel="one"   itemValue="1" />
        <f:selectItem itemLabel="two"   itemValue="2" />
        <f:selectItem itemLabel="three" itemValue="3" />
    </h:selectOneMenu>
    <h:commandButton value="submit" />
    <h:messages />
</h:form>

The request scoped bean:

public class Bean {
    private int num;

    public void setNum(Integer aNum) {
        num = aNum;
    }

    public Integer getNum() {
        return num;
    }
}

I'm receiving Validation Error: Value is not valid and can't imagine what I'm doing wrong already when I've written so little code which shouldn't need any converter. Am I missing something obvious or is this a bug in JSF RI 1.1_02?

I can get around the problem by simply changing the property type in the backing bean to String but am just frustrated by having to do that when (automatic) conversion is supposed to be there for me.

1

There are 1 answers

4
BalusC On BEST ANSWER

I took the time to create a JSF RI 1.1_02 playground environment and I was able to reproduce your problem. After checking the source code the culprit seems that the <f:selectItem> value is never converted to the same type as the submitted value. So basically it is comparing the item value as String against the submitted value as Integer and this comparison ain't ever going to return true.

This is a pretty awkward bug which can technically only be solved by replacing the UISelectOne component (the UISelectMany exposes the same bug by the way). The problem is in the private matchValue() method. A custom converter (a solution which I initially had in mind) isn't going to help in any way as it wouldn't be invoked for the <f:selectItem> value at all.

Upgrading to Mojarra 1.2_15 instantly fixed the problem.


Update: in case you really, really, can't upgrade, I found a workaround utilizing EL coercion: if you reference the values in EL instead of as static strings, then they're implicitly treated as Long. If you change the property type from Integer to Long, then it'll work without any converter.

<h:selectOneMenu value="#{bean.num}">
    <f:selectItem itemLabel="one"   itemValue="#{1}" />
    <f:selectItem itemLabel="two"   itemValue="#{2}" />
    <f:selectItem itemLabel="three" itemValue="#{3}" />
</h:selectOneMenu>

with

private Long num;