facelets - javaserver faces

31
Facelets - JavaServer Faces View Definition Framework Developer Documentation Jacob Hookom Editing and bug fixes: Ed Burns Editing: Hiroshi Iwatani 1.0.0 Table of Contents Introduction 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 Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html 1 de 31 4/12/2010 22:20

Upload: wiltonor

Post on 03-Apr-2015

309 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Facelets - JavaServer Faces

Facelets - JavaServer Faces View Definition

Framework

Developer Documentation

Jacob Hookom

Editing and bug fixes: Ed Burns

Editing: Hiroshi Iwatani

1.0.0

Table of Contents

Introduction

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

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

1 de 31 4/12/2010 22:20

Page 2: Facelets - JavaServer Faces

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

Introduction

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:

Works with JSF 1.1 and JSF 1.2, including Sun's RI and Apache MyFaces.

Zero Tag development time for UIComponents

Fast Templating/Decorators for Components and Pages

The ability to specify UIComponent trees in separate files (UICompositions)

Line/Tag/Attribute precise Error Reporting

Specify Tags in Separate Files, even packaged with Jars

Full EL support, including Functions

Build-time EL Validation

XML configuration files aren't necessary

Reserves the 'jsfc' attribute which acts the same as Tapestry's jwcid (Example: <input id="bar" type="text"

jsfc="h:inputText" value="#{foo.bar}"/>)

Plugable Decorators to really make designer's job easy (Example: transform <input type="text"/> to <h:inputText/> at

compile time)

Works with any RenderKit

Facelet APIs aren't dependent on a Web Container

Everyone wants to be more designer friendly, and Tapestry seems to be the only choice developers are pursuing. On the other hand,

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

2 de 31 4/12/2010 22:20

Page 3: Facelets - JavaServer Faces

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.

Documentation Guide

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

Chapter 1, Getting Started with Facelets as an entry-level tutorial on using JavaServer Faces and Facelets together. All of the

content in this section is generic to Faces with the exception of Section 1.6, “Creating Web Pages”. This section describes the

simplest Facelets templating scenario that could possibly work.

Chapter 2, Configuration for details on setting up your web application for use with Facelets.

Chapter 3, Tag Libraries for incorporating JSF objects into Facelet documents as tags.

Chapter 5, Templating and Re-Use to learn about how Facelets encourages templating and re-use in your documents.

Chapter 6, Facelets Architecture as an overview to the Facelets API and compiler.

Chapter 7, Extending Facelets as a starting point for extending Facelets functionality with custom tag handlers.

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

http://facelets.dev.java.net

Chapter 1. Getting Started with Facelets

Tutorial Goals

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:

Java Web Applications - http://www.onjava.com/pub/a/onjava/2001/03/15/tomcat.html

JavaServer Faces - http://java.sun.com/j2ee/javaserverfaces/

The steps in this tutorial are as follows:

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

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

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

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

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

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

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

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

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

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

3 de 31 4/12/2010 22:20

Page 4: Facelets - JavaServer Faces

1.1. Downloading Facelets

Facelets is currently available as a sub-project of the JavaServer Faces Reference Implementation on Java.net

(http://facelets.dev.java.net/). You have a couple options for downloading Facelets:

Download a release binary from http://facelets.dev.java.net/servlets/ProjectDocumentList. Once downloaded, unzip the

project into an appropriate folder.

If you are a member of Java.net, you may checkout Facelets from CVS. Make sure you are located in the appropriate directory

and use the following CVS commands (Replace USER_NAME with your Java.net Member Login Name):

cvs -d :pserver:[email protected]:/cvs login1.

cvs -d :pserver:[email protected]:/cvs checkout facelets2.

More information on accessing Java.net's CVS repository is located at http://facelets.dev.java.net/servlets/ProjectSource.

See Chapter 8, Building Facelets for more information on building Facelets from source (specifically if you used CVS).

1.2. Dependencies

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:

Table 1.1. Facelets Dependencies

ProjectBuild

Req?Included? Description Link

JavaServer

Faces RINo No

The reference implementation of JSF 1.1 and JSF 1.2

are available for use with your application.http://javaserverfaces.dev.java.net/

Apache

MyFacesNo No

The alternative to the JSF reference implementation.

MyFaces currently implements the JSF 1.1

specification.

http://myfaces.apache.org/

JavaServer

Faces 1.2 APIYes No

JSF 1.2 API that works with the new EL Specification.

This API is packaged with the JavaServer Faces RI and

available on Java.net.

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

EL API Yes YesThe standardized EL specification that is standalone

from JSP or JSF, but used by both frameworks.http://glassfish.dev.java.net/

EL RI No YesThe reference implementation that is used by Facelets

for handling EL.http://glassfish.dev.java.net/

XML SAX Yes No

This dependency should not be an issue for most

deployments as it's a standard part of web containers

and JREs.

http://java.sun.com/xml/

For more information on using these projects:

Those projects that are required to build Facelets, please see Chapter 8, Building Facelets.

If you would like to use Apache MyFaces with Facelets, see Section 2.1.2, “Apache MyFaces”.

To use Facelets with the JavaServer Faces Reference Implementation, see Section 2.1.1, “JavaServer Faces RI”.

1.3. Directory Structure

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

4 de 31 4/12/2010 22:20

Page 5: Facelets - JavaServer Faces

Since we are putting together a sample web application, your project should have the following directory structure (presumes JSF RI

use):

$DEPLOY_DIR+- /WEB-INF +- /classes +- /lib +- /jsf-facelets.jar +- /el-api.jar +- /el-ri.jar [jsf implementation dependencies] +- /jsf-api.jar +- /jsf-impl.jar +- /commons-digester.jar +- /commons-logging.jar +- /commons-collections.jar +- /commons-beanutils.jar +- /web.xml +- /faces-config.xml+- /[xhtml documents]

For more information on web application deployments in general, there is additional documentation at http://java.sun.com/j2ee

and at http://jakarta.apache.org/tomcat.

1.4. Project Setup

1.4.1. Web.xml Descriptor

First configure your application's web.xml. Make sure that the FacesServlet is mapped and JSF's javax.faces.DEFAULT_SUFFIX

initialization parameter is specified. This standard initialization parameter lets JSF know what documents to use for specifying your

views.

<web-app>

<!-- Use Documents Saved as *.xhtml --> <context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.xhtml</param-value> </context-param> <!-- Special Debug Output for Development --> <context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param>

<!-- Optional JSF-RI Parameters to Help Debug --> <context-param> <param-name>com.sun.faces.validateXml</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>com.sun.faces.verifyObjects</param-name> <param-value>true</param-value> </context-param>

<!-- Faces Servlet --> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>

<!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping>

</web-app>

1.4.2. Faces-Config.xml

JavaServer Faces is extremely interoperable with other frameworks. Most of this flexibility lies in JSF's Application composite

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

5 de 31 4/12/2010 22:20

Page 6: Facelets - JavaServer Faces

which includes: a default ActionListener, ELResolver, StateManager, NavigationHandler, and ViewHandler. Facelets is used as

the application's ViewHandler, represented by the class com.sun.facelets.FaceletViewHandler.

To configure JavaServer Faces to use Facelets as the ViewHandler, modify your project's faces-config.xml to specify the <view-

handler> element:

<faces-config> <application> <view-handler> com.sun.facelets.FaceletViewHandler </view-handler> </application> </faces-config>

Even though there are other parts to the faces-config.xml needed for this tutorial, only the <view-handler> element is required

for Facelets use.

1.5. The NumberBean

1.5.1. The Java Code

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; }

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

