Question

I am using JSF, PrimeFaces 3.2, Omnifaces 1.1, JBoss AS 7.1.1, Final, Mojarra 2.1.7

I have a form that has two numeric fields both are not required, like this:

<h:form>
    <p:inputText id="num1" value="#{bean.field1}"/>
    <p:inputText id="num2" value="#{bean.field2}"/>
<p:commandButton ... ajax="true" />
</h:form>

I have also setup OmniFaces ResetInputAjaxActionListener on faces-config.

The bean properties field1 and field2 are Integer.

Now the issue is if I input say 123 on num1 and input 345 on num2 and click OK all okay. If I then remove 123 from num1 and put abc on num2. Then validation (conversion) error is shown but 123 comes back!

If I make them both required=true then all is well.

Is there are a way to make this work with optional fields?

Was it helpful?

Solution

This is a Mojarra specific issue. The field which is being bound to an Integer is implicitly been converted by the IntegerConverter which converts the submitted empty string value to null and sets it as such in the component's local value.

When a form is redisplayed after submit, JSF will first check if the submitted value is not null and then display it, else if the local value is not null, then display it, else display the model value. As the local value is null, the model value is been displayed instead. This is indeed undesired behaviour and has been reported several times:

This can be fixed by overriding UIInput#getValue() as follows:

public Object getValue() {
    return isLocalValueSet() ? getLocalValue() : super.getValue();
}

MyFaces already does it right. I've re-reported this issue again which eventually ended up as spec issue 566 (update and finally fixed in Mojarra 2.2.0 and backported to 2.1.21).

In the meanwhile, the easiest way to workaround this, while taking 3rd party component libraries with their own renderers like PrimeFaces into account, is to copy the source code file of javax.faces.component.UIInput class straight in your project's source folder and then add the desired UIInput#getValue() method. Yes, a clumsy fix, but there's not really a nicer way as the cause of the problem is deep in the JSF API itself.

The OmniFaces ResetInputAjaxActionListener serves an entirely different purpose and isn't designed/suitable to solve this problem. It is supposed to clear the state of input components of which the value of the component is not submitted, but the component itself is re-rendered in ajax.

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