In my JSF application I've got a link to a page, which is build with a dynamic query string:
<h:link outcome="list?#{controller.queryString}" value="Example" />
I can't use <f:param>, because the count of included parameters changes for every request.
The problem is that the query string is URL encoded, because some parameter values can contain a =. The result is that the query string is encoded twice in the result HTML.
An outcome of list?a=b%3Dc becomes:
<a href=".../list.xhtml?a=b%253Dc">Example</a>
Looking at the JSF spec (Default NavigationHandler Algorithm) I can't find anything about encoded in the query string. But I think that com.sun.faces.application.NavigationHandlerImpl.findImplicitMatch is a rather hacky implementation.
My question: Did I use <h:link> in a wrong way (works as designed) or is this somehow a bug?
My current solution is to use a <h:outputLink> instead - which prevents the usage of any navigation rules.
If #{controller.queryString} is at least view scoped or broader, then you could use a Map<String, String> with unencoded values instead and use <c:forEach> to dynamically generate <f:param> entries.
private Map<String, String> params;
<h:link ...>
<c:forEach items="#{bean.params}" var="entry">
<f:param name="#{entry.key}" value="#{entry.value}" />
</c:forEach>
</h:link>
If it is however request scoped (e.g. depends on user input), then you'd need to use a request scoped bean and explicitly rebuild the view as below in the action method before ajax-updating the link, so that JSTL tags run once again during render response.
String viewId = context.getViewRoot().getViewId();
UIViewRoot view = context.getApplication().getViewHandler().createView(context, viewId);
context.setViewRoot(view);
If the bean being request scoped is however not an option, then your best bet is manually generating the URL with help of ViewHandler#getBookmarkableURL(), passing the view ID and the parameters as a Map.
url = context.getApplication().getViewHandler().getBookmarkableURL(context, outcomeViewId, params, false);
<a href="#{bean.url}">...</a>
The outcome view ID is easy if you rely solely on implicit navigation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With