XML-less JSF Navigations

JSF’s declarative navigation management requires you to specify a navigation rule with navigation cases in faces-config.xml. If your application gets bigger, your faces-config.xml would get bigger as a result. Following the convention over configuration design paradigm, it is possible to avoid navigation rules in xml.

As usual we need to extend JSF and the idea is to plug-in a custom navigation handler. This navigation handler assumes the outcome is the name of the target view of the navigation.

public class LetsGetRidofXMLStuffNavigationHandler extends NavigationHandler{

    public final static String REDIRECT_PREFIX = "redirect";

    public void handleNavigation(FacesContext facesContext, String fromAction, String outcome) {
        if(outcome == null)
            return;            //no navigation

        ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
        String targetViewId = getTargetViewId(facesContext, outcome);

             ExternalContext externalContext = facesContext.getExternalContext();
             String redirectPath = viewHandler.getActionURL(facesContext, targetViewId);

             catch (IOException e)
                 throw new FacesException(e.getMessage(), e);
            UIViewRoot viewRoot = viewHandler.createView(facesContext, targetViewId);

    private boolean isRedirect(String outcome) {
        return outcome.startsWith(REDIRECT_PREFIX);

    private String getTargetViewId(FacesContext facesContext, String outcome) {
        String targetViewId;
        String viewSuffix = getDefaultViewSuffix(facesContext);

        if(isRedirect(outcome)) {
            targetViewId = "/" + outcome.split(":")[1] + viewSuffix;
        } else {
            targetViewId = "/" + outcome + viewSuffix;

        return targetViewId;

    private String getDefaultViewSuffix(FacesContext facesContext) {
        String suffix = facesContext.getExternalContext().getInitParameter("javax.faces.DEFAULT_SUFFIX");

        return suffix!=null ? suffix : ".jsp";


After implementing this navigation handler, we need to plug it in so that it can take over navigation management. In faces-config;

<?xml version="1.0" encoding="utf-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">


Now without defining an navigation rule in xml, in action binding methods just return the name of the page. For example, to navigate from a paged called login.jsf to mainpage.jsf, return “mainpage”.

public String login() {

//do some stuff

return "mainpage";


When the “mainpage” outcome reaches our navigation management, it finds the view id as /target.jsp or /target.xhtml(depending on what view technology you use) and then do a forward. For redirects add the redirect prefix so the string to be returned should be “redirect:mainpage”.

After all there is no need to define any navigation-rule in faces-config so we can get rid of this;


5 Responses to XML-less JSF Navigations

  1. Isn’t there something like this already in Myfaces (or was it tomahawk)?

  2. cagataycivici says:

    Don’t know, never seen one.

  3. Matt Raible says:

    Good stuff – is something like this going to be a part of JSF 2.0? If not, I’d love to see it added to another library (i.e. Spring or MyFaces).

  4. cagataycivici says:

    I’ve pinged Ed Burns about this today after writing the example, I hope this goes in 2.0 somehow. At least, I may commit it to myfaces.

  5. Pingback: XML-less JSF Navigation | Maxa Blog

%d bloggers like this: