Monday, March 5, 2012

Stateless view parameter

The JSF 2.0 <f:viewParam> tag is a very useful tag which allows you to set GET request parameters as model values of a managed bean. You can even convert and validate them before it get set in the model. See also Communication in JSF 2.0 - Processing GET request parameters.

However, in combination with view scoped beans, it has one disadvantage. When you perform a postback on the same view, then the initial GET request parameter get converted and validated again based on the submitted value which was saved in the view state (the initial GET request parameter is namely not available anymore in the postback request). When the conversion is performed through a service/DAO method based on some entity ID as request parameter, then that service/DAO method would be invoked again during the postback, which is completely unnecessary in case of a view scoped bean.

The solution is simple: just make the <f:viewParam> tag stateless as to the submitted value! If it becomes null, then it won't be set in the model anyway. On jdevelopment.nl you can find a more in depth explanation about this. Arjan Tijms has extended the UIViewParameter component to achieve this functionality into a new OmniFaces <o:viewParam> tag (source code here).

The usage is simple, just replace f: tag prefix by o: tag prefix. So, instead of


    <f:metadata>
        <f:viewParam name="id" value="#{users.user}"
            converter="#{userConverter}" converterMessage="Bad request. Unknown user."
            required="true" requiredMessage="Bad request. Please use a link from within the system."
        />
    </f:metadata>

use


    <f:metadata>
        <o:viewParam name="id" value="#{users.user}"
            converter="#{userConverter}" converterMessage="Bad request. Unknown user."
            required="true" requiredMessage="Bad request. Please use a link from within the system."
        />
    </f:metadata>

As a bonus, the label attribute will also default to the name attribute instead of the client ID whenever the label attribute is not specified. The name attribute is a more sane default for this.

4 comments:

Tarqaron said...

until finding this post i didnt understand why on my ViewScoped backing bean, the attributes injected by were validated correctly only on first call to the view. But when pressing a with an Ajax listener, the required validation error messages appeared. Considering this i can now dic this issue :D thanks a great post

Unknown said...

How can i use metadata params with ajax request? after calling ajax action the metadata params are no longer on client side

Bauke Scholtz said...

@Tomasz: Use a @ViewScoped bean.

Kwasi Kyei said...

I've included view parameters in my code but when i click, the corresponding field in the bean does not seem to be updated until the page is refreshed. How do I rectify this? Is that how it is supposed to be?