Facelets Components in JSF 1.2

November 2009

One of the more advanced features of the Facelets framework is the ability to define complex templates containing dynamic nested content.

What is a template?The Merriam-Webster dictionary defines the word "template" as "a gauge, pattern, or mold (as a thin plate or board) used as a guide to the form of a piece being made" and as "something that establishes or serves as a pattern." In the context of user interface design for the Web, a template can be thought of as an abstraction of a set of pages in the web application.A template does not define content, but rather it defines placeholders for content, and provides the layout, orientation, flow, structure, and logical organization of the elements on the page. We can also think of templates as documents with "blanks" that will be filled in with real data and user interface controls at request time. One of the benefits of templating is the separation of content from presentation, making the maintenance of the views in our web application much easier.

The <ui:insert> tag has a name attribute that is used to specify a dynamic content region that will be inserted by the template client. When Facelets renders a UI composition template, it attempts to substitute any <ui:insert> tags in the Facelets template document with corresponding <ui:define> tags from the Facelets template client document. Conceptually, the Facelets composition template transformation process can be visualized as follows:

In this scenario, the browser requests a Facelets template client document in our JSF application. This document contains two <ui:define> tags that specify named content elements and references a Facelets template document using the <ui:composition> tag's template attribute. The Facelets template document contains two <ui:insert> tags that have the same names as the <ui:define> tags in the client document, and three <ui:include> tags for the header, footer, and navigation menu.

This is a good example of the excellent support that Facelets provides for the Composite View design pattern. Facelets transforms the template client document by merging any content it defines using <ui:define> tags with the content insertion points specified in the Facelets template document using the <ui:insert> tag. The result of merging the Facelets template client document with the Facelets template document is rendered in the browser as a composite view.

While this concept may seem a bit complicated at first, it is actually a powerful feature of the Facelets view defi nition framework that can greatly simplify user interface templating in a web application. In fact, the Facelets composition template document can itself be a template client by referencing another composition template. In this way, a complex hierarchy of templates can be used to construct a flexible, multi-layered presentation tier for a JSF application.

Without the Facelets templating system, we would have to copy and paste view elements such as headers, footers, and menus from one page to the next to achieve a consistent look and feel across our web application. Facelets templating enables us to define our look and feel in one document and to reuse it across multiple pages. Therefore, if we decide to change the look and feel, we only have to update one document and the change is immediately propagated to all the views of the JSF application.

Let's look at some examples of how to use the Facelets templating feature.

A simple Facelets template

The following is an example of a simple Facelets template. It simply renders a message within an HTML <h2> element. Facelets will replace the "unnamed" <ui:insert> tag (without the name attribute) in the template document with the content of the <ui:composition> tag from the template client document.

A simple Facelets template client

Let's look at a simple example of Facelets templating. The following page is a Facelets template client document. (Remember: you can identify a Facelets template client by looking for the existence of the template attribute on the <ui:composition> tag.) The <ui:composition> tag simply contains the text Hello World.

The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01a.jsf:

A more complex Facelets template

The Facelets template in the previous example is quite simple and does not demonstrate some of the more advanced capabilities of Facelets templating. In particular, the template in the previous example only has a single <ui:insert> tag, with no name attribute specified. The behavior of the unnamed <ui:insert> tag is to include any content in the referencing template client page.

In more complex templates, multiple <ui:insert> tags can be used to enable template client documents to defi ne several custom content elements that will be inserted throughout the template. The following Facelets template document declares three named <ui:insert> elements. Notice carefully where these tags are located.

In the following example, the template client document defines three content elements named title, header, and content using the <ui:define> tag. Their position in the client document is not important because the template document determines where this content will be positioned.

The next screenshot displays the result of the Facelets UI composition transformation when the browser requests templateClient02a.jsf. We can follow this pattern to make a number of JSF pages reuse the template in this manner to achieve a consistent look and feel across our web application.

Decorating the user interface

The Facelets framework supports the definition of smaller, reusable view elements that can be combined at runtime using the Facelets UI tag library. Some of these tags, such as the <ui:composition> and <ui:component> tags, trim their surrounding content. This behavior is desirable when including content from one complete XHTML document within another complete XHTML document.

There are cases, however, when we do not want Facelets to trim the content outside the Facelets tag, such as when we are decorating content on one page with additional JSF or HTML markup defi ned in another page.

For example, suppose there is a section of content in our XHTML document that we want to wrap or "decorate" with an HTML <div> element defined in another Facelets page. In this scenario, we want all the content on the page to be displayed, and we are simply surrounding part of the content with additional markup defined in another Facelets template. Facelets provides the <ui:decoration> tag for this purpose.

Decorating content on a Facelets page

The following example demonstrates how to decorate content on a Facelets page with markup from another Facelets page using the <ui:decoration> tag. The <ui:decoration> tag has a template attribute and behaves like the <ui:composition> tag. Facelets templating typically uses the <ui:composition>. It references a Facelets template document that contains markup to be included in the current document. The main difference between the <ui:composition> tag and the <ui:decoration> tag is that Facelets trims the content outside the <ui:composition> tag but does not trim the content outside the <ui:decoration> tag.

<!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=utf-8" /><title>ui:decorate example</title><link rel="stylesheet" type="text/css" href="css/style.css" /></head><body>Text before will stay.<ui:decorate template="/WEB-INF/templates/box.jsf"><span class="header">Information Box</span><p>This is the first line of information.</p><p>This is the second line of information.</p><p>This is the third line of information.</p></ui:decorate>Text after will stay.<ui:debug /></body></html>

Creating a Facelets decoration

Let's examine the Facelets decoration template referenced by the previous example. The following source code demonstrates how to create a Facelets template to provide the decoration that will surround the content on another page.

As we are using a <ui:composition> tag, only the content inside this tag will be used. In this example, we declare an HTML <div> element with the "box" CSS style class that contains a single Facelets <ui:insert> tag. When Facelets renders the above Facelets page, it encounters the <ui:decorate> tag that references the box.jsf page. The <ui:decorate> tag will be merged together with the associated decoration template and then rendered in the view. In this scenario, Facelets will insert the child content of the <ui:decorate> tag into the Facelets decoration template where the <ui:insert> tag is declared.

The result is that our content is surrounded or "decorated" by the <div> element. Any text before or after the <ui:decoration> is still rendered on the page, as shown in the next screenshot:

The included decoration is rendered as is, and is not nested inside a UI component as demonstrated in the following Facelets debug page:

Rendering a UI fragment

Like the <ui:decorate> tag, the <ui:fragment> tag is also a non-trimming tag. Facelets preserves the markup outside this tag.

One difference between the <ui:decoratition> and the <ui:fragment> tags, however, is that Facelets includes the content of the <ui:fragment> tag inside a UI component. In this way, the <ui:fragment> and the <ui:component> tag have similar behavior.

Another difference between the <ui:decorate> and the <ui:fragment> tags is that the <ui:fragment> tag does not support the template attribute, but instead has a binding attribute that gives us the ability to bind the tag to a UI component in our backing bean.

<!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"xmlns:ui="http://java.sun.com/jsf/facelets"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>ui:fragment example</title></head><body><h:form>Text before will be rendered.<ui:fragment><p>A fragment adds a component to the view but does not trim anycontent.</p></ui:fragment>Text after will be rendered.<ui:debug /></h:form></body></html>

The non-trimming and UI component-based behavior of the <ui:fragment> tag is demonstrated in the Facelets debug page shown in the next screenshot.

As Facelets renders the content of the <ui:fragment> tag within a UI component, we can use this tag whenever we want to group multiple components (and markup) together as a single UI component, such as within the <h:panelGrid> and <f:facet> tags.

An advanced Facelets composition template

The following example demonstrates an advanced Facelets composition template and uses the majority of Facelets tags in a single composite view. In this example, the template client document specifies a number of named content elements using the <ui:define> tag and reuses multiple UI elements.

The <ui:define> tag named title specifies the document title. The links element uses a <ui:include> tag to include the navigation menu that will be inserted into the links section of the template. The header element simply defines the page header. The content element defines the paragraph text to be rendered by the template. Finally, the data element defines the data to be displayed by re-using the external links.jsf template that renders a parameterized list of customers.

The corresponding Facelets UI composition template for this example uses te <ui:include> tag to render a header defined in an external Facelets page. The main content of the page is rendered using the <h:panelGrid> tag to render a single-column layout table. (CSS-based layouts are generally preferred to table-based layouts; this example is for demonstration only.)

The first row of the panel grid renders the links element by using the <ui:insert> tag named links. Notice that the content is wrapped in a <ui:fragment> tag to ensure that any included content is wrapped with a single UI component so the content is rendered in a single column within the panel grid component.

The second row of the panel grid renders a title inside the HTML <h2> element. The third row of the panel grid renders a box decoration around the named data element provided by the template client. The page footer is rendered using a <ui:include> tag.

Finally, we declare the <ui:debug> tag and set the rendered attribute to true based on the value of the facelets.DEVELOPMENT initialization parameter. This way, debugging support can be enabled conditionally whenever Facelets error handling is turned on during the development cycle.

The result of the Facelets UI composition transformation is a complex composite view arrangement containing multiple reusable UI elements, such as headers, footers, navigation menus, and box decorations.

Summary

In this article, we explored how the Facelets view definition framework can be used to enhance presentation tier development in a JSF application.

We looked at a brief history of web development on the Java platform and compared Facelets with JSP technology to understand the advantages that Facelets offers to the JSF developer.

Facelets provides a fresh and compelling alternative to JSP as the view technology for JSF. Designed specifically to support the UI component tree lifecycle, Facelets is a highly optimized technology that greatly simplifies user interface development with the JSF framework.

Facelets pages are different from JSP pages because they are not compiled to generate servlets and they do not contain JSP expressions and directives. JSF tag libraries can be included in Facelets pages by using XML namespaces. Faceletsand JSP (since JSP 2.0) both support inline JSF EL expressions.

Our discussion included tips on how to configure a JSF application to use Facelets by specifying initialization parameters in web.xml and by configuring JSF to use the Facelets ViewHandler implementation in faces-config.xml. We can enable the Facelets refresh behavior during development, and disable it in production for best performance.

We studied examples of how to perform common tasks with the Facelets framework, such as enabling detailed error reporting with line number and attribute information, examining the UI component tree at runtime, iterating data in a Facelets page, including components and markup, removing components and markup, and decorating content in a Facelets page. We also looked at how to render advanced UI composition templates using the Facelets framework. Facelets templates can be reused by multiple client documents, simplifying the task of implementing a consistent look and feel across all the pages in our JSF application.

Based on the Composite View design pattern, Facelets is a sophisticated framework that makes it easy to create reusable user interface elements for a JSF application. Facelets supports a declarative approach to component-based development.

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.