Theflex
Theflex

Reputation: 71

JSF 2 : Bean Validation JSR 303 notnull : The model value is returned

I am using JSF 2 (MyFaces 2.2.9) and Bean Validation (Hibernate Validator 5.2.2.Final).

I use the @NotNull annotation on a bean that is a property of my managed bean.

(ManagedBean class)

@ManagedBean
public class ConfiguracionesBean {

    private Configuraciones configuraciones;

    @PostConstruct
    public void postConstruct() {
        this.configuraciones = Configuraciones.find();
    }

    //getters/setters/unrelevant code
    ...

}

(Bean class)

public class Configuraciones {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @NotNull
    private String name;
}  

(.xhtml page)

<h:outputLabel for="name">#{i18n['name']}</h:outputLabel>
<h:inputText id="name" label="#{i18n['name']}" value="#{configuracionesBean.configuraciones.name}" />
<h:message for="name" errorClass="error" warnClass="warn" infoClass="info"/>

The first time the page is displayed, the "name" input text field contains the value that was previously stored in my database (normal until here).
If I delete this value on the html form, and I submit, then the @NotNull constraint is triggered, and I get an error (still normal here).
But the value of the inputText displayed on the html page is the value from the managed bean as it was initialized). Not the "empty" value that the user just put (by emptying the field). So the user sees an error "The field can not be null", but the field actually contains the previous value.

Is there a way to prevent this? I want the input to be empty, as it is what the user put.

I precise that I have the option :

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

Thanks in advance for you answers.
Note : I would really like to stick with the validations only done by JSR 303, as like this I have a uniform way of dealing with constraints. So no JSF validators (that could do the same, I know).

Alex

Upvotes: 0

Views: 913

Answers (1)

teg-man
teg-man

Reputation: 11

This is the normal behaviour. Validations are processed in JSF's "Process Validations Phase". This phase is computed before the "Update Model Values" phase. That means if validation fails your model (Bean) won't be updated with the invalid values. All phases after "Process Validations Phase" will be skipped and "Render Response Phase" will be executed. The result is that when your invalid field is rerendered it will still show the old value because the model has not been updated.

In the "Render Response Phase" you will now be able to show an error message with <h:messages>. The only way I can think of to prevent old model values from showing is using the ajax-Element and not rendering the input element in the render response phase but instead just rendering its error message.

So in your xhtml:

<h:outputLabel for="name">#{i18n['name']}</h:outputLabel>
<h:inputText id="name" label="#{i18n['name']}" value="#{configuracionesBean.configuraciones.name}">
    <f:ajax event="valueChange" render="errorBlock" />
</h:inputText>
<h:panelGroup id="errorBlock">
    <h:message for="name" errorClass="error" warnClass="warn" infoClass="info"/>
</h:panelGroup>

The following links might be helpful

JSF life cycle illustrated: http://developersbook.com/jsf/images/JSF-Lifecycle.png

JSF life cycle: https://docs.oracle.com/javaee/1.4/tutorial/doc/JSFIntro10.html#wp122256

Upvotes: 1

Related Questions