Facelets tutorial: Using Templates

What are Facelets ? In short, Facelets is a core component of Jakarta Faces specification and also the preferred presentation technology for building Jakarta Faces technology-based applications. In this sample article we will see a few simple example of this technology.

Facelets are discussed in detail in the Jakarta Faces specification . In general terms, Facelets provide an abstract syntax tree that, when executed, builds a UIComponent hierarchy. You can design Facelets through XHTML pages using a simple set of expressions.

The biggest advantage of using Facelets for large-scale development projects include the following:

  • Support for code reuse through templating and composite components
  • Functional extensibility of components and other server-side objects through customization
  • Faster compilation time
  • Compile-time EL validation
  • High-performance rendering

We will best understand the concept with some example. Let’s see how you can use Facelets to create JSF templates.

Creating Templates with 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.

When describing templating within Facelets, we have two roles: the template and the template client. A template is basically a document which can act as a template; but what makes a document a template? It just simply uses one or more <ui:insert/> tags to inject some content from another source. The other half of the equation is the template client, which references the template, adding its own customizations.

Here’s an a sample 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://xmlns.jcp.org/jsf/facelets"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

<h:head>
    <h:outputStylesheet name="style.css" />

</h:head>

<h:body>
    <div class="page">
        <div class="header">
            <ui:include src="header.xhtml" />
        </div>

        <div class="content">
            <ui:insert name="content">
                    Default Content
                </ui:insert>
        </div>
        <div class="footer">
            <ui:include src="footer.xhtml" />
        </div>
    </div>

</h:body>
</html>

Two things to notice:

At first the tag library declaration (xmlns:ui=”http://xmlns.jcp.org/jsf/facelets”) which informs the compiler we want to use the tag for templates.

Then, notice the template tags. In this sample we are using the ui:include tag to include another .xhtml page in the document. We are using also the ui:insert tag to include a custom content which is named “content“. You will need to define “content” in the XHTML pages using this template.

For the purpose of this sample, just include two xhtml files named header.xhtml and footer.xhtml .

Here is the header.xhtml file:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<h2>
<h:outputText   value="This is the Facelet Header"/>
</h2>

</html>

And this is the footer.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">
<h2>
<h:outputText  value="This is the Facelet Footer"/>
</h2>

</html>

Now let’s move to the landing page of our application (index.xhtml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://xmlns.jcp.org/jsf/core" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
   <body>
      <ui:composition template="/templates/template.xhtml">
         <ui:define name="content">
            <h:form id="jsfexample">
               <h:dataTable value="#{userList}" var="item" styleClass="table" headerClass="table-header" rowClasses="table-odd-row,table-even-row">
                  <h:column>
                     <f:facet name="header">Name</f:facet>
                     <h:outputText value="#{item.name}" />
                  </h:column>
                  <h:column>
                     <f:facet name="header">Surname</f:facet>
                     <h:outputText value="#{item.surname}" />
                  </h:column>
                  <h:column>
                     <f:facet name="header">Email</f:facet>
                     <h:outputText value="#{item.email}" />
                  </h:column>
               </h:dataTable>
            </h:form>
         </ui:define>
      </ui:composition>
   </body>
</html>



Firstly, notice the ui:composition tag. This tag tells us that we are using the template.xhtml file as a template.

Then, within the ui:define section, we are defining the “content” section. That will be automatically added in our template.xhtml page.

facelets tutorial

Finally, within the JSF Datatable we are showing a list of User objects in tabular format. The list of User objects is available in the dataList alias which is produced in the following CDI Bean:

@Model
public class Manager {

    List<User> userList;
    
    @PostConstruct
    public void retrieveAllItems() {
 
        userList = new ArrayList<User>();
        userList.add(new User("John","Smith","[email protected]"));
        userList.add(new User("Frank","Walker","[email protected]"));
        userList.add(new User("Fiona","Middleton","[email protected]"));
    }
    
    
    @Produces
    @Named
    public List<User> getUserList() {
        return userList;
    }


}

Packaging and deploying the application

Your application is almost ready. We need to add some XML configuration though.

Firstly, add in your pom.xml the Jakarta dependency so that you can run your application on a Jakarta-compliant container such as WildFly:

<dependencies>
  <dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version>${jakartaee.version}</version>
    <scope>provided</scope>
  </dependency>
</dependencies>

Next, map in your web.xml declaration the correct mapping for .xhtml pages

<servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

This is the project tree for your Facelets application:

src
└── main
    ├── java
    │   └── com
    │       └── itbuzzpress
    │           └── jsf
    │               ├── bean
    │               │   └── Manager.java
    │               └── model
    │                   └── User.java
    └── webapp
        ├── index.xhtml
        ├── resources
        │   └── style.css
        ├── templates
        │   ├── footer.xhtml
        │   ├── header.xhtml
        │   └── template.xhtml
        └── WEB-INF
            ├── beans.xml
            ├── faces-config.xml
            └── web.xml

Deploy it on WildFly application server and reach out the index.xhtml page:

jsf facelets tutorial

Cool! We have just completed our first Facelets application. To learn how to build custom Facelets components check the following tutorial: Facelets tutorial. Using composition components

Source code: https://github.com/fmarchioni/mastertheboss/tree/master/web/jsf-facelets