The following is a simple use case of <f:viewAction>
.
<f:metadata>
<f:viewParam name="id" value="#{testManagedBean.id}" maxlength="20"/>
<f:viewAction action="#{testManagedBean.viewAction}"/>
</f:metadata>
The managed bean involved.
@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
private Long id; //Getter and setter.
public void viewAction() {
System.out.println("viewAction() called : " + id);
}
}
The parameter id
is passed through a URL. There is a conversion error, when a non-numeric value like xxx
is passed through the URL in question and the viewAction()
method associated with the listener of <f:viewAction>
is not invoked.
The value of id
is null
in this case. I would like to redirect to another page, when id
is not convertible to a desired target type (like in this case) or id
is not validated against the specified validation criteria to avoid potential exceptions which are likely to be thrown in the LazyDataModel#load()
method of PrimeFaces or somewhere else in the associated managed bean whenever access to these parameters is attempted in the corresponding managed bean. For this to be so, the viewAction()
method should be invoked.
How to proceed with this? Should I use
<f:event type="preRenderView">
in conjunction with <f:viewAction>
?
Why not simply validate
id
yourself?This is specified behavior. When
PROCESS_VALIDATIONS
phase ends with a validation failure, both theUPDATE_MODEL_VALUES
andINVOKE_APPLICATION
phases are skipped. Exactly like as in "regular" forms with<h:form>
. Think of<f:viewParam>
as a<h:inputText>
and a<f:viewAction>
as a<h:commandButton>
and it will become more clear.For your particular requirement, performing a redirect when conversion/validation has failed, there are at least 3 solutions:
As you found out, add a
<f:event listener>
. I'd rather hook onpostValidate
event instead for better self-documentability.The check on
FacesContext#isPostback()
prevents the redirect being performed on validation failures of "regular" forms in the same view (if any).Extend the builtin
LongConverter
whereby you perform the redirect ingetAsObject()
(a validator is insuitable as the default converter forLong
would already fail on non-numeric inputs; if a converter fails, the validators are never fired). This is however poor design (tight-coupling).You could if necessary play around with
<f:attribute>
inside<f:viewParam>
to "pass" parameters to the converter.Create a custom taghandler which does basically the same as
<f:event listener>
but without the need for an additional backing bean method.com.example.taghandler.ViewParamValidationFailed
/WEB-INF/my.taglib.xml
/WEB-INF/web.xml
True, it's a bit of code, but it ends up in clean and reusable
<my:viewParamValidationFailed>
tag and is actually a good fit for a new OmniFaces feature.