6 de 31 4/12/2010 22:20

Page 7: Facelets - JavaServer Faces

// 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.

1.5.2. Faces Bean Descriptor

You can map JavaBeans into your JavaServer Faces application via the faces-config.xml. JavaBeans used in your application can

be wired together by bean properties and can be provided scope: a single request, a whole session visit, for everyone in the

application, or none if you don't want it stored directly.

<faces-config>

<!-- from project setup --> <application> <view-handler> com.sun.facelets.FaceletViewHandler </view-handler> </application> <!-- our NumberBean we just created --> <managed-bean> <managed-bean-name>NumberBean</managed-bean-name> <managed-bean-class>tutorial.NumberBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>min</property-name> <value>1</value> </managed-property> <managed-property> <property-name>max</property-name> <value>10</value> </managed-property> </managed-bean>

</faces-config>

The <managed-bean> element above tells JSF to guarantee a tutorial.NumberBean is available under the attribute name

NumberBean in the user's session. In addition, we've allowed our NumberBean to be configured by setting the min and max values a

user can guess. It should be noted that JavaServer Faces will lazy load our NumberBean when it's first accessed by our application.

1.6. Creating Web Pages

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:

$DEPLOY_DIR

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

7 de 31 4/12/2010 22:20

Page 8: Facelets - JavaServer Faces

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

1.6.1. The Page Template - template.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" xmlns:ui="http://java.sun.com/jsf/facelets"><head><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;}--></style></head>

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

</html>

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:

Use of proper namespaces such as xmlns:ui="http://java.sun.com/jsf/facelet" to specify tag libraries loaded by

Facelets. In this example, we are declaring that Facelet's own UI library of tags will be prefixed with a ui. Namespace

definitions need to be specified before you use a tag from that library, otherwise Facelets will properly error when it compiles

your document.

1.

<ui:insert> is used to declare parts of the document that can be inserted or overwritten. If a document doesn't override the

insertion point with the specified name (title or body), then the default text from the original template is used.

2.

1.6.2. Configuring User Input - guess.xhtml

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" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"><body>

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? </ui:define>

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}"/> <br/> <h:commandButton type="submit" id="submit" action="success" value="Submit" /> <br/>

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

8 de 31 4/12/2010 22:20

Page 9: Facelets - JavaServer Faces

<h:message showSummary="true" showDetail="false" style="color: red; font-weight: bold;" id="errors1" for="userNo"/> </h:form> </ui:define>

This text will not be displayed. </ui:composition>

This text below will also not be displayed.

</body></html>

Using a <ui:composition> tag will trim everything outside of it. This means that you can create/edit your documents with a

visual editor, but Facelets will only use what's between the <ui:composition> tags.

1.

The <ui:composition> uses the template attribute to reference the template or look and feel of this page.2.

Two <ui:define> tags are specified with names that match the ones used in the template we had created. This means that

when Facelets builds your page, those blocks of content will be placed appropriately in the template. Any text that happens to

reside inside the <ui:composition> tag, but outside of the <ui:define> tags is not displayed in the rendered output.

3.

Facelets also can use 'inlined' EL Expressions to make outputting dynamic content extremely easy. In the example above,

#{NumberBean.max} will display the max property of the NumberBean in your session. EL expressions may also reside outside

tag attributes, in the space between tags, but you must keep in mind that the result of evaluating the expression will only

appear in the rendered output if template text in that same position would appear.

4.

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.

1.6.3. Displaying the Response - response.xhtml

Finally, if a user entered valid input as specified by the NumberBean.validate method, then we need a page to give them feedback

on their guess.

<!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" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"><body>

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

<ui:define name="title"> #{NumberBean.message} </ui:define> <ui:define name="body"> <form jsfc="h:form"> <input jsfc="h:commandButton" type="submit" id="back" value="Back" action="success"/> </form> </ui:define> </ui:composition>

</body></html>

Again we use an <ui:composition> to trim unecessary content from our page and use the template.xhtml.1.

We also introduced the jsfc attribute which allows the XHTML tags to be compiled into <h:form> and <h:commandButton>

when the page is compiled. This means that a designer's visual editor will render a normal form and button, but it will be

transformed into a dynamic UIComponent when compiled by Facelets.

