Facelets - JavaServer Faces View Definition Framework

Developer Documentation


Table of Contents

Documentation Guide
1. Getting Started with Facelets
1.1. Downloading Facelets
1.2. Dependencies
1.3. Directory Structure
1.4. Project Setup
1.4.1. Web.xml Descriptor
1.4.2. Faces-Config.xml
1.5. The NumberBean
1.5.1. The Java Code
1.5.2. Faces Bean Descriptor
1.6. Creating Web Pages
1.6.1. The Page Template - template.xhtml
1.6.2. Configuring User Input - guess.xhtml
1.6.3. Displaying the Response - response.xhtml
1.7. Handling Navigation
1.8. Deployment
2. Configuration
2.1. Configuring JavaServer Faces
2.1.1. JavaServer Faces RI
2.1.2. Apache MyFaces
2.2. Web Application Descriptors
2.2.1. Initialization Parameters
2.2.2. Security
2.3. Logging
3. Tag Libraries
3.1. Using Tags
3.1.1. Tag Namespaces
3.1.2. Using 'jsfc'
3.1.3. Unresolved Namespaces
3.2. Available Tag Libraries
3.2.1. JavaServer Faces Specification
3.2.2. Templating Library
3.2.3. JSTL Support
3.2.4. Oracle ADF Faces
3.3. Functions
3.4. Loading Libraries
3.5. Creating Tag Libraries
3.5.1. Tag Library Schema
3.5.2. UIComponents
3.5.3. Validators
3.5.4. Converters
3.5.5. Tag (Source) Files
3.5.6. Custom Tags
3.5.7. Function Specification
4. Expression Language
4.1. Inlining Text
4.2. EL Lifecycle
5. Templating and Re-Use
5.1. Template/Client Relationships
5.1.1. Wrapping Content within a Template
5.1.2. Piecemeal Content within a Template
5.1.3. Multi-Level Templating
5.2. <ui:component/>
5.3. <ui:composition/>
5.4. <ui:debug/>
5.5. <ui:decorate/>
5.6. <ui:define/>
5.7. <ui:fragment/>
5.8. <ui:include/>
5.9. <ui:insert/>
5.10. <ui:param/>
5.11. <ui:remove/>
5.12. <ui:repeat/>
6. Facelets Architecture
6.1. View Creation
6.2. Facelets API
6.2.1. FaceletFactory
6.2.2. Facelet
6.2.3. FaceletHandler
6.3. Document Compiler
7. Extending Facelets
7.1. Tag Development Overview
7.2. Custom TagHandlers
7.3. Meta Tags
7.3.1. Custom ComponentHandlers
7.3.2. Custom ValidateHandlers
7.3.3. Custom ConvertHandlers
7.4. FaceletViewHandler
7.5. Tag Decorators
8. Building Facelets
8.1. Using Ant
8.2. IDE Integration

The web community is eagerly seeking a light-weight, templating framework backed by JavaServer Faces as the industry standard. While JavaServer Faces and JavaServer Pages technology (JSP) are meant to be aligned, Facelets steps outside of the JSP specification and provides a highly performant, JSF-centric view technology. Anyone who has created a JSP page will be able to do the same with Facelets and familiar XML-tag use. The difference is under the hood where all the burden of the JSP vendor API is removed to greatly enhance JSF as a platform and provide easy plug-and-go development without requiring JSP tag development.

JavaServer Faces UIComponents are first class citizens within Facelets; there's no need to develop extra objects to integrate. There's also no need to learn yet another XML schema to define your views.

Facelets includes many features such as:

Everyone wants to be more designer friendly, and Tapestry seems to be the only choice developers are pursuing. On the other hand, JSF is the standard everyone would like to have happen, but JSF needs a more "pluggable" ViewHandler framework that is both designer and developer friendly.

Out of the box, Facelets provides full support for all components specified in the JavaServer Faces specification, including limited support for JSTL tags such as <c:forEach> and <c:if>. Where developers really gain an advantage with using Facelets is its ability to auto-wire additional artifacts to your XML documents such as UIComponents, Validators, and Converters.

