JSF 1.2 ComponentsJava developers and Web designers today need more powerful tools to deliver the richer, faster, and smoother web experience that users now demand. JavaServer Faces is an advanced web application framework that includes hundreds of powerful, feature-rich,
Ajax-enabled UI components that provide all of the functionality needed to build web applications in a Web 2.0 world.
also read:
There has never been a better time to learn JSF. The JSF ecosystem is growing fast and the abundance of JSF components, development tools, industry conferences, and job opportunities is impressive. Learning JSF can be a challenge, but this book makes it easy by showing you the most important JSF technologies and concepts that you need to know to become a JSF professional.
What This Book Covers
Chapter 1: Standard JSF Components introduces you to the JavaServer Faces framework and the key concepts that you need to understand to build simple JSF applications. You will learn about Model-View-Controller, managed beans, the JSF expression language, converters, and validators. You will also discover how to use the standard JSF user interface components (such as text fields, radio buttons, selection lists, and checkboxes) to receive text, date/time, numeric, and other types of input from users as well as handle form submission, render messages, lay out components in a grid, and display a data table.
Chapter 2: Facelets Components introduces the Facelets view definition framework and compares it to JSP as the view technology for JSF. You will learn about working with valid XHTML documents and will see examples of how to use the Facelets framework to
create simple and complex composite user interfaces based on Facelets templates. You will also learn how to use the Facelets component library to display debugging information, iterate data, include and remove UI components and markup, pass parameters between Facelets pages, create reusable view elements, and apply advanced Facelets templating concepts.
Chapter 3: Apache Tomahawk Components covers the Apache Tomahawk component library and looks at how to use Tomahawk components such as calendars, trees, a file upload component, and navigation menus to solve common web development tasks. You
will learn how to use Tomahawk components to validate user input, accept date/time input, upload files, render tree components, create navigation menus, implement user interface security, display sortable data tables, and use newspaper layouts.
Chapter 4: Apache Trinidad Components discusses the Apache Trinidad framework and Ajax technology and will introduce you to many of the 100 plus rich user interface controls in this powerful component library. You will learn how to use color choosers,
pop-up calendars, dynamic trees, data tables, a number spinbox, shuttle components, navigation menus, layout panels, and more, to implement typical web development use cases. You will also learn how to use the Apache Trinidad dialog framework to add dialog windows to your application, how to enable Trinidad’s client-side JavaScript validation, how to create dynamic navigation menus, how to design custom skins and icons for Trinidad’s skinning framework, and how to use Trinidad’s partial page rendering (PPR) Ajax feature to enhance your JSF pages.
Chapter 5: ICEfaces Components introduces the ICEfaces Ajax component library, and explains many of the important concepts that you need to know in order to develop JSF applications based on ICEfaces. You will learn how to use many of the more than 50
Ajax-enabled user interface components in the ICEfaces component library, such as how to add dynamic effects to your pages to enhance input validation, how to use navigation and context menus, how to work with tree components, how to render dynamic data
tables that support sorting and paging, how to render pie charts and bar graphs, how to create a tabbed user interface, how to arrange elements using drag-and-drop, how to lay out components in a grid, and how to work with modal dialogs.
Chapter 6: JBoss Seam Components covers the JBoss Seam framework and introduces you to the fundamentals of building JSF applications that use the full Java Enterprise Edition (Java EE) technology stack. You will learn how to configure Seam, how to apply
Seam annotations to Java classes, and how to use Seam JSF controls to bridge the gap between Enterprise JavaBeans (EJB3) components, the Java Persistence API (JPA), and the JSF framework. This chapter will show you how to validate user input efficiently
using Seam, JPA, and the Hibernate Validator framework. You will also discover how to use the Seam tag library and Java API to display validation and success messages, render required field decorations, display debugging information, use Seam’s conversation
management feature to implement robust JSF workflows, and how to combine Seam with JBoss RichFaces and Ajax4jsf to build next generation JSF applications.
Chapter 7: JBoss RichFaces and Ajax4jsf Components covers the JBoss RichFaces and Ajax4jsf component libraries. You will learn how to use many advanced RichFaces components such as in-place editable text, a calendar, an Ajax-based auto-complete suggestion box, rich panel and menu components, a Google map component, a Microsoft Virtual Earth component, dynamic data tables with sorting and paging, data grids, a color picker, a slider component, a number spinner, a picklist control, a rich text editor, and
more. You will also learn how to add Ajax support to non-Ajax JSF components with Ajax4jsf, and how to perform advanced Ajax tasks such as submitting forms asynchronously, submitting one component at a time, polling the server, and re-rendering
parts of the page after an Ajax request.
Appendix: Learning JSF: Next Steps introduces JavaServer Faces 2.0 and provides a summary of the key features in the next generation of the JSF framework. You will discover how JSF 2.0 emphasizes convention over configuration by learning about the new JSF annotations to simplify managed bean configuration and reduce XML, the new JSF resource loading mechanism, the simplified navigation mapping convention, the integration of Facelets into the core JSF framework, the new “composite” JSF tag library for defining composite components, and the significantly improved support for Ajax that is now built-in to the framework. You will also learn about PrimeFaces, a promising new JSF component library.
Facelets Components
In the previous chapter, we looked at how to use standard JavaServer Faces components to implement a number of common web development tasks, such as rendering forms containing simple UI components and accepting and validating input from users. We also discussed several features and extension points of the JSF framework, such as the managed beans facility and message bundle support.
Indeed, the JSF framework was designed with extensibility in mind, enabling both application and framework developers to leverage its infrastructure to build even more sophisticated technologies on top of an already excellent platform for web development. One of the most interesting extension points of the JSF framework is the ViewHandler mechanism.
In this chapter, we will discuss one of the most important technologies in the JSF ecosystem—the Facelets view definition framework. The Facelets framework includes a pluggable ViewHandler implementation that provides an alternative to JavaServer Pages (JSP). Facelets also includes a number of useful JSF tags that can be used in place of the JavaServer Pages Standard Tag Library (JSTL).
To gain a better appreciation for the role of Facelets in the JSF context, we will begin with a brief history of Java web development, paying attention to the similarities and differences between Facelets and JSP. We will also look at how to configure a JSF application to use Facelets.
The topics we will look at in this chapter include:
- Getting started with Facelets
- Rendering debug information
- Iterating data in a Facelets page
- Removing UI components and markup
- Including UI components and markup
- Passing parameters from one Facelet to another
- Rendering a UI composition
- Rendering a UI component
- Creating a Facelets UI composition template
- Decorating the user interface
- Rendering a UI fragment
A brief history of Java web development
Before we dive into the details of the Facelets framework, let’s review a brief history of web development on the Java platform to understand how Facelets fits into this broader context.
Before Model-View-Controller (MVC) web frameworks and templating systems such as Struts, Tiles, Tapestry, JSF, and Facelets, building web applications on the Java platform involved writing Java Servlets and JavaServer Pages (JSPs).
JSP technology was introduced in 1999 as a competitor to Microsoft’s Active Server Pages (ASP) and PHP. JSP made it easier for Java developers to separate programming logic from web page markup, and introduced the concept of custom tag libraries. Developers could now write custom tag classes that could encapsulate presentation logic, register them in a Tag Library Descriptor (TLD) file, and use them declaratively in a JSP page simply by adding an import directive at the top of the page.
The Struts framework was originally launched in 2000 and made extensive use of the Servlet API, JSP, and the JSP custom tag mechanism. Struts applied the MVC design pattern to the Servlet API, and introduced a class named the ActionServlet that acted as the Front Controller of the framework. The Struts ActionServlet handled all requests matching a particular URL pattern (usually *.do) by delegating request processing to a number of application-defined action classes implementing the Command pattern.
The Struts framework also introduced a number of custom tag libraries, which provided useful functionality that was common to web development. Some of these libraries included tags for working with JavaBeans, tags for working with HTML elements, and tags for implementing presentation logic such as data iteration and conditional rendering.
The popularity of the Struts framework in general and of the Struts custom tag libraries in particular suggested a widespread need in the Java developer community for tools to simplify the process of implementing Java web applications. This need was recognized by the Java Community Process, and in 2002 the JSP Standard Tag Library (JSTL) was released. It introduced standardized tag libraries for implementing conditional logic, data iteration, date/time and number formatting, internationalization, and more.
The JSTL also supported the JSP Expression Language (JSP EL), a compact scripting language with a simple syntax that provided a less verbose and less error-prone alternative to JSP scriptlets for dynamic rendering.
Due to the similarities between the JSTL and the Struts custom tag libraries, the Struts documentation encouraged developers to adopt the JSTL over Struts tags, whenever there was redundancy between the two libraries.
The Struts framework also supported a templating system known as “Tiles”. Tiles was an open source project that integrated into the Struts framework and had a plug-in to support the definition of user interface screens based on the Composite View design pattern.
The Composite View design pattern
Implementing web user interfaces often involves creating and reusing a number of repeating branding and navigational elements, such as organizational logos, headers, footers, and navigation menus. An effective strategy for managing these repeating elements is to use the Composite View design pattern. This pattern helps us to subdivide our user interface into smaller pieces, and to create new views by “compositing” these pieces back together in different ways.
As we will see, Facelets performs a role similar to Tiles in the JSF context, but includes many other features as well.
When JSF 1.0 was released in 2004, it introduced a number of enhancements over and above what the Struts framework was currently providing, such as automatic type conversion of strings to and from other Java data types, direct binding of user interface components to application domain models, and more. The Struts framework can be described as an action-based MVC framework due to its emphasis on action classes and the command pattern, while JSF can be described as an event-driven, component-based MVC framework due to its emphasis on UI components and the Observer pattern.
The Command pattern and the Observer pattern
Two popular software design patterns are the Command pattern and the Observer pattern. The Command pattern emphasizes the use of objects as executable actions. An object encapsulates a single action, typically by implementing a callback interface method such as execute(), and is invoked by a Controller object. The Observer pattern is common in GUI programming and emphasizes
events and event handlers. Another name for the Observer pattern is the Publisher/Subscriber model. A UI component such as a button or hyperlink publishes an event (such as a mouse click), and an event handler observes user interaction and processes the event. The advantage of the Observer pattern is that a single object can manage state (the Model) more easily and can handle multiple events for a single user interface screen (the View). Also, a component can have multiple event handlers registered with it. The Observer pattern is also used in GUI toolkits such as Swing/AWT.
Like Struts, JSF is a highly extensible framework. JSF has a number of important extension points, such as managed beans, converters, validators, lifecycle phase listeners, UI components, render kits, and more. In JSF, even the view technology itself can be swapped out for an alternative ViewHandler implementation.
Comparing Facelets and JSP
Before we can appreciate the advantages that Facelets brings to a JSF application, let’s consider the role of JSP as the presentation technology for JSF. By default, the JSF ViewHandler mechanism uses JSP. The ViewHandler is an infrastructural component of the JSF framework that performs an important role during the request processing lifecycle, specifically during the Render Response and Restore View phases. The ViewHandler is responsible for creating, restoring, and rendering the UI component tree for the current view.
JSP was originally designed to solve the problem of how to include dynamic content in a static HTML document. JSPs enable dynamic content to be inserted into an HTML document through the use of scriptlets, expressions, and JSP directives.
These are typically blocks of Java code interspersed with HTML markup. When the JSP page is requested by the browser, the Servlet/JSP container generates a Java servlet from the JSP source code, compiles it, and executes it to produce an HTML document that is sent to the browser for rendering. This is called the JSP translation process and depending on the speed of the computer, it can take approximately one or two seconds to complete. During JSF application development, we often make many changes to our JSF pages, resulting in frequent recompilation of our JSP pages, and this compile-time overhead can add up.
Facelets pages are simply XML documents (typically XHTML pages) that are never compiled to servlets. Instead, Facelets uses a fast SAX-based compilation process that constructs the UI component tree for our views, which is free from the JSP translation overhead.
Another issue with JSP as the view technology for JSF applications is the mismatch between the JSP compilation process and the UI component tree lifecycle. When a JSP containing JSF tags is rendered for the first time, the page is executed and the components are constructed and rendered at the same time. The problem is that some UI components, such as labels, depend on the presence of other UI components in the tree before they can properly render themselves. The result is that some UI components may render in a different order from the first JSP page request to the next.
Fortunately, Facelets was designed with the JSF UI component lifecycle in mind and, for many developers, it represents a much more intuitive view technology for JSF application development. All of the examples in this book are based on Facelets, so a proper introduction is in order. Let’s take a look at how to configure a JSF application to use Facelets as the ViewHandler implementation.
Configuring a JSF application to use Facelets
Java web applications consist of compiled Java classes, XML configuration files, static resources, and other artifacts. To enable Facelets in our JSF application, we must configure our web.xml file with a few context parameters, which are used by the Facelets framework.
Mapping the FacesServlet
The FacesServlet is the front controller of the JSF application. Incoming requests are mapped to this servlet using different URI patterns. Although it is possible to map any arbitrary prefix and/or file extension to the FacesServlet, for simplicity, we have chosen to use the .jsf file extension for our FacesServlet mapping pattern.
Configuring web.xml
The following example demonstrates some of the context parameters that we set in web.xml to enable the Facelets ViewHandler. Notice that we set the facelets. REFRESH_PERIOD parameter to true to enable more verbose output during page development. This parameter should be set to false in a production environment.
We also set the facelets.REFRESH_PERIOD parameter to 1 second to ensure that Facelets detects and renders any changes that we make to our pages while the application is running. Whenever we make a change to a Facelets page, save it, copy it to our exploded web application deployment, and request it again in the browser; Facelets will compare the last modified date of the file with the date when the view was last compiled. If at least one second has elapsed, Facelets will recompile the view. Otherwise, it will render the previously compiled view.
The refresh behavior of the Facelets framework can be enabled in a development environment by setting the refresh period to 1 and disabled in a production environment by setting the refresh period to -1. As frequent changes to pages are not expected for a live application running on a production server, performance can be improved by disabling the refresh behavior using the -1 setting.
We also indicate that JSF should look for files with the .jsf extension when rendering our JSF pages. For simplicity, we chose to use the same file extension for the FacesServlet mapping pattern and the actual files that constitute our views, so all our JSF pages have the .jsf file extension.
The default behavior in Facelets is to exclude XML comments from the rendered response. This has some performance benefits, but can cause problems too. The facelets.SKIP_COMMENTS parameter when set to false indicates to Facelets that XML comments should be preserved from the rendered markup. One reason for preserving comments is to avoid breaking web pages that use legacy techniques such as wrapping JavaScript code with an HTML comment to hide it from older browsers. Another reason is simply to preserve HTML comments to improve the human readability of the rendered markup.
The following source code listing demonstrates how to configure Facelets in web.xml for a development environment. This configuration provides a simplified mapping relationship between JSF pages (*.jsf) and the FacesServlet, detailed error reporting and a refresh period that enables instant JSF view updates.
<context-param> <param-name>javax.faces.DEFAULT_SUFFIX</param-name> <param-value>.jsf</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <b><context-param> <param-name>facelets.DEVELOPMENT</param-name> <param-value>true</param-value> </context-param> <context-param> <param-name>facelets.REFRESH_PERIOD</param-name> <param-value>1</param-value> </context-param></b> <context-param> <param-name>facelets.SKIP_COMMENTS</param-name> <param-value>false</param-value> </context-param> <b><context-param> <param-name>facelets.VIEW_MAPPINGS</param-name> <param-value>*.jsf</param-value> </context-param></b> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <b><servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> <url-pattern>*.jsf</url-pattern> </servlet-mapping></b>
Configuring faces-config.xml
The next step in configuring Facelets in our JSF application is to specify the Facelets ViewHandler in our faces-config.xml file. The following example demonstrates the XML required to enable Facelets in our JSF application:
<application> <message-bundle>messages</message-bundle> <b><view-handler>com.sun.facelets.FaceletViewHandler</view-handler></b> <locale-config> <default-locale>en</default-locale> <supported-locale>fr</supported-locale> <supported-locale>es</supported-locale> </locale-config> </application>
Getting started with Facelets
One of the goals of the Facelets view definition framework is to simplify designing composite views in a JSF application. The Composite View design pattern is an approach to user interface development that encourages subdivision and reuse of view elements, such as headers, footers, navigation menus, and more. Let’s examine how the Facelets framework supports this approach. Facelets includes a number of useful tags for assembling JSF views from smaller elements.
What is a Facelet?
We can think of a Facelet as a subset of a user interface comprised of zero or more UI components. In this chapter, we will begin by looking at some of the basic tags in the Facelets tag library and will progress
towards a more complex composite view implementation based on advanced Facelets templating concepts.
Hello World Facelets
First, let’s begin with a very simple example of a Facelets page to highlight some key similarities and differences between Facelets and JSP. The following Facelets example renders a simple welcome message:
<!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"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Facelets Hello World Example</title> </head> <body> <p>Hello, #{backingBean.username}!</p> <p><h:outputText value="How are you today?" /></p> </body> </html>
There are a few details to note about this example. First, the document is a well-formed XHTML document and there are no scriptlets or JSP declarations on the page. Second, the roottag imports the JSF HTML tag library by declaring an XML namespace with the prefix h and the URL http://java.sun.com/jsf/html. This is similar to importing a tag library in a JSP page using the <%@ taglib %> directive. Third, notice the absence of the tag. This tag is not required in a Facelets page. Fourth, notice that Facelets supports inline JSF EL expressions. This enables page authors to render EL expressions mixed with plain HTML tags. Since JSP 2.0, inline EL expressions are also permitted in plain HTML and template text in JSP pages.
So, Facelets pages are very similar to JSP pages except:
- A Facelets page must be a well-formed XML document
- JSF tag libraries are imported using XML namespaces
- The tag is not required
- No JSP expressions or directives are allowed
- Facelets pages are not compiled to generated servlets
Rendering debug information
It is often helpful to have diagnostic information about the pages in our web application for analyzing and resolving issues. Aside from the usual error reporting mechanism of our web container, the JSF framework lacks a reliable means of obtaining detailed and precise error information about the pages in our JSF application.
Fortunately, the Facelets framework provides comprehensive diagnostic information to simplify debugging our JSF pages. For example, Facelets can provide detailed information about invalid EL expressions in our views. First, we must set the facelets.DEVELOPMENT initialization parameter to true in web.xml to enable detailed error reporting.
The following Facelets page example contains an unbalanced EL expression. When the page is rendered, a Facelets error page will be displayed indicating the view ID, line, and column number on which an unbalanced EL expression was declared.
error01.jsf
<!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>Facelets error page example</title> </head> <body> <b><h:outputText value="There are #{customerBean.customerCount customers." /></b> </body> </html>
In addition to reporting errors about EL expressions, Facelets can also provide XML syntax checking information to help us ensure that our JSF markup is well formed. Unlike JSP, Facelets is based on pure XML, and therefore requires that all JSF pages (typically XHTML documents) are valid as per the XML specification. The following screenshot demonstrates Facelets’ XML error reporting feature. In the next example, our EL expression is syntactically correct, but the tag is missing an end tag.
error02.jsf
<!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>Facelets error page example</title> </head> <body> <h:outputText value="There are #{customerBean.customerCount} customers."> </body> </html>
Facelets also includes a tag that can be used to render additional diagnostic information about our JSF pages even after we have corrected any invalid markup. The tag has two important attributes. The rendered attribute supports conditional rendering of debug information. In the following example, we only enable this information if Facelets is running in development mode. This ensures that our application will not incur the overhead of generating debug information for each view while running in production mode.
The hotkey attribute is also an important attribute for this tag. It defines the key to use in combination with the control and shift keys to open a pop-up window that will display the diagnostic information. By default, it is the letter “D”. The following example demonstrates how the Facelets debug page enables us to see the hierarchical structure of the UI component tree for our view. In this example, we include the Facelets debug component on our page and we press Ctrl+Shift+D to launch the debug window. Note that there are no errors on this page. The debug window is a useful tool for understanding the structure of the JSF UI component tree
for the current view.
debug01.jsf
<!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:debug example</title> </head> <body> <h:outputText value="There are #{customerBean.customerCount} customers." /> <ui:debug hotkey="D" rendered="#{initParam['facelets.DEVELOPMENT']}" /> </body> </html>
The following screenshot displays the result of pressing Ctrl+Shift+D to launch the Facelets debug window. Notice that a visualization of the UI component tree for the previous view is shown. For example, we can see the UIViewRoot component with a child HtmlOutputText component followed by the UIDebug component. We will use the Facelets debug window throughout this chapter to examine how Facelets tags can modify the UI component tree.
The Facelets debug page also displays any scoped variables such as request or session attributes that were used by the current view, as shown in the following screenshot. Notice the reference to the session-scoped customerBean object.
Iterating data in a Facelets page
The JSTL tag library includes a tag that supports iterating dynamic data. While Facelets supports a subset of the JSTL, it provides the tag as an alternative to the JSTL tag for data iteration. The following example demonstrates how to render an unordered list of customers using the Facelets tag and plain HTML tags:
repeat01.jsf
<!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:repeat example</title> </head> <body> <h:form> <ul> <ui:repeat value="#{customerBean.customerList}" var="customer"> <li>#{customer.fullName}</li> </ui:repeat> </ul> </h:form> </body> </html>
Removing UI components and markup
Sometimes, it is desirable to remove certain elements from a JSF page during development without necessarily deleting the markup. As developers we are accustomed to “commenting out” code, but standard JSF does not provide a simple way for us to remove markup without deleting it.
We can always set the rendered attribute to false for UI components, but what if the rendered attribute is already specified based on some EL expression? We can use HTML comments, but any EL expressions in those comments will still be evaluated,possibly resulting in runtime errors.
Facelets provides a simple solution to this problem: the tag. Any markup wrapped by the tag will literally be removed from the UI component tree at request time. The following example shows the difference between a button component that is not rendered, and a button component that is removed. In the first attempt, we set the button’s rendered attribute to false.
remove01.jsf
<!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:remove example</title> </head> <body> <h:form> <h:outputText value="The button below is not rendered." /> <h:commandButton rendered="false" /> <ui:debug /> </h:form> </body> </html>
Notice that the button component is still included in the UI component tree even when it is not rendered.
In the second example, we surround the button component with the tag. This is an effective way to remove UI components and markup from a JSF page.
remove02.jsf
<!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:remove example</title> </head> <body> <h:form> <h:outputText value="The button below is removed." /> <ui:remove> <h:commandButton /> </ui:remove> <ui:debug /> </h:form> </body> </html>
Notice that the button has now been removed from the UI component tree.
Including UI components and markup
One of the most common techniques for implementing the Composite View design pattern is the Server Side Include (SSI) technique. JSP supports the server-side include element, and Facelets provides similar functionality through the tag. The tag’s src attribute can be used to specify the path of a Facelets page to be included at request time. This technique enables us to externalize common view elements such as headers and footers as separate files and to reuse these by including them in other pages throughout our application.
Including a header and footer
The following example demonstrates how to create a simple composite view using the SSI approach. The header and footer files are included to create a complete view.
include01.jsf
<!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:include example</title> </head> <body> <h:form> <ui:include src="/WEB-INF/includes/header.jsf" /> <div>This is the body</div> <ui:include src="/WEB-INF/includes/footer.jsf" /> </h:form> </body> </html>
Creating the header Facelet
Notice that the following header file is a complete XHTML document, so it can be edited using any XML editor. But as we are using the Facelets tag, only the content inside this tag is included by the Facelets framework at request time; the content outside the tag will be trimmed.
The use of the tag makes it easier for us to edit complete XHTML documents in our favorite editor, while ensuring that Facelets uses only the content inside the composition to produce a valid composite view at runtime. If we did not wrap the header content shown in the following example with a tag, the entire document would be included, resulting in invalid markup.
HTML editors such as Dreamweaver will ignore the tag, enabling web designers to edit the header as if it was a complete document. When the header.jsf page is included by the include01.jsf page, only the desired content will be added to the document. We will discuss the tag in more detail later on, in this chapter.
header.jsf
<!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>Untitled Document</title> </head> <body> <ui:composition> <h1>Header</h1> <hr /> </ui:composition> </body> </html>
Creating the footer Facelet
The page footer can also be externalized as its own file and reused throughout the application.
footer.jsf
<!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>Untitled Document</title> </head> <body> <ui:composition> <hr /> <div>Footer</div> </ui:composition> </body> </html>
Passing parameters from one Facelet to another
Including static content declared in another document is fine for view elements such as headers and footers, but what if we wanted to pass an object from one Facelet to another? The tag is more than a simple SSI tag; it has enhanced functionality that makes it possible to pass arbitrary data from one page to another. Facelets supports the ability to pass parameters from one Facelet to another by nesting the tag inside a tag. Using the tag’s name and value attributes, we can define named content that can be referenced by the included Facelet.
The next example demonstrates how to pass parameters to an included Facelet by using the tag within a tag. In this case, we include a Facelet that renders a customer list twice, and we pass different parameters to each one. In the first case, we render a list of male customers, and in the second case we render a list of female customers.
This example demonstrates how we can create a Facelet that renders an unordered list of Customer objects using the tag. Instead of hardcoding the backing bean EL expression that obtains the list of customers in our tag’s value attribute, we can introduce some indirection here by referencing a parameter named customers that will be defined by the including Facelet.
param01.jsf
<!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:param example</title> <link rel="stylesheet" type="text/css" href="css/style.css" /> </head> <body> <h:form> <h:panelGrid columns="2"> <ui:include src="/WEB-INF/includes/customerList.jsf"> <ui:param name="title" value="Male Customers" /> <ui:param name="customers" value="#{customerBean.maleCustomers}" /> </ui:include> <ui:include src="/WEB-INF/includes/customerList.jsf"> <ui:param name="title" value="Female Customers" /> <ui:param name="customers" value="#{customerBean.femaleCustomers}" /> </ui:include> </h:panelGrid> <ui:debug rendered="true" /> </h:form> </body> </html>
The included customer list is defined in a separate Facelets document. Notice that the value expression for the is not bound to a backing bean directly, but indirectly using a parameter named customers.
By combining the Facelets tag with the tag, we can create dynamic, parameterized user interface elements that can be reused by other Facelets pages. The following example demonstrates how to create a reusable Facelet. Notice that the HTML element contains a parameter named title for the page header. Once again, we use the tag to surround the content that we wish to be included. Any markup outside the tag will be trimmed.
customerList.jsf
<!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"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> </head> <body> <ui:composition > <h2>#{title}</h2> <ul> <ui:repeat value="#{customers}" var="customer"> <li>#{customer.fullName}</li> </ui:repeat> </ul> </ui:composition> </body> </html>
Rendering a UI composition
In the previous example, we saw that content from one page could be included in another page by using a combination of the and tags. Let’s discuss the tag in more detail.
When Facelets encounters a tag, it includes the surrounded content and “trims” the content outside this tag. The surrounded content is included as is, and unlike the tag, is not wrapped in a UI component.
Including a UI composition
The following source code example demonstrates how to include a Facelets UI composition using the tag. When the markup in the file named composition.jsf is included, only the content inside the tag is rendered.
<!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:composition example</title> </head> <body> <ui:include src="/WEB-INF/includes/composition.jsf" /> <ui:debug /> </body> </html>
Declaring a UI composition
The Facelets UI composition from the previous example is declared here. Notice that the page is a complete XHTML document, so it can be edited by any XHTML editor, but as it is designed to be included by another page, the Facelets framework trims any content outside the tag at runtime.
<!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:f="http://java.sun.com/jsf/core" 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:composition example</title> </head> <body> Text before will be removed. <ui:composition> This text will NOT be rendered inside a UI component. </ui:composition> Text after will be removed. </body> </html>
The output in the debug window shown in the next screenshot demonstrates that the included text within the tag is inserted into the including Facelets page, but is not wrapped with a UI component.
Rendering a UI component
Sometimes, it is desirable to include content from another view element as a single UI component. This enables us, for example, to use the rendered attribute on the included content to support conditionally rendered markup more easily, and is convenient for situations where a single component is expected (such as inside the or tag).
The Facelets tag is similar to the tag. In both cases, any content outside the tag is trimmed, but in the case of the tag, the content will be rendered within a UI component. Let’s look at some examples of using the Facelets tag.
Including a UI component
The following example demonstrates that a Facelet containing a tag can be included just like a Facelet containing a tag:
component01.jsf
<!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:component example</title> </head> <body> <ui:include src="/WEB-INF/includes/component.jsf" /> <ui:debug /> </body> </html>
Declaring a UI component
The Facelet containing the tag is a complete XHTML document. It can be edited using any XHTML editor. The content outside the tag will be trimmed at runtime. The content inside the tag will be rendered inside a UIComponent instance.
component.jsf
<!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:f="http://java.sun.com/jsf/core" 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:component example</title> </head> <body> Text before will be removed. <ui:component> This text will be rendered inside a UI component. </ui:component> Text after will be removed. </body> </html>
The next screenshot demonstrates that the content inside the tag is inserted into the including Facelets page within a UI component.
Creating a Facelets UI composition template
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, fl ow, 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 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 tags in the Facelets template document with corresponding 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 tags that specify named content elements and references a Facelets template document using the tag’s template attribute. The Facelets template document contains two tags that have the same names as the tags in the client document, and three 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 tags with the content insertion points specified in the Facelets template document using the 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 definition 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 Example
The following is an example of a simple Facelets template. It simply renders a message within an HTML
element. Facelets will replace the “unnamed” tag (without the name attribute) in the template document with the content of the tag from the template client document.
template01.jsf
<!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:f="http://java.sun.com/jsf/core" 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>Facelets template example</title> <link rel="stylesheet" type="text/css" href="/css/style.css" /> </head> <body> <h2><ui:insert /></h2> </body> </html>
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 tag.)
The tag simply contains the text Hello World.
templateClient01.jsf
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html 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:composition example</title> </head> <body> <ui:composition template="/WEB-INF/templates/template01.jsf"> Hello World </ui:composition> <ui:debug /> </body> </html>
The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01.jsf.
Another simple Facelets template client
The following Facelets template client example demonstrates how a template can be reused across multiple pages in the JSF application:
templateClient01a.jsf
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html 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:composition example</title> </head> <body> <ui:composition template="/WEB-INF/templates/template01.jsf"> How are you today? </ui:composition> <ui:debug /> </body> </html>
The following screenshot displays the result of the Facelets UI composition template transformation when the browser requests templateClient01a.jsf:
Summary
In this chapter, 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.
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. As Facelets is supported by all major JSF component libraries, we will use it extensively throughout this book.