Partial Facelets Adoption

December 11, 2006

So you have committed to JSF, but have already completed a large majority of your project before hearing about Facelets (or perhaps before it was even released). Since Facelets promises to solve the painful mismatch between JSF and JSP, you would like to take advantage of it. "But how?" you ask, because it is certainly not reasonable to think that you are going to rewrite all of your JSP files over night. Thanks to a lesser known option in Facelets, facelets.VIEW_MAPPINGS, it is possible to partially adopt Facelets by migrating only handful of pages at a time. The facelets.VIEW_MAPPING option tells Facelets which page requests the FaceletViewHandler should process. All the non-matching page requests will be passed up the chain to the default JSF view handler (JspViewHandler).

Assuming you have already gone through the required steps to setup Facelets, the only additional step is to define the pages that you would like Facelets to handle. However, before doing this step, it is necessary to revert the configuration of the javax.faces.DEFAULT_SUFFIX option back to its default value (.jsp), rather than the value that the Facelets documentation recommends (.xhtml). Since Facelets will not handle all requests, the default suffix must be appropriate for the default JSF view handler to interpret.

<context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.jsp</param-value> <!-- .jspx for XML syntax -->
</context-param>

The list of pages that Facelets will handle is configured using the facelets.VIEW_MAPPING option in web.xml. The mappings are specified as a semicolon (;) delimitted list of resources. The resources can either be a file extension (such as *.xhtml) or a resource prefix (followed by an asterisk). The resource prefix style allows for matching either a subset of pages (such as /user/*) or just a single page (such as /login.jsp*). Because of the way that Facelets does prefix matching, it is necessary to include the trailing asterisk, even when matching against a single page.

Let's assume for a moment, that you are creating a new module for managing users. All the pages are placed in the "/user/" folder at the root of the web context. In that folder we may have pages such as "list.jsp", "detail.jsp", "edit.jsp" and so on. To configure Facelets to process only the pages in this folder and the login page (/login.jsp), while allowing the default JSF view handler to deal with any other page in the web application, you will need to add the following context-param definition to your web.xml file:

<context-param>
  <param-name>facelets.VIEW_MAPPINGS</param-name>
  <param-value>/login.jsp*;/user/*</param-value>
</context-param>

This first example assumes that the same file extension is being used for both Facelets views and non-Facelets views. Another way to integrate Facelets is to use a different file extension (such as .xhtml) than what is used by the non-Facelets views. That way, it is easy to distinguish which files are handled by Facelets, and which ones are not. The configuration for that setup is a bit simpler.

<context-param>
  <param-name>facelets.VIEW_MAPPINGS</param-name>
  <param-value>*.xhtml</param-value>
</context-param>

Of course, it is also possible to use a combination of the two approaches. It depends on how you would like to name your pages.

Now you are ready to take the plunge into Facelets without having to burn the midnight oil in order to migrate the entire application at once! And believe me, once you start using Facelets, you will want to thank somebody.

Posted at 01:01 AM in Java | Permalink Icon Permalink

4 Comments from the Peanut Gallery

1 | Posted by Patrick on July 30, 2007 at 06:21 PM EST

I have tried this solution but adding the VIEW_MAPPINGS prevents all files ending in .xhtml from rendering. What's weird, the xhtml suffix is converted to .faces which then fails to map as a .jsp. Even overriding the URL to point to my XHTML as a faces extension doesn't work. Any ideas?

2 | Posted by Daniel Reznick on October 23, 2008 at 06:29 AM EST

you forgot to add another important thing:

you need to change the mapping of "Faces Servlet" into this: Faces Servlet into the followinf url-pattern /faces/* INSTEAD OF *.faces

only after adding this , it worked for me...

more info at : http://wiki.java.net/bin/view/Projects/FaceletsFAQ#How_do_I_use_Facelets_and_JSP_in

3 | Posted by Dan Allen on October 30, 2008 at 04:04 PM EST

I left out an important point, as the last two comments have highlighted. When you are using suffix mapping for the Faces Servlet (e.g., *.faces), JSF can only deal with a single file extension when it maps a URL to a view ID. In this case, you can mix and match JSP and Facelets view templates, as described in this entry, but all the files have to be using the same extension. The file extension is dictated by the javax.faces.DEFAULT_SUFFIX file context parameter. There is no such limitation when you are using prefix mapping for the Faces Servlet (e.g., /faces/*).

4 | Posted by apptaro on May 14, 2010 at 04:40 AM EST

I wrote how to use suffix mapping for partial facelets adoption: http://apptaro.seesaa.net/article/149870899.html