An Alternative JSF Navigation Handler |
Two of the things that frustrate me about the stock JSF navigation handler are 1) I find it cumbersome to have navigation rules externalised in faces-config.xml; and 2) there is little or no possibility for reuse in XML. The CRUD pattern we use was spawning lines and lines of almost identical configuration for navigation.
Naturally the only solution to these problems is to swear a lot, post angry messages online and denounce the JCP as a disturbed, malevolent oligarchy led by individuals with as much grip on reality as a gecko has on teflon. But... I refrained.
Instead, I implemented this little NavigationHandler which allows you to shortcut the navigation rules by specifying a view id directly as an outcome:
An Alternative JSF Navigation Handler<h:commandButton actionListener="${bean.update}" action="view.xhtml"/>
The action can still be a method expression which returns the view id.
Here is the implementation, which you can also find in Furnace Webcore 1.4:
/** * An extension to the default navigation handler which allows us to * specify viewIds directly as the outcome. There is no support for * redirection, however if you need this you can specify a viewId * which simply contains a web:redirect tag. */ public class WebcoreNavigationHandler extends NavigationHandlerImpl { private Logger log = Logger.getLogger(getClass().getName()); /** * Default constructor. */ public WebcoreNavigationHandler() { super(); } /** * Override the default navigation handler to check for viewIds in * the outcome string. This simply looks for the .xhtml extension. */ @Override public void handleNavigation(FacesContext context, String fromAction, String outcome) { if (outcome != null && outcome.endsWith(".xhtml")) { // canonicalize path relative to current view String dir = "/"; if (!outcome.startsWith("/")) { dir = context.getViewRoot().getViewId(); dir = dir.substring(0, dir.lastIndexOf("/")); } try { File file = new File(dir, outcome); outcome = file.getCanonicalPath(); } catch (IOException ioe) { log.severe("Error canonicalizing " + outcome); return; } // set the specified view ViewHandler views = context.getApplication().getViewHandler(); UIViewRoot view = views.createView(context, outcome); context.setViewRoot(view); } else { super.handleNavigation(context, fromAction, outcome); } } }
You need to configure the WebcoreNavigationHandler in your faces-config.xml (this is already done for you in the Furnace jar):
<application> <navigation-handler>au.com.ninthavenue.webcore.application.WebcoreNavigationHandler</navigation-handler> </application>
Hope you find it useful :)
Roger Keays is an artist, an engineer, and a student of life. He has no fixed address and has left footprints on 40-something different countries around the world. Roger is addicted to surfing. His other interests are music, psychology, languages, the proper use of semicolons, and finding good food. |