Facelets is a clean slate for correcting concerns with JSF. Templating, re-use, and ease of development are top priorities that will help bring developers on board with JSF as a suitable platform for large scale projects.

To get a jump start on development, this guide covers varying degrees of depth. Please follow these steps:

Additional documentation and resources such as: mailing lists, forums, and announcements, are available on Facelets' home page at:

  • http://facelets.dev.java.net

This section will walk you through creating a simple Number Guess web application. Familiarity with Java Web Applications is required along with some knowledge of JavaServer Faces. For those who are new to those technologies, you can browse:

The steps in this tutorial are as follows:

  1. Section 1.1, “Downloading Facelets” for downloading Facelets binaries or for accessing Facelets source code from CVS.

  2. Section 1.2, “Dependencies” will provide an overview of libraries needed to use JavaServer Faces with Facelets

  3. Section 1.3, “Directory Structure” shows the familiar directory structure you should use for this tutorial

  4. Section 1.4, “Project Setup” has initial configuration settings you need to get up and running

  5. Section 1.5, “The NumberBean” details the one JavaBean our tutorial requires and how to use it in JavaServer Faces

  6. Section 1.6, “Creating Web Pages” shows how to create and use a template within JavaServer Faces components

  7. Section 1.7, “Handling Navigation” includes how to tie your views together

  8. Section 1.8, “Deployment” finishes off the tutorial with deploying your application

While this tutorial is a little basic for some, you may want to jump back to Documentation Guide for direction.

Facelets will work with both version 1.1 and 1.2 of JavaServer Faces and makes no bearing on the implementation used. Facelets also uses the new EL-API and again can be used with any implementation of that API. Please reference the table below to make sure your dependencies are available to Facelets:

For more information on using these projects:

We will have a simple, straight-forward JavaBean that will act as our 'controller' for our NumberGuess tutorial. Note that the desired class name will be tutorial.NumberBean.

package tutorial;

import java.io.Serializable;

import java.util.Random;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

public class NumberBean implements Serializable {

  protected final static Random rand = new Random();