2.

That's it for the pages. Again, if you have questions about JavaServer Faces components or would like some additional background,

visit http://java.sun.com/j2ee/javaserverfaces

1.7. Handling Navigation

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

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

9 de 31 4/12/2010 22:20

Page 10: Facelets - JavaServer Faces

into the faces-config.xml to specify navigation cases.

<faces-config>

<!-- from project setup --> <application> <view-handler> com.sun.facelets.FaceletViewHandler </view-handler> </application> <!-- our NumberBean we created before --> <managed-bean> <managed-bean-name>NumberBean</managed-bean-name> <managed-bean-class>tutorial.NumberBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>min</property-name> <value>1</value> </managed-property> <managed-property> <property-name>max</property-name> <value>10</value> </managed-property> </managed-bean> <!-- going from guess.xhtml to response.xhtml --> <navigation-rule> <from-view-id>/guess.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/response.xhtml</to-view-id> </navigation-case> </navigation-rule>

<!-- going from response.xhtml to guess.xhtml --> <navigation-rule> <from-view-id>/response.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/guess.xhtml</to-view-id> </navigation-case> </navigation-rule>

</faces-config>

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.

1.8. Deployment

Finally, you should be able to deploy all of these artifacts now to your web application. Your application should generate a random

number and allow you to flip between your guess page and response page. To access your application, remember that the

javax.faces.web.FacesServlet in your web.xml was mapped to *.jsf. To start your guessing fun, point your browser to

http://localhost:8080/numberguess/guess.jsf (presuming you used the application name numberguess).

If you have additional problems or questions, going to Facelet's home page at http://facelets.dev.java.net will provide you with

additional resources such as forums, mailing lists, and additional documentation.

Chapter 2. Configuration

2.1. Configuring JavaServer Faces

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

<faces-config> <application> <view-handler>

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

10 de 31 4/12/2010 22:20

Page 11: Facelets - JavaServer Faces

com.sun.facelets.FaceletViewHandler </view-handler> </application> </faces-config>

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

“Initialization Parameters”.

2.1.1. JavaServer Faces RI

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

2.1.2. Apache MyFaces

Apache MyFaces has it's own version of the JavaServer Faces API included in its distribution. Currently, Apache MyFaces is only up to

the 1.1 specification, but has not yet passed the TCK.

http://myfaces.apache.org

2.2. Web Application Descriptors

2.2.1. Initialization Parameters

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

Table 2.1. Web.xml Parameter List

Parameter Name Default Value Description

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.DEVELOPMENT false

Setting 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 -1

The 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

8192

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

11 de 31 4/12/2010 22:20

Page 12: Facelets - JavaServer Faces

Parameter Name Default Value Description

partially rendered when an error is

generated.

facelets.REFRESH_PERIOD 2

When 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_RESOLVER com.sun.facelets.impl.DefaultResourceResolver

Optionally 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_COMMENTS true

A 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

2.2.2. Security

Java applications can restrict access to resources or pages by outside users. This feature is common to all application servers and

part of the Servlet specification.

Lets presume that you want to take advantage of developing simple Facelet XHTML documents that are viewable in your browser

during development. When your application is deployed to production, you don't want anyone from the outside to access your XHTML

documents unless they are served through the JavaServer Faces Servlet.

<web-app>

<!-- servlets and such would be above -->

<security-constraint> <display-name>Restrict XHTML Documents</display-name> <web-resource-collection> <web-resource-name>XHTML</web-resource-name> <url-pattern>*.xhtml</url-pattern> </web-resource-collection> <auth-constraint> <description>Only Let 'developer's access XHTML pages</description> <role-name>developer</role-name> </auth-constraint> </security-constraint>

</web-app>

You can read more about Security in the Web Tier at http://java.sun.com/webservices/docs/1.3/tutorial/doc/Security2.html

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

12 de 31 4/12/2010 22:20

Page 13: Facelets - JavaServer Faces

2.3. Logging

Facelets uses java.util.Logger for handling logging. This was done to reduce library dependencies while taking advantage of many

Servlet container's ability to modify logging levels on the fly.

For many, using the JDK 1.4 java.util.Logger will be new to them. You can read more on it at http://java.sun.com/j2se/1.4.2

/docs/guide/util/logging/index.html

Table 2.2. Facelet Logger Names

Name Description

facelets.compilerFor outputting debug information about the compilation process. This would include namespace

resolution for TagLibraries and XML events. Most of the output will be FINE.

facelets.factory Information about the inner workings of the FaceletFactory.

facelets.tag.component Debug information that helps with component lifecycles in relation to Facelets.

facelets.viewhandler Will output view-id mapping/resolution and the states of your views.

For those who are currently developing a Facelets project and would like to have all the debug information available on both your

application server and in your IDE; modify the logging.properties in your JRE/lib directory and add the following lines to the end

of that file:

facelets.level = FINEST

# uncomment any of the below

#facelets.compiler.level = SEVERE#facelets.tag.component.level = INFO#facelets.viewhandler.level = SEVERE

Chapter 3. Tag Libraries

3.1. Using Tags

3.1.1. Tag Namespaces

Facelets uses valid XML with namespace support for compilation. If you are new to XML, there are great resources online, such as

http://www.w3schools.com. To use a library of tags, you would 'include' the library by declaring a namespace. Declaring a

namespace involves using the library's URI (or URL) and mapping it to a prefix.

<!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" xmlns:h="http://java.sun.com/jsf/html"> <body> <h:inputText value="#{hello.world}"/></body>

</html>

In the example above, we've declared 2 namespaces:

xmlns="http://www.w3.org/1999/xhtml" Says every tag without a prefix, such as <body>, are part of XHTML.

xmlns:h="http://java.sun.com/jsf/html" Maps the prefix h: to the JSF HTML library.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

13 de 31 4/12/2010 22:20

Page 14: Facelets - JavaServer Faces

