Retaining GET request query string parameters on JSF form submit
Solution 1:
Your concrete problem is caused because a JSF <h:form>
submits by default to the current request URL without any query string. Look closer at the generated HTML output, you'll see
<form action="/app/agreement.xhtml" ...>
You'd thus explicitly need to include those request parameters yourself. There are several ways to solve this. If you weren't sending a redirect, then you could just add them as hidden inputs to the JSF form.
<h:form>
<input type="hidden" name="site" value="#{param.site}" />
<input type="hidden" name="site" value="#{param.serviceId}" />
...
</h:form>
Only, those parameters won't reappear in URL in browser's address bar. This isn't a problem if you're only using using ajax on the same page. The <h:inputHidden>
is by the way not suitable as it will confusingly lose its value when a conversion or validation error occurs on the form.
In order to get them to reappear in URL, you need <f:viewParam>
and includeViewParams
. In order to get includeViewParams
to work, you need to declare the following in both the source page agreement.xhtml
...
<f:metadata>
<f:viewParam name="site" value="#{agreement.site}" />
<f:viewParam name="serviceId" value="#{agreement.serviceId}" />
</f:metadata>
... and the target page generated.xhtml
:
<f:metadata>
<f:viewParam name="site" value="#{generated.site}" />
<f:viewParam name="serviceId" value="#{generated.serviceId}" />
</f:metadata>
Now you can send a redirect including the view parameters as follows:
public String generateMethod() {
// ...
return "generated?faces-redirect=true&includeViewParams=true";
}
Do note that the bean should be @ViewScoped
in order to keep those parameters alive between opening the page with the form and submitting the form, also on validation errors. Otherwise, when sticking to a @RequestScoped
bean, you should be retaining them as <f:param>
in the command components:
<h:commandButton ...>
<f:param name="site" value="#{generated.site}" />
<f:param name="serviceId" value="#{generated.serviceId}" />
</h:commandButton>
There's no way to set them for <f:ajax>
inside input components, your bean should then really be @ViewScoped
.
Alternatively, if you happen to use JSF utility library OmniFaces already, then you could also just replace the <h:form>
by <o:form>
as follows (see also showcase example):
<o:form>
That's basically all. This will generate a <form action>
with current query string included.
<form action="/app/agreement.xhtml?site=US&serviceId=AABBCC" ...>
Those request parameters are then just available in the request parameter map of the form submit. You don't need additional metadata/viewparams and you also don't need to send a redirect and your bean can be kept @RequestScoped
, if necessary.
public String generateMethod() {
// ...
return "generated";
}
See also:
- What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
- How to navigate in JSF? How to make URL reflect current page (and not previous one)
Solution 2:
Your generateMethod
would have to return
return "generated?site=US&serviceId=AABBCC&faces-redirect=true";
You can even replace &
with &
but escape it in your xhtml.
In your generated.xhtml
you can catch the parameters that are being passed with <f:viewParam>
like this
<f:metadata>
<f:viewParam name="site" value="#{yourBean.site}"/><!--Make sure you have a setter-->
<f:viewParam name="serviceId" value="#{yourBean.serviceId}"/><!--Make sure you have a setter-
</f:metadata>
<h:head>