You might have already heard about Facelets (docs), a library for Java Server Faces (JSF), and wondered why it is popular and what it is good for. I've wondered too and now I want to share the answers with you.
Warning: I'm a novice to Facelets and some things may be not completely exact.
- an alternative, non-JSP view technology and handler for JSF that gives you the power of JSP while avoiding its inherent problems with JSF
- a simple templating system similar partly to Tiles
- a way to use newer JSF (1.2) in an older servlet container (below JSP 2.1) that couldn't support it otherwise
- it's compatible with JSF 1.2 and can be used with Sun's RI or with Apache's MyFaces
It's very difficult and error-prone to use JSP to define JSF views because they've different life-cycles and just don't fit together well. Result: you must enclose most non-jsf content by f:verbatim and you may be sometimes surprised by content appearing in a different order in the resulting html. See Improving JSF by Dumping JSP by Hans Bergsten.
Facelets were designed as a view technology for JSF and let you define your views in XHTML and mix freely JSF components, xhtml, unified expression language (including custom functions), and a subset of JSTL (core, functions; for example c:if). All of these are translated into a jsf component tree and go through the same life-cycle. No more problems with mixing jsf components and jsf-unaware html: everything is a part of a component with Facelets.
You can defined your views in .xhtml, or, if you want to keep your IDE's support including autocompletion, you can use JSPX with Facelets (JSPX = JSP with xml syntax; Facelets require its view definition to be a valid xml).
Example - mypage.jspx:
<?xml version="1.0" encoding="UTF-8" ?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" version="2.0"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><title>JSPX Facelets example</title></head>
<h:messages id="messages1" styleClass="messages">
The framework provides a couple of tags that let you create and apply page templates: in a template you specify variable, page-dependant content (perhaps with some default content) using ui:insert name="...", in a page (a template client) you enclose the code that shouldn't be ignored by ui:composition template="<template file path>" and finally use some ui:define name="..." to define content for the template's ui:inserts. This let you easily define e.g. common layout in for your pages.
The description is a very brief and simplified one, refer to the Facelets templating docs to learn about its full power.
Another distinct advantage of Facelets is that it let you create extremely easily components composed from other components: you just define the composition as another xhtml fragment, define the tag to use for it in a Facelets tag library. An example from the Facelets docs:
Tag description from a Facelets taglib file mytags.taglib.xml (referenced by the context parameter facelets.LIBRARIES):
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "facelet-taglib_1_0.dtd">
And the tag definition - tags/echo.xhtml:
Called as (notice how the varaible msg is passed; the namespace 'my' is defined by: xmlns:my="http://example.com/my"):
By setting the context param facelets.DEVELOPMENT to true you instruct Facelets to display a pretty useful information whenever a processing error occures, inlcuding the exact location of the error in the xhtml/jspx. The developers have indeed taken care of providing useful output here!
When using Sun's RI, you may also want to set the context params com.sun.faces.validateXml and com.sun.faces.verifyObjects to true.
Notice: I've tried Facelets 1.0.10, but the latest version is 1.1.14 - you may prefer to try that one.
You need the following libraries in your WEB-INF/lib (versions may differ): jsf-facelets-1.0.10.jar, el-ri-1.0.jar, el-api-1.0.jar, jstl-1.1.2.jar (all included in the Facelets download).
You must not have there either Sun's RI of JSF 1.2 (jsf-api, jsf-impl) or MyFaces libs (myfaces-api-1.1.2-SNAPSHOT.jar, myfaces-impl-1.1.2-SNAPSHOT.jar). The RI requires Java 1.5 that may not be possible to use for political reasons and myfaces conflict with myfaces libraries bundled with JBoss in <jboss>\server\default\deploy\jbossweb-tomcat55.sar\jsf-libs.
Note: If Tomcat cannot find the myfaces TLDs and complains about unmapped namespace http://java.sun.com/jsf/html or core, extract the TLDs from the myfaces jars and put them somewhere under your WEB-INF.
That's all - assuming you've set your web.xml and faces-config.xml correctly. In web.xml you don't need anything special outside of normal JSF configuration (Faces servlet and startup listener) unless using extension mapping instead of the prefix /faces/* - in that case you must also specify .xhtml (or .jspx) as the default suffix of JSF pages using the context param. javax.faces.DEFAULT_SUFFIX. In faces-config.xml you need to set Facelets as the view handler (you may define for which resources it should be used, delegationg all others to the default jsp view handler, via its context param. facelets.VIEW_MAPPINGS):
<application> <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> </application>
That's all folks, thank you for attention!