3.1.2. Using 'jsfc'

Facelets provides you the ability to have one XML element in the page be converted to another at compile time by specifying the

jsfc attribute.

<!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" xmlns:h="http://java.sun.com/jsf/html"> <body> <input type="text" jsfc="h:inputText" value="#{hello.world}" /></body>

</html>

The <input> tag above is readable/displayable in browsers and visual tools as a normal text field. It would be nice to use that same

text field in JavaServer Faces, so we provide the jsfc="h:inputText". This declaration tells the compiler to resolve the <input>

tag as an <h:inputText> (the same as above). Note, the same rules for namespaces and naming apply to the value of the jsfc

attribute.

3.1.3. Unresolved Namespaces

If there is a tag in your document under a namespace (such as XHTML) that isn't specified in a Tag Library, then Facelets will treat

that tag as a simple text fragment and optimize it for tree creation. If the namespace is known, but the element's name isn't included

in the tag library, then an exception will be thrown which will tell you what file and line caused the problem.

If your tag or component isn't showing up in your rendered page, check the source of page and see if the tag was simply ignored. This

usually means you are using the wrong namespace for your library.

3.2. Available Tag Libraries

3.2.1. JavaServer Faces Specification

Facelets comes with support for all tags (components) included in the JavaServer Faces Specification. Great care was taken to mimic

the specification's JSP tag counterparts to leverage existing knowledge and available documentation. For development, you may

reference the 'Tag Library Documentation' at:

http://java.sun.com/j2ee/javaserverfaces/reference/api/index.html

Table 3.1. Specification Tag Libraries

Namespace Description

http://java.sun.com

/jsf/coreThe core JavaServer Faces custom actions that are independent of any RenderKit used.

http://java.sun.com

/jsf/html

This tag library contains JavaServer Faces component tags for all UIComponent + HTML RenderKit

Renderer combinations defined in the JavaServer Faces Specification.

3.2.2. Templating Library

You can read all about the cool templating features in Facelets in Chapter 5, Templating and Re-Use.

3.2.3. JSTL Support

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

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

14 de 31 4/12/2010 22:20

Page 15: Facelets - JavaServer Faces

documentation from JSTL:

http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/index.html

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

Table 3.2. <c:if/>

Attribute Required? Description Example

var false An optional expression variable to store the result of evaluating the 'test' attribute. result

test trueA required expression that evaluates to a boolean for deciding if the body of this tag is

included in tree creation. Note, an expression evaluating to null is also false.#{user.roles['admin']}

Table 3.3. <c:forEach/>

Attribute Required? Description Example

var false An optional expression variable to store the actual currently indexed value. employee

items false An expression that evaluates to an indexable Collection, Array, or Map. #{empDao.employees}

varStatus false

Variable to bind an Object that describes the current indexed state. The Object

has the following properties: first[boolean], last[boolean], begin[int], end[int],

index[int], step[int].

idx

begin false Index the forEach should start at. #{param.offset}

end false Index the forEach should end at#{param.offset +

param.pageSize}

step false The step size to skip entries in the collection 2

Table 3.4. <c:catch/>

Attribute Required? Description Example

var false An optional value to store the Exception Object exp

Table 3.5. <c:set/> (Avoid if Possible)

Attribute Required? Description Example

var true A variable to store the 'value' expression aList

value true

An expression that will be bound under the specified 'var' attribute. Anytime this 'var'

shows up in other expression, this 'value' will be embeded in the succeeding expression.

The example here would bind 'aList' as "the list within the map under the key 'listA'", NOT

as a List Object. Every time 'aList' is used, it will evaluate the example expression to

generate the instance.

#{listMap['listA']}

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.

3.2.4. Oracle ADF Faces

Oracle ADF Faces is unofficially supported by Facelets. This work is being done by independent contributions and is available from

the Facelet's home page under documents and files.

3.3. Functions

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

15 de 31 4/12/2010 22:20

Page 16: Facelets - JavaServer Faces

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.

3.4. Loading Libraries

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.

When Facelets searches the classpath, it will attempt to load any file with the extension *.taglib.xml from the /meta-inf

folder of your Jars. For example, /meta-inf/mycompany.taglib.xml would be found by Facelets while

/mycompany.taglib.xml and /meta-inf/mycompany.xml would not. See Section 2.3, “Logging” for information on recieving

debug information on the libraries loaded.

Facelets will check for an initialization parameter from your web.xml and load all libraries specified there relative to your

application's root. See Section 2.2.1, “Initialization Parameters” for details on the parameter. This is an ideal way to declare

specialized tags for a particular application; tags that aren't necessarily distributed with code in Jars.

3.5. Creating Tag Libraries

Overview

Facelets allows you to configure custom tag libraries in a short amount of time. This section will focus on defining tag libraries in XML

which can be automatically loaded by Facelets compiler as described in Section 3.4, “Loading Libraries”.

3.5.1. Tag Library Schema

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" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

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)>

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

16 de 31 4/12/2010 22:20

Page 17: Facelets - JavaServer Faces

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 definition of a tag library (including namespace) can be delegated to the class specified in the library-class element.

The class specified must implement com.sun.facelets.tag.TagLibrary. This is useful if you would like to maintain your tag

library in Java, but would like to have it automatically picked up by the compiler by placing an XML file in your Jar's meta-inf

folder.

Each document (not specified by library-class) requires a namespace element which will match the namespace used in your

document, see Section 3.1.1, “Tag Namespaces”.

The rest of the document is made up of tag and function elements. Tag elements require a tag-name and can take on

different behavior depending on what you would like Facelets to handle for you. Functions can also be specified under the

library's namespaces and follow the same signature as in JSP TLD files.

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

3.5.2. UIComponents

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

<tag> <tag-name>bar</tag-name> <component> <component-type>com.mycompany.Data</component-type> <renderer-type>com.mycompany.Bar</renderer-type> </component></tag>

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:

