Learning JSF2: Page params and page actions
Learning JSF 2 series continues with page parameters and page actions. Read other Learning JSF 2 articles.
If you worked with JSF 1.2, you know that calling a page action wasn’t simple. A page action is useful when you request a page for the first time (GET request) and would like to prepare some data to be rendered on a view (page). Of course there are some workarounds, one of them is to use @PostConstruct method inside the bean or even create a phase listener. Both could work but developers desired a more robust, and out of the box solution similar to what Seam 2 provides.
A feature that closely relates to page action is page params (page parameters). Usually when you issue a get request like this:
http://host/app/page.jsf?productId=101 |
you want the productId request parameter to be assigned to a property inside a bean so that you can use the id inside action (page action) to load data to display on the page. In JSF 1.2, you would end up doing something like this:
Managed bean:
@ManagedBean(name="bean") public class Bean { private Integer productId; // getter and setter } |
JSF configuration file:
<managed-bean> <managed-bean-name>bean</managed-bean-name> <managed-bean-class>test.Bean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>productId</property-name> <value>#{param['productId']}</value> </managed-property> </managed-bean> |
#{param} is an implicit object in JSF that holds all request parameters. In the code snippet above, we are taking the value of productId and assigning it to productId property inside the bean using JSF managed bean facility. It’s just not an elegant solution and it doesn’t offer any flexibility, ability to validate the value, and also defined separately from the actual page.
The good news is that both page actions and page params are supported by JSF 2. Let’s start with page params.
Page params
We all know that when we have a JSF input field bound to a bean property and we submit the page ( POST), the value entered in the page automatically get pushed into the bean (assuming no conversion/validation errors or anything else stopping the life cycle).
JSF page:
<h:inputText value="#{bean.productId}" /> |
Bean:
public class Bean { private Integer productId; // getter and setter } |
The easiest way to think of page params is that the same thing is happening as above but only without input fields on the page. Instead, the values are submitted via the GET URL and pushed in the same way into the bean:
http://host/app/page.jsf?productId=101 |
In both cases the result is the same, the value either from the page or URL is set into the property. We know how to do it with input field bound to a property during a POST. Let’s see what needs to be done when a GET request is issued. We have to somehow map the request param to bean properties.
JSF 2 introduced a new metadata tag called
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head></h:head> <f:metadata> <f:viewParam name="productId" value="#{bean.productId}"/> <f:viewParam name="text" value="#{bean.text}"/> </f:metadata> <body> ... </body> </html> |
In the code example above
http://localhost:port/app/page.jsf?productId=111&text=nice |
A quick and easy way to test that values were set into the proprieties is just to render the values on the page:
<h:outputText value="ProductId: #{bean.productId}" /> <h:outputText value="Text: #{bean.text}" /> |
Default values
If bean properties are set to some initial values page params will overwrite them (same as with a POST). If page params are not provided then during rendering the default values will be displayed.
Good to know
The
<f:view> <f:facet name="javax_faces_metadata" ></f:facet> </f:view> |
As this metadata tag going to be used extensively, a shortcut tag (alias) was created:
<f:view> <f:metadata></f:metadata> </f:view> |
The
Conversation and validation
When a value is submitted via a POST it can bean converted and validated before being pushed into the bean property. For a GET request, conversation and validation can be invoked in a similar fashion. When either fails, error message can be displayed just like with a POST.
When components are bound to a bean property, a converted or validator is registered with the component on the page. As we don’t have a component, conversation and validation is added to the
Requiring a value
To make a value required, we use the familiar required attribute and overwrite the default error message:
<f:metadata> <f:viewParam name="productId" value="#{bean.productId}" required="true" requiredMessage="Product id is required"/> <f:viewParam name="text" value="#{bean.text}" required="true" requiredMessage="Text is required"/> </f:metadata> |
To display the error message,
<h:messages /> <h:outputText value="ProductId: #{bean.productId}" /> <h:outputText value="Text: #{bean.text}" /> |
Note: we have to use
For example, the following request:
http://localhost:port/app/page.jsf?productId=111&text= |
will produce the following:

As we didn’t provide a value for text, validation fails. productId is also not set as Update Model phase was not executed (as expected after validation fails).
Good to know
When a page (view) is requested via a GET and no page params are present, Restore View and Render Respose phases will be executed (same behavior you get in JSF 1.2). Once page params are added to a GET request, JSF will run through the full life cycle in order to convert and validate the values and then set the values into the bean.
More validation
In addition to requiring a value, we can attach other standard validators to page params such as range validator for numbers and length validator for strings. For example:
<f:metadata> <f:viewParam name="productId" value="#{bean.productId}" required="true" requiredMessage="Product id is required" validatorMessage="Product id must be between 0 and 1000"> <f:validateLongRange minimum="0" maximum="1000"/> </f:viewParam> <f:viewParam name="text" value="#{bean.text}" required="true" requiredMessage="Text is required" validatorMessage="Text must be at least 3 chars long"> <f:validateLength minimum="3"/> </f:viewParam> </f:metadata> |
In this example,
For example the request with the parameters which not meets the requirements specified will produce the following:

Lastly, a custom validator can be attached as well via validator attribute (in which case the method is validation method is placed inside the bean):
<f:viewParam name="text" value="#{bean.text}" validator="#{bean.validateProduct}"/> |
or with
<f:viewParam name="text" value="#{bean.text}"> <f:validator validatorId="produdIdValidator"/> </f:viewParam> |
Conversion
As with validation, conversation is added in similar fashion. When we do a POST, all values are first converted and then validated. All values entered on a page are sent as strings and need to be converted before pushed into bean properties. Page param values are also sent as plain strings. Taking the productId param, a converter could be added like this:
<f:viewParam name="productId" value="#{bean.productId}" required="true" requiredMessage="Product id is required" validatorMessage="Product id must be between 0 and 1000" converter="javax.faces.Integer" converterMessage="Product id must be an integer"> <f:validateLongRange minimum="0" maximum="1000"/> </f:viewParam> |
This is just to demonstrate how it’s done but we don’t actually have to register the integer converter. Integer converter is one of the default converters in JSF which means that JSF will try to convert the value automatically. The converter attribute could be used to attached a custom converter as well.
Page actions
Page actions can be used to initialize data to be rendered in the view. Page actions are added with new the
<f:metadata> <f:viewParam../> <f:viewParam.../> <f:event type="preRenderView" listener="#{bean.loadAction}" /> </f:metadata> |
Two things are specified above, the event type (preRenderView) and the action listener to be invoked. The preRenderView event type indicates that this listener will be invoked during Render Respone phase.
Just for demonstration purposes, let’s use the productId value as a counter for the number of times to insert text value into a list and then display it.
Bean:
public ArrayList<String> list; // getter public void loadAction() { list = new ArrayList<String>(); for (int i = 0; i < productId ; i++) { list.add(text); } } |
For this to work, page params need to be set first and that’s exactly what happens. Page params are set into the model during Update Model phase and page action is invoked during Render Response phase (just before the rendering). We use a page param (productId) to decide how many times to insert the text value into the list. To render the list, we use this:
<ol> <ui:repeat value="#{bean.list}" var="txt"> <li> #{txt} </li> </ui:repeat> </ol> |
Entering the following URL:
http://host:port/app/page.jsf?productId=5&text=JSF2 |
will produce the following:

Note that if conversation or validation fails, the listener (page action) is still invoked. However, an exception will be thrown as productId is null (unless it’s initialized to some value). One option is to check if any error messages were queued and skip the listener logic. For example:
public void loadAction() { List<FacesMessage> messages = FacesContext.getCurrentInstance() .getMessageList(); if (messages.size() == 0) { list = new ArrayList<String>(); for (int i = 0; i < productId ; i++) { list.add(text); } } } |
Note: if only page action is present without page params, then only Restore View and Render Response phase are executed.
Summary
Page params and page actions are two great features in JSF 2. Being able to issue a GET with request params also allows to create bookmarkable URLs. Bookmarkable URLs and how page params are tied to navigation as well as the new
Hi Max!
Thank you very much for this great introduction to the prospects of page params.
I’m wondering if this page params also return “url-params” that are passed after a hash (#) in an URL (http://localhost:port/app/page.jsf#productId=111,text=nice)? This would have the big advantage that params dynamically inserted after the hash in an URL do not cause a full page refresh, which would be a precondition to support bookmarkable URLs on AJAX pages (i.e. pages where only parts are replaced with AJAX requests).
If not, I’m looking forward to your next article covering bookmarkable URLs – I hope AJAX request are covered there.
@Smax: I don’t believe that’s supported as you just perform a standard GET request (non-AJAX). As for Ajax, f:ajax tag is covered here: http://mkblog.exadel.com/jsf/learning-jsf-2-ajax-in-jsf-using-fajax-tag/
Hi Max,
thank you very much for your quick response!
Yesterday I incidentally came across the rich:hashParam component on your blog about the components yet available in RichFaces4. Unfortunately I didn’t find any description for this component (apart from “Incomplete” in the RichFaces doku @ JBoss.org). With this component, is it possible to get URL parameters that are passed after an #? E.g. the param “productId” in an URL like http://localhost:port/app/page.jsf#productId=111. Does rich:hashParam work similarly to f:viewParam?
Thank you yery much in advance!
PS: With “I hope AJAX requests are covered there” in my last post I meant the bookmarkability of pages where parts of the page are dynamically changed by AJAX request. I.e. how to bookmark a site when there’s never a full page refresh (a GET request where the URL changes) but just AJAX requests changing parts of the site.
@Smax: rich:hashParam creates a JavaScript param (hash) that can be used together with rich:componentControl to pass params to the component you are controlling.
Thank you very much! f:viewParam and f:event was just what I was looking for. Worked on the first try!
Very Simple and well explained article. Thanks!!
Ok It’s useful, but what happend with particular characters like ñ (Spanish letter)?
If you have in the text param a word like España instead of JSF2, you will have problems, because the browser will translate in something like ñ and I don’t know if it’s possible to decode.
Just as a correction to your post, when using a custom validator, the attribute is validatorId, not validator.
<f:validator validatorId=”produdIdValidator” />
Thanks for the great post though!
@Michael: Thanks, fixed.
Is it possible to combine the metadata/viewparam tags with the templating mechanism (I have a template and need the viewparams on each page)? I tried to implement it that way, unfortunately the values are not set in the managed bean.
@Mike: I can’t be 100% sure but I’d think it’s possible. Template or not template.. at the end you just get a complete, single page (so the template shouldn’t matter).
Very good, thanks!
Very useful article – the one which I was searching for hours together!
Hi!
I wonder if it’s possible to redirect the user if he’s supplied invalid params or in case of an error in the page action! We need this kind of functionality but don’t know what the best practice for this is in JSF.
Any thoughts?
Thanks!
@Rene: you can use this method: http://goo.gl/3TUPq
@max: Thanks!
Thanks a lot for exploring these tag using examples. It helps me a lot…
Thanks for this article, Max. It is very informative. Glad to see you are still responding to replies a year and half later!
If I enter the url
http://localhost:8080/contacts-as7/index.jsf?sitecode=0200
I get exactly the result I want. I use f:viewParam to set the sitecode and f:event to retrieve the site info:
Here’s where I am having trouble. In addition to being able to jump right into the page with a URL containing a parameter, I also want to be able to enter a sitecode into an input field on the same page and end up with the same result, ie parameter in the URL and correct info on the page.
It seems I can do either the GET using f:viewParam and f:event (no input field) or the POST using h:commandButton (no parameter in the URL).
How do I make my app do both?
@tanya: see if you can use a redirect when doing a post.
Thanks for pointing me in the right direction. I did the POST and the return string from the POST action included the parameter in the URL together with faces-redirect=true
return “index.jsf?sitecode=” siteCode “&faces-redirect=true”;
the xhtml file included the metadata to make use of the redirected URL
f:viewParam name="sitecode" value="#{contactView.siteCode}" /f:viewParam f:event listener="#{contactView.retrieve}" type="preRenderView"/f:eventTDR
I suppose that you mean Converting and not Conversation
Thanks, updated.
Max, do you know if there is some issues with param and c:forEach?
I am creating a pagination bar, using c:forEach to create the page numbers as h:links with param. Other h:links are a working, setting the value in the managedbean property, but that inside the c:forEach not.
Could be.. as c:forEach is processed at different time than JSF tags.
Changed to ui:repeat and no success… restarted all enviroment, including Web”cache”Sphere, now it works very well. It seems like a cache problem with the server. Thank you, Max.