PrettyUrlPhaseListener - A Quick and Easy Way To Make Human-friendly URLs
One of the most common requests from JSF users is "How do I use GET requests?" or "How do I make pretty URLs?" The answer usually boiled down to implementing a custom PhaseListener to handle the URI-to-managed-bean data transfer, but these solutions were almost always very specific to the application. Scales, however, now has a general use PrettyUrlPhaseListener to handle this painlessly.
Configuring the PhaseListener is quite simple. First, the PhaseListener must be registered with JSF:
Second, the PhaseListener must be configured in web.xml:
The value of this context-param lists a key/value pair of actual template files and URL patterns. NOTE: the extension used in the mapping key is the extension of the physical file on disk, NOT the servlet mapping used in the browser. When the PhaseListener processes each request, it uses a regular expression created from each URL pattern to determine if the current request URL is one which it should process. If it is, the value from the request URL that corresponds to each EL expression in the pattern is extracted, URL-decoded, then set on the ValueExpression created from the EL. Once all the values have been processed, JSF is instructed to display the actual template file, specified by the key in the pair.
One important thing to note, which may or may not be obvious, is that any security constraints specified in web.xml will still be applied, so using this feature will not allow you to circumvent those protections. Since the web container is still doing the processing, nothing changes with regard to those constraints. Additionally, while this is, strictly speaking, outside the scope of Mojarra Scales, any resources on the disk will hide any Servlet mappings, so take care when creating mappings.
One more step must be performed, however. If your pretty URLs do not match any existing servlet-mapping entries, then entries must be added until all of the URLs configured are covered. This will send the request to the FacesServlet so that the PhaseListener can process the request. The servlet-mappings for the URLs above might look like this:
With these config changes in place, the user can now request http://localhost:8080/MyApp/orderList/123456/15, and the PhaseListener will call testBean.setCustomerNumber("123456") and testBean.setPageNumber("15"), then cause JSF to display viewOrderList.jsp.
One final note: This PhaseListener will not affect any links rendered in the page. It was not designed to do so, though there are other more general solutions that will do so. The purpose of this component is simply to give a "pretty" entry point into an application. It is certainly possible that this will be expanded in the future to modify links created by, for example, h:commandLink to match the rules setup, but it does not do that now.