<faces-config> <component> <component-type>com.mycompany.Data</component-type> <component-class>com.mycompany.jsf.components.UIDataComponent</component-class> </component></faces-config>

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.

3.5.3. Validators

Validators can also be added to Facelets with the validator element.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

17 de 31 4/12/2010 22:20

Page 18: Facelets - JavaServer Faces

<tag> <tag-name>validateEmail</tag-name> <validator> <validator-id>faces.validator.Email</validator-id> </validator></tag>

Again, we reference JSF entities by type or id. Facelets will also take care of wiring attributes directly to your Validator by

matching attribute name to property name. If you would like to provide special behavior or wire odd properties, you can jump ahead

to Section 7.3.2, “Custom ValidateHandlers”.

If you've just written your own Validator, you can add it to your JSF Application with the following snippet in your faces-

config.xml:

<faces-config> <validator> <validator-id>faces.validator.Email</validator-id> <handler-class>com.mycompany.jsf.validate.EmailValidator</handler-class> </validator></faces-config>

3.5.4. Converters

Converters can be registered with Facelets by adding a converter element.

<tag> <tag-name>convertMoney</tag-name> <converter> <converter-id>faces.convert.Money</converter-id> </converter></tag>

Converters are referenced by id. Facelets will take care of wiring attributes directly to your Converter by matching attribute name

to property name. If you would like to provide special behavior or wire odd properties, you can jump ahead to Section 7.3.3, “Custom

ConvertHandlers”.

If you've just written your own Converter, you can add it to your JSF Application with the following snippet in your faces-

config.xml:

<faces-config> <converter> <converter-id>faces.convert.Money</converter-id> <handler-class>com.mycompany.jsf.convert.ConvertMoney</handler-class> </converter></faces-config>

3.5.5. Tag (Source) Files

Facelets has a feature similar to JSP's Tag Files. Within your tag library definition, you can provide a source element that points to a

another file, that will be compiled into another Facelet. Since this file can be referenced by tag-name, you can easily include that

Facelets into another and pass variable data to it.

<tag> <tag-name>echo</tag-name> <source>tags/echo.xhtml</source></tag>

The echo.xhtml will be included anytime a developer uses the echo tag. The following is an example tag file:

<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"> <span class="message">#{msg}</span></ui:composition>

This tag file can be included and any variable used within the tag file can be passed as an attribute:

<my:echo msg="#{bean.warningMessage}"/>

In this example, the msg attribute is assigned to #{bean.warningMessage} and then referenceable within echo.xhtml under the

variable msg.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

18 de 31 4/12/2010 22:20

Page 19: Facelets - JavaServer Faces

This was a simple example, but you can do some fairly cool things with building reusable components in your pages. Going one step

further, you may provide a body to your custom tag, by placing a <ui:insert/> as a place for body inclusion. See Chapter 5,

Templating and Re-Use for more information.

3.5.6. Custom Tags

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.

<tag> <tag-name>if</tag-name> <handler-class>com.mycompany.IfHandler</handler-class></tag>

All tags in a Facelets extend com.sun.facelets.tag.TagHandler which provides some base functionality for tying XML data to your

Java code. To read more about creating custom tags, jump to Section 7.2, “Custom TagHandlers”.

3.5.7. Function Specification

You may reference functions within your tag library. Functions are represented by static methods in Java.

<function> <function-name>reverse</function-name> <function-class>com.mycompany.Functions</function-class> <function-signature>java.lang.String reverse(java.lang.String)</function-signature></function>

The function element is a top level entity like the tag element. You need to specify both the class type and the method signature

that Facelets should use. All class names in the signature must be fully qualified, with the exception of primitives such as int or

boolean.

In this example, you would be able to reference this function with a namespace prefix in your document, such as

#{my:reverse{employee.name}}. See Section 3.3, “Functions” for more information on function use in your pages.

Chapter 4. Expression Language

Facelets utilizes the new EL Specification and will continue to support it in future revisions. This may include extra language

extensions such as method invocation and inlined sets, for example.

With the new EL Specification, the use of #{...} and ${...} are both supported and Facelets makes no distinction between the two.

The short of it is that you can freely interchange the two with whatever is most familiar to what you're working on. Both syntaxes

will be handled the same way and share the same lifecycles and features.

4.1. Inlining Text

Text and expressions can exist anywhere in the document. This means you can have an example like below, and have Facelets

correctly evaluate it at render time.

<span>Your Basket has ${basket.lineCount} Items</span>

4.2. EL Lifecycle

Facelets provides a unique lifecycle to EL. When building a UIComponent tree, all EL expressions are re-built based on the state of

the current FaceletContext. These expressions are either stored on things like UIComponents or stored in the component tree as

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

19 de 31 4/12/2010 22:20

Page 20: Facelets - JavaServer Faces

text. When it's time to render, then these expressions are evaluated as the second phase. This offers the truest form of

variable/state management in relation to tree building within JavaServer Faces. This is also a feature that is not supported within

JSP for inlined text.

Chapter 5. Templating and Re-Use

Overview

When I set out to design the Facelets framework, my main emphasis was ease of integration with JavaServer Faces. A ways into the

the notebook of ideas, I saw that templating and re-use would have to be just as important within your documents, if not more

important than the JSF integration features. Thusly, the Facelet compiler makes special accomodations to the built-in UI tag library

for high-perforance templating in your pages. This section acts as both an introduction and a whiteboard for ideas you may pursue

with Facelets and JavaServer Faces.

5.1. Template/Client Relationships

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.

5.1.1. Wrapping Content within a Template

A template client can refrain from using <ui:define> tags in their body; then the target template only uses a single <ui:insert/>

(without the name attribute). This will cause the body of the template client to be injected into the template wherever the 'nameless'

<ui:insert/> is located.

<!-- template document -->...<span class="repeatingBox"> <c:forEach begin="1" end="10"> <ui:insert/><br/> </c:forEach></span>...

