This problem is caused by the fact that you are using your final URL as the navigation "outcome", which must actually map to either a specified navigation case or an implicit navigation case (matching a view file on disk).
To resolve this, you should use the "outcome" attribute as it is intended (I agree the JSF docs could maybe be clearer on this,) and use the view-id in your button configuration instead:
<p:button outcome="/management/product/read.xhtml" value="Navigate">
<f:param name="product" value="#{...}" />
</p:button>
This will cause the NavigationCase to resolve successfully, and when the URL is encoded using HttpServletResponse.encodeUrl()
, PrettyFaces will handle rewriting the URL to the desired "/admin/product/edit
".
Note that you can also achieve this (and decouple your view file from their location on disk), by using the PrettyFaces navigation system:
<p:button outcome="pretty:adminEditProduct" value="Navigate">
<f:param name="product" value="#{...}" />
</p:button>
This will achieve the same result, but will mean that you only have one place (your PrettyFaces configuration) to keep track of which view file matches up against which URL.