  protected int min;
  protected int max;
  protected int guess;
  protected int actual;
  // Default Constructor
  public NumberBean() {
    this.min = 1;
    this.max = 10;
  // called by JSF to validate user input
  public void validate(FacesContext context, UIComponent component, Object value)
      throws ValidatorException {
    // coerce the value to an int
    try {
      int param = Integer.parseInt(value.toString());
      // validate param
      if (param > this.max || param < this.min) {
          FacesMessage msg = new FacesMessage("Guess must be between "+this.min+" and "+this.max);
          throw new ValidatorException(msg);
    } catch (NumberFormatException e) {
      FacesMessage msg = new FacesMessage("Must be a number");
      throw new ValidatorException(msg);
  // lazy generate our actual value
  public synchronized int getActual() {
    if (this.actual == 0) {
        this.actual = rand.nextInt(this.max-this.min);
        this.actual += this.min;
    return this.actual;
  // our message for the response
  public String getMessage() {    
    if (this.guess == this.getActual()) {
      return "Sweet, you got it right!";
    } else if (this.guess < this.getActual()) {
      return "Sorry, try something higher";
    } else {
      return "Too bad, go lower";
  // other bean properties
  public int getMin() { return this.min; }
  public int getMax() { return this.max; }
  public int getGuess() { return this.guess; }
  public void setMin(int min) { this.min = min; }
  public void setMax(int max) { this.max = max; }
  public void setGuess(int guess) { this.guess = guess; }

The above class should be compiled with Java and located at $DEPLOY_DIR/WEB-INF/classes/tutorial/NumberBean.class. If you do not know how to compile Java classes, please stop this tutorial and go to http://java.sun.com for introductory help.

This section contains the only content the "Getting Started" chapter that is entirely specific to Facelets.

Facelets emphasizes its ability to template content in your application. Templating promotes re-use and eases long term maintenance of your application, allowing content to be changed in one spot, but used in multiple pages. While using templating features wouldn't be necessary for this simple application, it does serve as a tutorial. For more information on this topic, see Chapter 5, Templating and Re-Use.

We will create three documents: a template page, a page for user input, and finally a page to display a response:

   [newly added pages below]
+- /template.xhtml
+- /guess.xhtml
+- /response.xhtml

Facelets comes with a library of UI (user interface) tags to use in writing your application. We will only focus on using a couple of them in creating a page called template.xhtml.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Facelets: Number Guess Tutorial</title>
<style type="text/css">
body {
  font-family: Verdana, Arial, Helvetica, sans-serif;
  font-size: small;

  <ui:insert name="title">Default Title</ui:insert>
  <ui:insert name="body">Default Body</ui:insert>


Facelets requires valid XML markup. Our sample application is using valid XHTML since these documents will be used on the web. You can even view this document within your favorite visual tool. A couple things to take notice of:

In this example page, we will incorporate components from the JavaServer Faces standard component libraries.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"

This text above will not be displayed.

<ui:composition template="/template.xhtml">

This text will not be displayed.

  <ui:define name="title">
    I'm thinking of a number from #{NumberBean.min} to #{NumberBean.max}.  Can you guess it?

This text will also not be displayed.

  <ui:define name="body">
    <h:form id="helloForm">
      <h:inputText type="text" id="userNo" value="#{NumberBean.guess}" validator="#{NumberBean.validate}"/>
      <h:commandButton type="submit" id="submit" action="success" value="Submit" />
      <h:message showSummary="true" showDetail="false" style="color: red; font-weight: bold;" id="errors1" for="userNo"/>

This text will not be displayed.

This text below will also not be displayed.


If you have questions or do not understand the attributes used for <h:inputText>, <h:commandButton>, or <h:message>; documentation on those components are available at http://java.sun.com/j2ee/javaserverfaces. Keep in mind that Facelets uses the same attributes, behavior, and naming conventions as the tags specified for JavaServer Faces' JSP TLD documents.

We would like to tie our two pages together from guess.xhtml to response.xhtml and back again. To do this, we need to go back into the faces-config.xml to specify navigation cases.

  <!-- from project setup -->
  <!-- our NumberBean we created before -->
  <!-- going from guess.xhtml to response.xhtml -->

  <!-- going from response.xhtml to guess.xhtml -->


In both pages, we included commandButtons in some form with action attributes specified. The action attribute is mapped to the <from-outcome> element in your faces-config.xml. This method of handling navigation is extremely flexible and more information on this aspect of JavaServer Faces is included at http://java.sun.com/j2ee/javaserverfaces.

Facelets comes with an extensible ViewHandler. This is the only necessary integration point within your faces-config.xml.


The FaceletViewHandler utilizes several <context-param> declarations in your web.xml which are detailed in Section 2.2.1, “Initialization Parameters”.

See Chapter 1, Getting Started with Facelets for a tutorial that uses JavaServer Faces RI as an example. More information on the JSF RI is available at:

  • http://javaserverfaces.dev.java.net

These parameters help with development and increase the flexibility of Facelet use.

Table 2.1. Web.xml Parameter List

Parameter NameDefault ValueDescriptionExample
facelets.LIBRARIES A semicolon (;) delimitted list of paths to Facelet tag libraries, relative to your application's root. These libraries will be loaded when the first request hits the FaceletViewHandler for page compilation./WEB-INF/facelets/foo.taglib.xml; /WEB-INF/facelets/bar.taglib.xml
facelets.DECORATORS A semicolon (;) delimitted list of class names of type com.sun.facelets.tag.TagDecorator, with a no-argument constructor. These decorators will be loaded when the first request hits the FaceletViewHandler for page compilation.com.sun.facelets.tag.jsf.html.HtmlDecorator
facelets.DEVELOPMENTfalseSetting this to true will cause the FaceletViewHandler to print out debug information in an easy to use screen when an error occurs during the rendering process.true
facelets.BUFFER_SIZE-1The buffer size to set on the response when the ResponseWriter is generated. By default the value is -1, which will not assign a buffer size on the response. This should be increased if you are using development mode in order to guarantee that the response isn't partially rendered when an error is generated.8192
facelets.REFRESH_PERIOD2When a page is requested, what interval in seconds should the compiler check for changes. If you don't want the compiler to check for changes once the page is compiled, then use a value of -1. Setting a low refresh period helps during development to be able to edit pages in a running application.-1
facelets.RESOURCE_RESOLVERcom.sun.facelets.impl.DefaultResourceResolverOptionally provide an alternate ResourceResolver that will replace the default logic of allowing the FacesContext resolve the resource URL.my.company.IDEResourceResolver
facelets.VIEW_MAPPINGS A semicolon (;) delimitted list of resources that Facelets should use. If no resource paths are specified, Facelets will handle all requests (DEFAULT). If one or more paths are specified, Facelets will only use the ones specified, otherwise fall back on the parent or default ViewHandler (JSP). Note, this requires the FacesServlet in your web.xml to be mapped with a prefix for capturing multiple file types ex: /faces/*./demos/*; *.xhtml
facelets.SKIP_COMMENTStrueA boolean value that tells the compiler to skip comments (default is true). Even if you comment out code in your page, the tags will not be compiled but expressions (EL) will be treated as if they were inlined-- still compiled and evaluated for output in the document. Skipping comments will remove all comments completely from the document.false

Facelets includes limited support for JSTL 'tags' within the Core and Function library only. Here is the link to Function and Core documentation from JSTL:

The Function library is implemented, according to the spec in its entirety. The Core library has the following implementations:

A note about EL within this JSTL implementation. Since all set variables from these tags are backed by the new EL API, the only scope they can bind to is within the current FaceletContext, no others. This means that variables only can exist for the benefit of creating the component tree for JSF and do not work to assign variables in other scopes. The reason for this is that the Expressions are actually bound to the FaceletContext, not the evaluted Object. This is to better serve JSF tree creation.

As part of the EL Specification, you can incorporate static Java methods into your documents. The JSTL library already has some of these functions available, see Section 3.2.3, “JSTL Support”.

Functions are declared within EL in the following format: #{fn:sizeOf(myCollection)}. What that line says is to reference the tag library using the prefix fn for a function named sizeOf. This syntax should feel similar to what's required for using tags from imported libraries.

Any tag library can offer any amount of functions. Please reference the particular library's documentation for function names and parameters information.

Tag libraries can be loaded multiple ways. First Facelets will load all libraries from your classpath (including packaged Jars) and then any libraries you have specified in your web.xml.

The schema (or DTD) for Facelets is extremely simple. Future releases of Facelets will actually just use your faces-config.xml files the same way a visual tool would for determining required attributes and namespaces.

Facelets currently uses the following doc type:

<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"

This is the (simple) DTD that Facelets uses:

<!ELEMENT facelet-taglib (library-class|(namespace,(tag|function)+))>
<!ATTLIST facelet-taglib xmlns CDATA #FIXED "http://java.sun.com/JSF/Facelet">
<!ELEMENT namespace (#PCDATA)>
<!ELEMENT library-class (#PCDATA)>
<!ELEMENT tag (tag-name,(handler-class|component|converter|validator|source))>
<!ELEMENT tag-name (#PCDATA)>
<!ELEMENT handler-class (#PCDATA)>
<!ELEMENT component (component-type,renderer-type?,handler-class?)>
<!ELEMENT component-type (#PCDATA)>
<!ELEMENT renderer-type (#PCDATA)>
<!ELEMENT converter (converter-id, handler-class?)>
<!ELEMENT converter-id (#PCDATA)>
<!ELEMENT validator (validator-id, handler-class?)>
<!ELEMENT validator-id (#PCDATA)>
<!ELEMENT source (#PCDATA)>
<!ELEMENT function (function-name,function-class,function-signature)>
<!ELEMENT function-name (#PCDATA)>
<!ELEMENT function-class (#PCDATA)>
<!ELEMENT function-signature (#PCDATA)>

As you can see, JSF entities are treated as first class citizens in Facelets' tag libraries. A couple things to observe from the schema above:

The following sections describe how to integrate your objects within the XML tag library.

UIComponents can be auto-wired by using the component element in your tag library.


In the above example, we are binding a component of type (not Class) com.mycompany.Data to the tag name bar. A renderer-type is also provided, but not required since UIComponents can easily render themselves.

Based on if your component implements ActionSource[2], ValueHolder, or EditableValueHolder, Facelets will take care of auto-wiring those standard attributes according to the specification. Facelets differs greatly from JSP in this important regard, and this difference is a feature of Facelets that takes advantage of the dynamism in JavaServer Faces that is wasted on JSP. Specifically, any tag attribute in a Facelets page is tolerated. If the value of the attribute is a ValueExpression, and tag is associated with a UIComponent, the expression is stored in the components's ValueExpression Map. Otherwise, Facelets looks for a JavaBeans property on the component whose name is equal to the tag attribute name. If it exists, its setter is called with the value of the tag attribute. If it doesn't exist, an entry is created in the generic attribute set for the component, the value of which is the value of the tag attribute. The upshot of all this is that turnaround time is greatly reduced because you can modify the component and/or renderer without having to change a TLD. Of course, the downside is that any attribute is legal, but errors in that regard are logged in the logging system.

This approach exemplifies a general philosophy of Facelets, sensible default behavior from the perspective of the page developer.

The attribute wiring behavior also applies to validators, EL expressions, converters, etc. Any additional properties on your component will also be wired for you too, just as JSP sets the properties on a JspTag. If you think that Facelets can't handle the special wiring your component needs, then skip to Section 7.3.1, “Custom ComponentHandlers”.

If you've just created a UIComponent from scratch and you are not sure how to integrate it into JavaServer Faces, here's all the code you need:


Notice that the component-type matches the one used in the Facelets tag library XML. This degree of indirection by referencing components by type increases the maintainability and portability of JavaServer Faces components.

When describing templating within Facelets, we have two roles: the template and the template client.

Any document can act as a template; but what makes a document a template? It just simply uses one or more <ui:insert/> tags to inject content from another source.

The other half of the equation is the template client. This includes documents that use the <ui:component/>, <ui:composition/>, <ui:fragment/>, or <ui:decorate/>. Each of those tags is detailed in the sections below.

The component tag and the composition tag (below) behave exactly the same, except the component tag will insert a new UIComponent instance into the tree as the root of all the child components/fragments it has.

Text before will be removed.
<ui:component binding="#{backingBean.menu}">
  <ul id="mainMenu">
  <c:forEach var="link" items="#{menuOptions[role]}">
	  <c:when test="#{link.id == page}">
		<li class="current"><a href="#{link.uri}">#{link.text}</a></li>
		<li><a href="#{link.uri}">#{link.text}</a></li>
Text after will be removed.

Using the ability to use Tag files in your tag libraries, see Section 3.5.5, “Tag (Source) Files”, you could include the above component into your pages while having the attributes automatically made available as variables within the document above:

<span id="header">
  <my:mainMenu page="home" role="#{user.role}"/>

Pretty cool eh?

The remove tag does not have any attributes and is used to remove chunks of XML content from a Facelet at compilation time. The remove tag is often used in conjunction with the jsfc feature, see Section 3.1.2, “Using 'jsfc'”.

  This will be removed.
<span jsfc="ui:remove">
	This won't be compiled either <h:outputText value="#{foo.bar}"/>

There are times in development when you need to quickly remove parts of the document just for testing purposes, or you would like to leave a 'template-model' in your document, but don't want it to be part of the final Facelet.

The repeat tag should be used in almost all cases instead of the c:forEach to iterate over content with JSF. The repeat tag is often used in conjunction with the jsfc feature, see Section 3.1.2, “Using 'jsfc'”.

    <ui:repeat value="#{company.departments}" var="dept">
	    <ui:repeat value="#{dept.employees}" var="emp">
		<dd>#{emp.lastName}, #{emp.firstName}</dd>

While this is a great step for JSF compositions, we can do better with the jsfc attribute where the repeat tag will provide some special behavior inclusive of the declared tag.

<tr jsfc="ui:repeat" value="#{dept.employees}" var="emp" class="#{emp.manager ? 'mngr' : 'peon'}">

Under the JavaServer Faces specification, there are some preliminary steps that must be covered when building views. This section will cover that process and its lifecycle in relation to Facelets.

  1. A request comes in to JavaServer Faces for a new view (or page). The FaceletViewHandler simply creates a new UIViewRoot for this new view.

  2. Since this is a new view being requested, we immediately render our view. Before rendering, Facelets needs to populate the view with components. At this time, the FaceletFactory is used to build a Facelet that will act as build instructions for the desired view. The UIViewRoot is applied to the Facelet and the view is populated for rendering.

  3. The UIViewRoot (view) is then asked to render itself back to the response.

  4. The user sees a completed web page and the state of the view is automatically stored for the next request. Note, all the inlined text and other transient components will not be stored, only 'crucial' component information such as input components and form data.

  5. The user clicks a button, causing a second request to come back to JavaServer Faces. This time, the view is restored from the previously stored state. Keep in mind, the view at this point only has the 'crucial' components available from the previous request.

  6. This restored view is passed through the JavaServer Faces lifecycle and eventually we will either generate a new view for another page, or re-render your current view if there were validation problems or no action was fired.

  7. In the case of re-rendering the view, the partial view that was restored is now rendered again. Before it's rendered, the same Facelet is used to re-populate the full view with inlined text and transient components.

  8. The UIViewRoot (view) is then asked to render itself back to the response.

  9. Repeat this process until another (new) view is requested.

The first take-away from those steps is that the same Facelet can be used multiple times with the same view. Basically, the process of building the view (a.k.a component tree) can go through many cycles of populating, rendering, trimming for state saving, then restored again-- repeat.

Facelets is founded on simple principles and the API is a solid reflection of it. The framework is focused on one specific task, and that's tree creation and content interweaving-- taking an XHTML or XML document and using it as instructions to populate a tree of UIComponents. That's it.

The JavaServer Faces platform is extremely extensible on many levels and Facelets only provides one part of that equation. Different render kits, controllers, components, validators, converters, frameworks-- all usable with Facelets. That's the beauty of JavaServer Faces as a platform that Facelets only seeks to enhance.

Facelets use stateless TagHandlers to coordinate tree creation. TagHandlers are not like JSP tags in that Facelets builds a static/stateless tree of TagHandlers shared by all requests. For more information on how Facelets coordinates view creation, see Section 6.1, “View Creation”.

Foundation classes, such as those included in Section 7.3, “Meta Tags”, will take care of the knowing when to apply state and build up the component tree for a given request. If you are writing your own TagHandler, you can use the ComponentSupport.isNew(UIComponent) to determine if it's okay for you to modify the newly created UIComponent.

public void apply(FaceletContext ctx, UIComponent parent) {
  if (ComponentSupport.isNew(parent)) {
    // okay to apply new state information to component

For JSTL-like functionality, it's up to you if you want to use the ComponentSupport.isNew(UIComponent) method to determine behavior. But again, if you use the foundation handlers in Section 7.3, “Meta Tags”, these checks will be take care of for you.

Facelets are composed of many different kinds of TagHandler instances. Just like a Facelet, all of the TagHandlers are stateless for offering a higher degree of performance. This section goes over customizing your tag library with your own tags, beyond what the default features of Facelets can offer you within the tag library XML configs.

Facelets allows you to write stateless tags that can be used in dictating component tree creation. This includes JSTL-like functionality that may be tied to business logic. Including your custom tag into your library requires using the handler-class element.


All tags in a Facelets extend com.sun.facelets.tag.TagHandler which provides some base functionality for tying XML data to your Java code. Here is an example of JSTL's <c:if/> tag:

public final class IfHandler extends TagHandler {

  // possible attributes
  private final TagAttribute test;
  private final TagAttribute var;

   * @param config
  public IfHandler(TagConfig config) {
      // helper method for getting a required attribute
      this.test = this.getRequiredAttribute("test");
      // helper method
      this.var = this.getAttribute("var");

   * Threadsafe Method for controlling evaluation of
   * its child tags, represented by "nextHandler"
  public void apply(FaceletContext ctx, UIComponent parent)
          throws IOException, FacesException, ELException {
      boolean b = this.test.getBoolean(ctx);
      if (this.var != null) {
          ctx.setAttribute(var.getValue(ctx), new Boolean(b));
      if (b) {
          this.nextHandler.apply(ctx, parent);

Now if that isn't easy, I don't know what is. Facelets uses the concept of a TagAttribute which encapsulates EL operations for you and also produces informative exceptions if an error did occur. Another really great example is catching exceptions with JSTL's CatchHandler:

public final class CatchHandler extends TagHandler {

  private final TagAttribute var;

  public CatchHandler(TagConfig config) {
      this.var = this.getAttribute("var");

  public void apply(FaceletContext ctx, UIComponent parent)
          throws IOException, FacesException, FaceletException, ELException {
      try {
          this.nextHandler.apply(ctx, parent);
      } catch (Exception e) {
          if (this.var != null) {
              ctx.setAttribute(this.var.getValue(ctx), e);

Isn't that awesome? The TagHandler provides some member variables, much like a JSP tag, to help you:

For more information on the inner workings of Facelets, please hop over to Chapter 6, Facelets Architecture.

The Facelets API understands that developers will run into cases where they need 'special' logic for setting attributes. The API provides a few foundation TagHandlers that you can extend to handle unique cases. These foundation classes take care of the dirty work of tree creation in JavaServer Faces.

com.sun.facelets.tag.MetaTagHandler acts as the foundation for auto-wiring abilities in Facelets. The MetaTagHandler uses a few objects: MetaRuleset, MetaRule, and Metadata to coordinate auto-wiring. The following sub sections provide examples of this coordination to customize specialized components.

The MetaTagHandler provides a couple methods for extension: setAttributes(FaceletContext,Object) and createMetaRuleset(Class). The method setAttributes(FaceletContext,Object) will be invoked for you by the classes described below which will take care of wiring all attributes according to the MetaRuleset created by createMetaRuleset(Class).

Anytime you do provide custom tags (handlers), you would use the handler-class element in your tag just as described in Section 3.5.6, “Custom Tags”.

Continuing on the capabilities in customizing Validators within Facelets, you may do the same with Converters by extending com.sun.facelets.tag.jsf.ConvertHandler.

public final class ConvertNumberHandler extends ConvertHandler {

    private final TagAttribute locale;

    public ConvertNumberHandler(TagConfig config) {
        this.locale = this.getAttribute("locale");

     * Returns a new NumberConverter
     * @see NumberConverter
     * @see com.sun.facelets.tag.jsf.ConverterHandler#createConverter(com.sun.facelets.FaceletContext)
    protected Converter createConverter(FaceletContext ctx)
            throws FacesException, ELException, FaceletException {
        return ctx.getFacesContext().getApplication().createConverter(NumberConverter.CONVERTER_ID);

    /* (non-Javadoc)
     * @see com.sun.facelets.tag.ObjectHandler#setAttributes(com.sun.facelets.FaceletContext, java.lang.Object)
    protected void setAttributes(FaceletContext ctx, Object obj) {
        super.setAttributes(ctx, obj);
        NumberConverter c = (NumberConverter) obj;
        if (this.locale != null) {
            c.setLocale(ComponentSupport.getLocale(ctx, this.locale));

    protected MetaRuleset createMetaRuleset(Class type) {
        return super.createMetaRuleset(type).ignore("locale");

This is probably the best example of customization so far. The ConvertHandler allows you to override the method createConverter(FaceletContext) to return any Converter instance. Also, the setAttributes(FaceletContext,Object) was overridden to do special wiring for the Locale on the NumberConverter.

The NumberConverter has many properties, but we only wanted to make a special case for locale, so we only tell the MetaRuleset to ignore that one attribute because we will take care of it ourselves.