<!-- template client document -->...<ui:composition template="template.xhtml"> I'm in the spin cycle <h:outputText value="#{random.name}"/>!</ui:composition>...

5.1.2. Piecemeal Content within a Template

A template client can break up its body within multiple, named <ui:define> tags. These tags may specify what goes in the menu, in

the header, and within the content area all at once. See Section 1.6, “Creating Web Pages” for a good example of this type of

templating.

5.1.3. Multi-Level Templating

Template use may go multiple levels deep. This means that a template client may use a template which in turn may use a template,

which may also use a template, and then it may use yet another template... you get the picture.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

20 de 31 4/12/2010 22:20

Page 21: Facelets - JavaServer Faces

Templating is backed by the a TemplateManager that has a stack of TemplateClient instances. Tags like <ui:composition>

implement TemplateClient. When a template is being evaluated and comes upon a <ui:insert/> tag, it will ask the

TemplateManager for a TemplateClient that either has a match for the tag's name attribute, or the top-most TemplateClient on

the stack.

An example would be having a <ui:insert name="title"/> tag in the template. The TemplateManager will walk through its

internal stack of TemplateClients, asking each one for a content under the name title. It will continue through the stack until one

is found. If none are found, then the original template is free to include the default content. See Section 5.9, “<ui:insert/>” for more

information on default content.

5.2. <ui:component/>

Table 5.1. Component Tag Attributes

Attribute Required? Description Example

id falseA unique id may be provided, otherwise Facelets will automatically assign one under the

same logic it uses for all UIComponents.mainMenu

binding false

This binding attribute is used the same as with any other UIComponent such that it allows you

to reference them as a property of a JavaBean. If that target property did not have a

UIComponent instance assigned already, JavaServer Faces will lazily create an instance for

you and set it on your JavaBean before continuing with building the tree.

#{page.menu}

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:choose> <c:when test="#{link.id == page}">

<li class="current"><a href="#{link.uri}">#{link.text}</a></li> </c:when> <c:otherwise>

<li><a href="#{link.uri}">#{link.text}</a></li> </c:otherwise></c:choose>

</c:forEach> </ul></ui:component>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}"/></span>...

Pretty cool eh?

5.3. <ui:composition/>

Table 5.2. Composition Tag Attributes

Attribute Required? Description Example

template falseThe resolvable URI of the template to use. The content within the

composition tag will be used in populating the template specified.

/WEB-INF/templates/detal-

template.xhtml

Facelets is founded on the idea of compositions. This means that a UIComponent tree can be defined in multiple Facelet pages and

