Search code examples
javajsfweb-applicationsservletsurl-mapping

In JSF, can I suppress part of the directory hierarchy of an XHTML file in the URL?


In a JSF application, we have the directory hierarchy:

webapp
  xhtml
    login.xhtml
    main.xhtml
    search.xhtml
  css
    main.css
    extra.css
  js
    jquery.js

etc. The servlet mapping is:

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

This works fine, but the URLs of our web app look like this:

http://localhost/myapp/xhtml/login.xhtml
http://localhost/myapp/xhtml/search.xhtml

We would like to have simpler URLs by dropping the /xhtml part, i.e. http://localhost/myapp/login.xhtml

I could not find any way to accomplish this. Is there some way to do this in the <servlet-mapping>? Do I need some additional framework?


Solution

  • You could do it with a Filter. Either homegrown or a 3rd party one like URLRewriteFilter. Just map it on *.xhtml and then forward to /xhtml/*.

    Something like:

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    
    String ctx = request.getContextPath();
    String uri = request.getRequestURI();
    String viewId = uri.substring(ctx.length(), uri.length());
    
    if (viewId.startsWith("/xhtml")) {
        // Redirect to URL without /xhtml (changes URL in browser address bar).
        response.setStatus(301);
        response.setHeader("Location", ctx + viewId.substring("/xhtml".length());
        // Don't use response.sendRedirect() as it does a temporary redirect (302).
    } else {
        // Forward to the real location (doesn't change URL in browser address bar).
        request.getRequestDispatcher("/xhtml" + viewId).forward(request, response);
    }
    

    But simpler would be to just change the directory hierarchy to get rid of /xhtml subfolder. Those CSS/JS (and image) files should preferably be placed in a /resources subfolder so that you can utilize the powers of <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> in a proper way.

    See also: