I�m slowly, but surely, digging into all the nooks and crannies of the world of
JSF. But, coming from the
Struts way of life I have some questions about properly designing navigation in JSF.
First, these questions are prompted by the design idea that directly typing a URL into the browser of a web application should always result in something useful to the user. I.e. A user should never see an �Internal Error� or anything similar. Also, the user should never be presented with a page that doesn�t match the internal state of the application.
I�ll start with the struts example and move forward.
Let�s assume we have two
JSP pages in a struts application:
/WEB-INF/pages/widgetSearch.jsp
/WEB-INF/pages/widgetView.jsp
First, the user typing in any URL cannot directly access these JSP pages. So I don�t have to worry about pages themselves being executed with a bad application state.
The general flow of execution for these pages would be as follows:
--> SearchAction --> widgetSearch.jsp
If the user wishes to continue searching the SearchAction gets called again and the process loops.
If from the widgetSearch.jsp page the user selects a view link, the following is executed:
--> ViewAction --> widgetView.jsp
ViewAction is responsible to validating that the selected widget is available and can be viewed. If the user forged up the URL and selected a widget ID that is not valid then ViewAction will simply return to widgetSearch.jsp and no harm is done. In this last case the search page would include a message indicating the widget could not be found.
This execution path guarantees the user can�t get to widgetView.jsp without a valid widget selected. The widget may get deleted while the user is looking at it, but this will be handled by whatever action the user selects next.
It�s when I move this to JSF that things are not as obvious. In JSF I would still have two pages, plus a backing bean:
/pages/jsfWidgetSearch.jsp
/pages/jsfWidgetView.jsp
com.widgetco.WidgetBean
The searching part is straight forward, when the user enters
http://mysite/pages/jsfWidgetSearch.faces the search bean gets created, the form displays and all is well. When a user clicks on a view link an action is called, for example �WidgetBean.viewWidget()�, the same validity checks are made, the widget is loaded, and things progress to jsfWidgetView.jsp and all is well.
But, here is where things get sticky, if the user types in �http://mysite/pages/jsfWidgetView.faces� there is no controller that can easily catch this and determine that a widget is not presently selected. I�m wondering how most folks are handling this? I�ve tried a couple of different solutions but none of them seem very clean. My not so clean solutions include the following:
1) Hacking in some phase listeners to catch these situations. This isn�t very clean as it scatters navigation logic across many different places.
2) Wrapping everything in jsfWidgetView.jsp with conditional code utilizing the rendered attribute. This sort of works, but the user still ends up on the page. As opposed to being back to the search page with a message saying �Widget was not found.�
I would more than welcome suggestions on how to properly handle this issue. Maybe, being influenced by Struts, I�m just attacking the problem incorrectly. From an architectural perspective I�m concerned because most of the JSF books and tutorials suffer from this particular problem.
Thanks much,
Michael