executed in part or whole. Some other frameworks, like Tapestry (http://jakarta.apache.org/tapestry), may define a single

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

21 de 31 4/12/2010 22:20

Page 22: Facelets - JavaServer Faces

component within a page, Facelets instead marks the start of a branch of child UIComponents-- a composition if you will.

Text before will be removed.<ui:composition> #{dynamic.text} <h:inputText id="myText" value="#{foo.bar}"/></ui:composition>Text after will be removed.

This means you can start a full XHTML document in your favorite visual tool with CSS definitions, but have Facelets trim everything

outside of the <ui:composition/> tag. Here's a simple example of using a composition in separate document:

...<h:column> <ui:include src="/composition.xhtml"/></h:column>...

Lets say this composition was included inside of a <h:column/> tag/component; it would gain two children based on the above

example: #{dynamic.text} and the <h:inputText/>.

The composition tag has templating abilities, to read more about how templating is coordinated, jump over to Section 5.6,

“<ui:define/>” and Section 5.9, “<ui:insert/>”.

5.4. <ui:debug/>

Table 5.3. Debug Tag Attributes

Attribute Required? Description Example

hotkey false

The hot key to use in combination with 'CTRL' + 'SHIFT' to launch the debug window. By default,

when the debug tag is used, you may launch the debug window with 'CTRL' + 'SHIFT' + 'D'. This value

cannot be an EL expression.

d

The debug tag will capture the component tree and variables when it is encoded, storing the data for retrieval later. You may launch

the debug window at any time from your browser by pressing 'CTRL' + 'SHIFT' + 'D' (by default).

... <ui:debug hotkey="d" rendered="#{initParam.debugMode}"/> </body></html>...

In the above example, we use the hot key 'd' to launch the debug window. Creating debug output on every request adds some

overhead, so you can use the UIComponent rendered property to turn debugging on or off based on some expression. In this example,

debugging is backed by an entry in the web.xml.

The debug tag doesn't need to be used with the facelet.DEVELOPMENT parameter. The best place to put this tag is in your site's main

template where it can be enabled/disabled across your whole application. If your application uses multiple windows, you might want

to assign different hot keys to each one.

5.5. <ui:decorate/>

Table 5.4. Decorate Tag Attributes

Attribute Required? Description Example

template trueThe resolvable URI of the template to use. The content within the decorate

tag will be used in populating the template specified.

/WEB-INF/templates

/sideBox.xhtml

The decorate tag acts the same as a composition tag, but it will not trim everything outside of it. This is useful in cases where you

have a list of items in a document, which you would like to be decorated or framed. The sum of it all is that you can take any

element in the document and decorate it with some external logic as provided by the template.

Text before will stay.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

22 de 31 4/12/2010 22:20

Page 23: Facelets - JavaServer Faces

<ui:decorate template="/WEB-INF/templates/sideBox.xhtml"> <ui:define name="title">Product Search</ui:define> <ui:define name="body"> ... </ui:define></ui:decorate>Text after will stay.

In some cases, it would make sense to externalize your "Product Search" box into a separate file, in other cases it doesn't and the

decorate tag allows you to inline as such.

For more information on how templating works in relation to the <ui:define/> tags, see Section 5.6, “<ui:define/>”.

5.6. <ui:define/>

Table 5.5. Define Tag Attributes

Attribute Required? Description Example

name trueThe literal name for this definition. This name will match up with a <ui:insert/> tag in a target

template.header

The define tag can be used within tags that allow templating. This includes composition and decorate tags.

Text before will stay.<ui:decorate template="/WEB-INF/templates/sideBox.xhtml"> <ui:define name="title">Product Search</ui:define> <ui:define name="body"> ... </ui:define></ui:decorate>Text after will stay.

The use of this tag will be familiar to those that have used Struts Tiles, for example. The define tag is used in conjuction with the

target template's insert tag, which you can read more about in Section 5.9, “<ui:insert/>”.

5.7. <ui:fragment/>

Table 5.6. Fragment Tag Attributes

Attribute Required? Description Example

id falseA unique id may be provided, otherwise Facelets will automatically assign one

under the same logic it uses for all UIComponents.mainMenu

binding false

This binding attribute is used the same as with any other UIComponent such that

it allows you to reference them as a property of a JavaBean. If that target

property did not have a UIComponent instance assigned already, JavaServer

Faces will lazily create an instance for you and set it on your JavaBean before

continuing with building the tree.

#{uiCache['searchResults']}

Just like composition has decorate as a non-trimming version of the same behavior, component has fragment. This allows you to

logically insert a UIComponent into the tree and possibly bind this fragment to a JavaBean property or Map for management.

The Text above will be used.<ui:fragment binding="#{uiCache['searchResult']}"> <div id="searchResults">

... </div></ui:fragment>The Text below will be used.

The fragment tag was also added to Facelets to get around some of the optimizations used in handling text within your document. If

you are using components such as <f:panelGrid/>, which renders its children, you may want more control over the building process

that Facelets does and using a fragment tag will help guarantee parent/child relationships for you.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

23 de 31 4/12/2010 22:20

Page 24: Facelets - JavaServer Faces

5.8. <ui:include/>

Table 5.7. Include Tag Attributes

Attribute Required? Description Example

src trueA literal or EL expression that specifies the target Facelet that you would like to include

into your document.anotherPage.xhtml

This tag should be familiar to most. The include tag can point at any Facelet which might use the composition tag, component tag,

or simply be straight XHTML/XML.

It should be noted that the src path does allow relative path names, but they will always be resolved against the original Facelet

requested.

<span id="header"> <ui:include src="#{backingBean.headerSource}"/></span>

The include tag can be used in conjunction with multiple <ui:param/> tags to pass EL expressions/values to the target page. See

Section 5.10, “<ui:param/>”, for more on passing variables to other pages.

5.9. <ui:insert/>

Table 5.8. Insert Tag Attributes

Attribute Required? Description Example

name falseThe optional name attribute matches the associated <ui:define/> tag in this template's client. If

no name is specified, it's expected that the whole template client will be inserted.header

The insert tag is used within your templates to declare spots of replaceable data.

<!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" xmlns:ui="http://java.sun.com/jsf/facelets"><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title><ui:insert name="title">Default Title</ui:insert></title></head><body><h1>Here is the Page Header</h1><ui:insert name="body"> Default Body</ui:insert></body></html>

As you can see, these insert tags indicate to the Facelets compiler where to insert content from the template client. If the

template client doesn't specify content for the specified name, then the body of the ui:insert tag in the template is used.

5.10. <ui:param/>

Table 5.9. Param Tag Attributes

Attribute Required? Description Example

name true The name of the variable to pass to the included Facelet. user

value true The literal or EL expression value to assign to the named variable. #{sessionScope.user}

From reading about Facelets templating, you've probably become familiar with passing fragments of content between pages. With

the param tag, you can pass objects as variables instead of just fragments of content. You can use the param tag wherever a define

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

24 de 31 4/12/2010 22:20

Page 25: Facelets - JavaServer Faces

tag is used within composition or decorate tags, in addition to passing objects to an include tag.

<span id="leftNav"> <ui:include src="/WEB-INF/siteNav.xhtml"> <ui:param name="user" value="#{currentUser}"/> <ui:param name="page" value="home"/> </ui:include></span>

In the above example, when siteNav.xhtml is used, it will have user and page variables available for use which will reference the

the currentUser object and the home string literal.

5.11. <ui:remove/>

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'”.

...<ui:remove> This will be removed.</ui:remove>...<span jsfc="ui:remove">

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

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.

5.12. <ui:repeat/>

Table 5.10. Repeat Tag Attributes

Attribute Required? Description Example

value true Expression for the List of items to iterate over #{blog.currentEntries}

var true The literal name of the variable to use while iterating entry

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'”.

...<dl> <ui:repeat value="#{company.departments}" var="dept"> <dt>#{dept.name}</dt>

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

</ui:repeat></dl>...

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.

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

Chapter 6. Facelets Architecture

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

25 de 31 4/12/2010 22:20

Page 26: Facelets - JavaServer Faces

6.1. View Creation

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.

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

for this new view.

1.

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.

2.

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

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.

4.

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.

5.

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.

6.

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.

7.

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

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

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.

6.2. Facelets API

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.

6.2.1. FaceletFactory

The FaceletFactory is an interface to the Facelet compiler while offering features such as caching and modification monitoring.

FaceletFactory factory = FaceletFactory.getInstance();Facelet facelet = factory.getFacelet("/example.xml");

6.2.2. Facelet

The Facelet class is similar to a lot of the Servlet API, such that it's stateless and can handle multiple threads accessing it at once.

The Facelet's soul responsibility is to populate a tree of UIComponents for manipulation and, of course, rendering. A single instance is

representative of physical XML resource, compiled into memory once and shared for all requests.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

26 de 31 4/12/2010 22:20

Page 27: Facelets - JavaServer Faces

FacesContext faces = FacesContext.getCurrentInstance();Facelet facelet = factory.getFacelet("/example.xml");facelet.apply(faces, faces.getViewRoot());

After 'applying' this Facelet to the UIViewRoot, it will be fully populated according to your various XHTML or XML pages used with

the Facelets framework.

Facelets delegate tree creation logic to an internal tree of FaceletHandlers constructed by the compiler. The action of passing

UIComponents through the tree of FaceletHandlers causes the view to be populated in a UIComponent tree, reflective of the logic

included in the FaceletHandlers.

6.2.3. FaceletHandler

The FaceletHandler is a part of a parent Facelet in a many to one association. FaceletHandlers work off of the visitor pattern

where state is passed to them for modification and tree creation, then possibly passed along to the next FaceletHandler in the

chain.

public class LoggingHandler implements FaceletHandler public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException { Logger.getLogger("example").info("Hello Logger"); }}

That example, while silly, shows the simple API that the FaceletHandler uses. If you would like to construct your own

FaceletHandlers for use in UIComponent tree creation, jump over to Section 7.2, “Custom TagHandlers”.

6.3. Document Compiler

It's a secret.

Chapter 7. Extending Facelets

7.1. Tag Development Overview

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.

7.2. Custom TagHandlers

Facelets are composed of many different kinds of TagHandler instances. Just like a Facelet, all of the TagHandlers are stateless for

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

27 de 31 4/12/2010 22:20

Page 28: Facelets - JavaServer Faces

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.

<tag> <tag-name>if</tag-name> <handler-class>com.mycompany.IfHandler</handler-class></tag>

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) { super(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) { super(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:

Table 7.1. TagHandler Member Variables

Variable

NameClass Type Description

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

28 de 31 4/12/2010 22:20

Page 29: Facelets - JavaServer Faces

Variable

NameClass Type Description

tagId java.lang.String

A unique id, assigned at compilation time for this stateless element. This can be

used in combination with the FaceletContext.generateUniqueId(String) to

generate consistently unique ids for a given page evaluation.

tag com.sun.facelets.tag.Tag

A Tag instance which is Facelet's representation of the element declared in a

page. The Tag includes namespace/name information, along with accessors to

the TagAttributes specified on the element declared in the page.

nextHandler com.sun.facelets.FaceletHandler

A generic interface representing zero or more child tags and their associated

handlers. Since Facelets uses stateless TagHandlers, the parent handler can

evaluate the nextHandler any number of times or not at all to dictate

component tree creation.

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

7.3. Meta Tags

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”.

7.3.1. Custom ComponentHandlers

Component wiring can be customized by extending the com.sun.facelets.tag.jsf.ComponentHandler class.

public class HtmlComponentHandler extends ComponentHandler {

/** * @param config */ public HtmlComponentHandler(ComponentConfig config) { super(config); }

protected MetaRuleset createMetaRuleset(Class type) { return super.createMetaRuleset(type).alias("class", "styleClass"); }

}

In this example, we override the createMetaRuleset(Class) to alias wiring class attributes to the styleClass JavaBean property.

To add your custom component to your tag library, do the following:

...<tag> <tag-name>custom</tag-name> <component> <component-type>com.company.Component</component-type> <renderer-type>com.company.OptionalRenderer</renderer-type> <handler-class>com.company.HtmlComponentHandler</handler-class> </component></tag>...

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

29 de 31 4/12/2010 22:20

Page 30: Facelets - JavaServer Faces

7.3.2. Custom ValidateHandlers

In the previous example, Facelets will automatically wire UIComponent JavaBean properties and expressions to a given instance. The

bonus is that MetaTagHandler will set attributes on any instance of Object. This opens the doors for working with things like

Validators by extending com.sun.facelets.tag.jsf.ValidateHandler:

public final class ValidateDelegateHandler extends ValidateHandler {

private final TagAttribute validatorId;

public ValidateDelegateHandler(TagConfig config) { super(config); this.validatorId = this.getRequiredAttribute("validatorId"); }

/** * Uses the specified "validatorId" to get a new Validator instance from the * Application. * * @see javax.faces.application.Application#createValidator(java.lang.String) * @see com.sun.facelets.tag.jsf.ValidateHandler#createValidator(com.sun.facelets.FaceletContext) */ protected Validator createValidator(FaceletContext ctx) { return ctx.getFacesContext().getApplication().createValidator( this.validatorId.getValue(ctx)); }

protected MetaRuleset createMetaRuleset(Class type) { return super.createMetaRuleset(type).ignoreAll(); }}

In the above example, we've decided to do all of the attribute mapping ourselves, so we tell the MetaRuleset to ignoreAll().

7.3.3. Custom ConvertHandlers

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) { super(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.

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

30 de 31 4/12/2010 22:20

Page 31: Facelets - JavaServer Faces

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.

7.4. FaceletViewHandler

Facelets comes with a ViewHandler that you may extend. Some extension points include initializing the compiler and setting up

alternate response writers for JavaServer Faces to use.

To learn more, look at the Facelets JavaDocs for the com.sun.facelets.FaceletViewHandler.

7.5. Tag Decorators

The compiler within Facelets allows you to specify multiple TagDecorator instances. These implementations can do things like

transforming all HTML elements to their JSF equivalents automatically.

To add your custom TagDecorator to your Facelets project, you may extend the FaceletViewHandler and override the compiler

initialization methods to add your TagDecorator to the passed Compiler instance.

Chapter 8. Building Facelets

8.1. Using Ant

Facelets uses new features in 1.6.5, such as macros.

Table 8.1. Ant Targets

Name Description

compile Just compiles the Facelets code base, requires JSF 1.2 API

javadoc Generates JavaDocs for the API

doc Generates this developer documentation

jar Compiles, then Jars

dist Does the jar'ing and prepares/populates the dist directory

clean Cleans or resets the project

8.2. IDE Integration

Table 8.2. Available IDEs

Name Vendor Link

Exadel Studio Exadel http://www.exadel.com/products_products1.htm

Facelets - JavaServer Faces View Definition Framework https://facelets.dev.java.net/nonav/docs/dev/docbook.html

31 de 31 4/12/2010 22:20