© Bauke Scholtz, Arjan Tijms 2018

Bauke Scholtz and Arjan Tijms, The Definitive Guide to JSF in Java EE 8, https://doi.org/10.1007/978-1-4842-3387-0_7

7. Facelets Templating

Bauke Scholtz and Arjan Tijms2

(1)Willemstad, Curaçao

(2)Amsterdam, Noord-Holland, The Netherlands

When JSF (JavaServer Faces) came out for first time in 2004, only JSP (Java Server Pages) had view technology. It was immediately clear that it was an ill-suited view technology for web development with JSF. The problem with JSP is that it writes to the HTTP response as soon as it encounters template text, while JSF would like to first create a component tree based on the view declaration in order to be able to perform the life cycle processing on it. For example, the following JSF 1.0/1.1 page using JSP view technology,

<h:commandLink action="...">
    <strong>strong link text</strong>
</h:commandLink>

would produce the following HTML output, with template text emitted by JSP before the generated HTML output of JSF components1:

<strong>strong link text</strong>
<a href="..." onclick="..."></a>

The “correct approach” would be to wrap template text in <f:verbatim> tags,

<h:commandLink action="...">
    <f:verbatim><strong>strong link text</strong><f:verbatim>
</h:commandLink>

which would produce the following HTML output:

<a href="..." onclick="...">  <strong>strong link text</strong></a>

This has obviously received a lot of criticism, and the general recommendation now is that people should not be mixing JSF with HTML. Another problem with JSF 1.0/1.1 was that there was no component to represent an HTML <div>. That was around the time “web 2.0” had just started, and people also started to discommend the use of HTML tables to lay out a web page. The prevailing view was that only divs should be used, which made people dislike JSF 1.0/1.1 even more.

The peculiar JSP behavior of causing a disorganized HTML output was worked around in JSF 1.2 which was released only two years later in 2006, and the missing component to represent an HTML <div> was solved by giving the <h:panelGroup> component a new layout="block" attribute so that it renders a <div> instead of <span>. So, already, since JSF 1.2, people can safely mix plain HTML with JSF components in a JSP page and continue using divs in both plain HTML and JSF ways. However, the recommended plan to avoid plain HTML while authoring JSF 1.0/1.1 pages turned into a persistent myth which is even today still alive among some people.

Another problem with JSP is that existing JSP taglibs such as JSTL (JSP Standard Tag Library) and existing JSP expressions in the form of ${…} didn’t integrate at all into the JSF life cycle and therefore mixing existing JSP taglibs and JSP expressions with JSF components in a JSP page would result in confusing and unintuitive behavior. People couldn’t use <c:forEach> to render a list of JSF components as those components wouldn’t see the variable declared by <c:forEach var>. There was no dedicated JSF component to loop over a list other than <h:dataTable> and ultimately people are stuck with tables while creating lists in the JSF page.

Finally, JSP also offers very limited templating capabilities with actually only one “templating” tag, <jsp:include>; therefore, templating with JSP would require a fairly complicated approach of creating a bunch of custom tags for every definition of a reusable template section.2 This contradicts the philosophy of JSF, to have reusable components to minimize code duplication. With JSP, you would end up duplicating JSF components themselves. Existing templating frameworks such as Tiles and Thymeleaf are either JSP centric or don’t support JSF at all and thus cannot be used.

There was clearly a strong need for a new-JSF oriented view technology which should supplant JSP and solve all of its problems with the JSF life cycle. And then Facelets was introduced in 2006. It could be installed separately for JSF 1.1 and 1.2, and it shipped built-in with JSF 2.0. It became the default view technology for JSF and JSP was deprecated as view technology for JSF. New tags introduced in JSF 2.0, such as <f:ajax>, <h:head>, <h:body>, <h:outputScript>, and <h:outputStylesheet>, are only available for Facelets and not for JSP. JSF 2.0 also introduced a new interface to more easily plug a custom view declaration language (VDL) as alternative to JSP and even Facelets, the ViewDeclarationLanguage API. This way, one could create, for example, a pure Java-based VDL for JSF.3

XHTML

The Facelets VDL specifies that the views are defined in XML-based files which are compiled using a SAX parser and kept around in memory. This memory cache is, since JSF 2.1, configurable using a custom FaceletCacheFactory. When the JSF project stage is set to Development, the SAX-compiled representations of Facelets files are by default not cached. This allows easier development against an already running server by just editing the Facelets files from inside an IDE (integrated development environment) which supports hot-publishing the local changes to the target runtime.

The Facelets files themselves usually use the .xhtml extension and therefore starters often call them “XHTML” instead of “Facelets.” This is okay when talking in the context of JSF, but the term “XHTML” has another side in the web development world. At its core, XHTML is a markup language for HTML pages which need to be compiled using an XML-based tool. In other words, developers basically create XML files with HTML markup mixed with web framework-specific XML tags, after which the web framework will parse them into an XML tree, generate some web framework-specific representation of the XML tree (which is in JSF the UIViewRoot), and ultimately generate the desired HTML output based on the framework’s internal representation of the XML tree.

But around the time of Facelets’ introduction in 2006, XHTML was being overhyped by another group of web developers who were basically disappointed by seeing the W3 validator invalidate their HTML4 documents—generally because of the desire to explicitly close all tags for consistency, including those which should actually not be closed as per HTML4 specification, such as <link>, <meta>, <br>, and <hr>—and sometimes because of the desire to specify custom tag attributes in order to have some JavaScript plug-ins to interact more cleanly with the HTML document, which is also disallowed by the HTML4 specification.

Even though basically every single web browser in the world leniently accepted that, including Jurassic IE6, those developers didn’t want to see their carefully crafted HTML4 documents being invalidated by the W3 validator and changed their HTML doctype declaration to use the XHTML DTD, an extension to HTML which requires every tag to be closed and allows custom attributes to be specified on existing tags. However, this is essentially abuse of XHTML as they didn’t at all actually use any XML tool to compile the document and generate the desired HTML output. It was merely to keep the W3 validator happy.

Coincidentally, also around that time, HTML5 was just started in draft. Essentially, developers could just strip out any DTD from the HTML doctype declaration in order to get an HTML document which allows XML-based syntax wherein all tags are always closed and custom elements and attributes are allowed and, importantly, validated correctly in the W3 validator. In other words, <!DOCTYPE html> was been sufficient for those developers, even in IE6. Unfortunately, it took ages before HTML5 was officially finished, so developers kept abusing the XHTML doctype before they could switch back to the HTML doctype. When talking about Facelets to those group of developers, don’t call it “XHTML” but just “Facelets”; otherwise it will generate confusion.

Template Compositions

Facelets provides tags for easily creating template compositions based on a single master template file. This should reduce code duplication for site-wide sections which are repeated across all web pages, such as header, navigation menu, and footer. The master template file should represent a full-blown web page layout with all site-wide sections and use <ui:insert> tags to represent places where the page-specific sections can be inserted. Following is a basic example of such a master template file, /WEB-INF/templates/layout.xhtml:

<!DOCTYPE html>
<html lang="en"
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <h:head>
        <title>#{title}</title>
    </h:head>
    <h:body>
        <header>
            <ui:include src="/WEB-INF/includes/layout/header.xhtml" />
        </header>
        <main>
            <ui:insert name="content" />
        </main>
        <footer>
            <ui:include src="/WEB-INF/includes/layout/footer.xhtml" />
        </footer>
    </h:body>
</html>

Note that the master template file and include files are explicitly placed in the /WEB-INF folder. This is done in order to prevent direct access by users who are guessing the path in URL. Also note that the page title is declared as a simple EL (Expression Language) expression #{title} instead of <ui:insert>. It is not allowed to have any markup in the <title> element.

The xmlns attribute basically defines, via a URI (uniform resource identifier), which tags can be used in the declared XML namespace. The root XML namespace specifies the URI of the W3 XHTML standard http://www.w3.org/1999/xhtml which thus defines “any XHTML and HTML5+ tag,” such as <html>, <title>, <header>, <main>, and <footer> in above example. The Facelets compiler is aware of this standard XML namespace and will pass through all elements as “general UI instructions.” The “h” XML namespace specifies the JSF HTML taglib URI and the “ui” XML namespace specifies the JSF Facelets taglib URI, which are both present in the JSF implementation JAR file and registered to Facelets during the web application’s startup. The Facelets compiler can this way find the associated tag handlers, components, and composite components, which in turn do the hard work of building the view, decoding the HTTP request, and encoding the HTTP response. Those URIs are thus not per definition live Internet addresses. You can even specify your own via a *.taglib.xml file. This will be expanded later in the section “Tag Files.”

Following is what the include file /WEB-INF/includes/layout/header.xhtml looks like:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <a href="#{request.contextPath}/">
        <h:graphicImage name="images/layout/logo.svg" />
    </a>
    <nav>
        <ul>
            <li><h:link outcome="/about" value="About" /></li>
            <li><h:link outcome="/help" value="Help" /></li>
            <li><h:link outcome="/contact" value="Contact" /></li>
        </ul>
    </nav>
</ui:composition>

Note the link around the logo. It points to #{request.contextPath}/. This basically prints the domain-relative URL to the application’s root. #{request} is an implicit EL object referring the current HttpServletRequest instance. contextPath refers to one of its properties, implied by the getContextPath() method.

Following is what the include file /WEB-INF/includes/layout/footer.xhtml looks like:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <nav>
        <ul>
            <li><h:link outcome="/terms-of-service"
                        value="Terms of Service" /></li>
            <li><h:link outcome="/privacy-policy"
                        value="Privacy Policy" /></li>
            <li><h:link outcome="/cookie-policy"
                        value="Cookie Policy" /></li>
        </ul>
    </nav>
    <small>© Example Company</small>
</ui:composition>

Finally, here’s how the template client can look, e.g., /home.xhtml:

<ui:composition template="/WEB-INF/templates/layout.xhtml"
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <ui:param name="title" value="Welcome!" />


    <ui:define name="content">
        <h1>Welcome to Example Company!</h1>
        <p>Lorem ipsum dolor sit amet.</p>
    </ui:define>
</ui:composition>

Note the template attribute of the <ui:composition>. This must represent the server-side path to the master template, preferably as an absolute path, thus starting with “/”.

In a template client, <ui:param> lets you define a simple parameter specific for the master template. Basically, you can use any parameter name, as long as it is supported by the master template and doesn’t clash with an existing managed bean name. In this specific case, the value for the EL variable #{title} is specified as “Welcome!”. This will ultimately end up inside the <title> element of the master template.

And the <ui:define> lets you define a block of markup specific for the master template. It will ultimately end up in the place where the <ui:insert> with exactly the same name is declared in the master template. Figure 7-1 gives a clear overview of how this all fits together.

A454457_1_En_7_Fig1_HTML.jpg
Figure 7-1 The relationship between the master template layout.xhtml, include files header.xhtml, and footer.xhtml, and the template client home.xhtml. Note that template file paths and some tag attributes are omitted for brevity. Refer the previously shown code snippets for the actual coding.

Finally, opening /home.xhtml should produce the final HTML output which you can inspect by right-clicking View page source in the average web browser.

Single Page Application

A recent trend is the so-called Single Page Application (SPA) . This concept is on its own not so new; in fact, it is older than JSF itself, but it was heavily popularized during “web 2.0” with JavaScript-based frameworks such as Angular. Basically, an SPA lets the web application behave like a desktop-oriented application by dynamically changing the main content with an Ajax request when navigating to a different page instead of loading the entire page via a GET request. Gmail is one such known example of an SPA.

Such an SPA is also achievable with JSF by simply using <ui:include> whose src attribute is dynamically updated by Ajax. Following is an example utilizing the same master template as shown in the previous section , /spa.xhtml:

<ui:composition template="/WEB-INF/templates/layout.xhtml"
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <ui:param name="title" value="Single Page Application" />


    <ui:define name="content">
        <aside>
            <nav>
                <h:form>
                    <f:ajax render=":content">
                        <ul>
                            <li><h:commandLink value="page1"
                                action="#{spa.set('page1')}" /></li>
                            <li><h:commandLink value="page2"
                                action="#{spa.set('page2')}" /></li>
                            <li><h:commandLink value="page3"
                                action="#{spa.set('page3')}" /></li>
                        </ul>
                    </f:ajax>
                </h:form>
            </nav>
        </aside>
        <article jsf:id="content" data-page="#{spa.page}">
            <ui:include src="/WEB-INF/includes/spa/#{spa.page}.xhtml" />
        </article>
    </ui:define>
</ui:composition>

Do note that the <article> element is declared as a so-called pass-through element by explicitly specifying a JSF identifier via jsf:id="…". This feature was introduced in JSF 2.2. Under the hood, when declaring an HTML element which has no JSF component equivalent, such as <header>, <footer>, <main>, <article>, <section>, etc. as a pass-through element this way, it is turned into a UIPanel component and is treated in the JSF component tree exactly like <h:panelGroup>. This way you can cleanly keep using semantic HTML5 markup while still being able to reference it as if it were a JSF component and thus be able to Ajax-update it.

As you might have deciphered in the above /spa.xhtml example, there’s a side navigation menu which sets the current page in the managed bean identified by #{spa} and Ajax-updates the component identified by id="content" which in turn contains a dynamic include. The above example excepts the following include files to be present in the /WEB-INF/includes/spa folder: page1.xhtml, page2.xhtml, and page3.xhtml. Each of them is a simple include file which looks as follows:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <h1>First page</h1>
    <p>Lorem ipsum dolor sit amet.</p>
</ui:composition>

The backing bean associated with the #{spa} managed bean is fairly simple; it looks as follows:

@Named @ViewScoped
public class Spa implements Serializable {


    private String page;

    @PostConstruct
    public void init() {
        page = "page1";
    }


    public void set(String page) {
        this.page = page;
    }


    public String getPage() {
        return page;
    }
}

The default page is defined in @ PostConstruct . Otherwise, the user might face an error page with the message “Invalid path : /WEB-INF/includes/spa/.xhtml”.

Note that the backing bean is declared @ViewScoped. This is important in order to remember across postbacks which page is currently being opened. If it were @RequestScoped, and the user navigates to, e.g., page2 and submits a form therein, which creates a new HTTP request, then the @RequestScoped managed bean would be recreated again, with page1 as page value and thus not page2. This has the consequence that <ui:include> won’t reference page2.xhtml when JSF is about to decode any input components in order to process the form submit during the postback request, and therefore JSF would fail to find the input components declared in page2.xhtml. A @ViewScoped bean lives as long as the user postbacks to the very same view, in this case /spa.xhtml, and therefore correctly remembers the currently selected page.

When playing around with this SPA example, you might have noticed one disadvantage: the pages are not bookmarkable. This is caused by the fact that the pages are not opened by an idempotent GET request. You can solve that by utilizing the HTML5 history.pushState API.4 Basically, on completion of the Ajax request you should push the intended URL to the browser history, which will be reflected in the browser’s address bar. And, you should modify the Spa backing bean to check if any specific page has been opened and then prepare the page variable accordingly.

Following is a kickoff example which just appends the ?page=xxx query string parameter. First adjust the <f:ajax> of the spa.xhtml to specify the onevent attribute as follows:

<f:ajax ... onevent="pageChangeListener">

And create the following JavaScript function:

function pageChangeListener(event) {
    if (event.status == "success") {
        var page = document.getElementById("content").dataset.page;
        var url = location.pathname + "?page=" + page;
        history.pushState(null, document.title, url);
    }
}

And, finally, adjust the Spa backing bean as follows:

@Inject @ManagedProperty("#{param.page}")
Private String page;


public void init() {
    if (page == null) {
        page = "page1";
    }
}
Note

The @ManagedProperty is currently available in two flavors: the deprecated one from the javax.faces.bean package and the JSF 2.3 introduced one from the javax.faces.annotation package.

You need the latter one. Also, note that you might want to validate the provided page parameter . Path probing by hackers is innocent, by the way, as JSF already doesn’t allow traversing into the parent path as in /spa.xhtml?page=../../templates/layout.

Template Decorations

In case you would like to have a reusable include file which is capable of inserting template definitions as if you would be using <ui:include> to reference an include file with one or more <ui:insert> sections, then you can use <ui:decorate>. Following is one such example, the /WEB-INF/decorations/contact.xhtml:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <section class="contact">
        <header><ui:insert /></header>
        <nav>
            <ul>
                <li>✆ <a href="tel:+31612345678"
                    title="Phone">+31 (0)6 1234 5678</a></li>
                <li>✉ <a href="mailto:[email protected]"
                    title="Email">[email protected]</a></li>
            </ul>
        </nav>
    </section>
</ui:composition>

Here is how it can be used, you can put the <ui:decorate> anywhere in your template client, as a <ui:include>:

<ui:decorate template="/WEB-INF/decorations/contact.xhtml">
    <h2>Questions? Contact us!</h2>
</ui:decorate>

Note that the contact.xhtml has only one <ui:insert> and that it has no name. This will insert the entire <ui:decorate> tag body at the declared place of <ui:insert>. You can, of course, specify a name, but then you would need to explicitly specify <ui:define> with a name for that. That would be only useful if you have more than one insert sections.

You can, if necessary, use <ui:param> to pass parameters. This works the same way as with <ui:composition template>. The following example parameterizes the e-mail user name /WEB-INF/decorations/contact.xhtml with a default value of “info.”

...
<li>✉ <a href="mailto: #{empty mailto ? 'info' : mailto}@example.com"
    title="Email">#{empty mailto ? 'info' : mailto}@example.com</a></li>
...

This can then be used as follows:

<ui:decorate template="/WEB-INF/decorations/contact.xhtml">
    <ui:param name="mailto" value="press" />
    <h3>Contact us</h3>
    <p>
        For press inquiries you can contact us by the below
        phone number and email address.
    </p>
</ui:decorate>

Tag Files

As with <ui:composition template> and <ui:decorate>, you can also use <ui: param> in <ui:include>. However, watch out that you don’t go overboard.

<ui:include src="/WEB-INF/includes/field.xhtml">
    <ui:param name="id" value="firstName" />
    <ui:param name="label" value="First Name" />
    <ui:param name="value" value="#{profile.user.firstName}" />
</ui:include>

Wherein the /WEB-INF/includes/field.xhtml looks something like the following:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf "
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
>
    <div class="field" jsf:rendered="#{rendered ne false}">
        <h:outputLabel id="#{id}_l" for="#{id}" value="#{label}" />
        <c:choose>
            <c:when test="#{type eq 'password'}">
                <h:inputSecret id="#{id}" label="#{label}"
                    value="#{value}">
                </h:inputSecret>
            </c:when>
            <c:when test="#{type eq 'textarea'}">
                <h:inputTextarea id="#{id}" label="#{label}"
                    value="#{value}">
                </h:inputTextarea>
            </c:when>
            <!-- More types can be added as c:when here -->
            <c:otherwise>
                <h:inputText id="#{id}" label="#{label}"
                    value="#{value}" a:type="#{type}">
                </h:inputText>
            </c:otherwise>
        </c:choose>
        <h:messages id="#{id}_m" for="#{id}" styleClass="messages" />
    </div>
</ui:composition>

In such a case, you would prefer to have something more concise, like the following, instead:

<t:field id="firstName" label="First Name"
    value="#{profile.user.firstName}">
</t:field>

Having <ui:include> with two or more <ui: param> is a strong sign that the include file can better be registered as a tag file so that it can be used with less boilerplate code in the Facelet.

First move the include file into a different subfolder, /WEB-INF/tags/field.xhtml. This is not a technical requirement. It will work just fine wherever you put it, but we just want to organize the files clearly. Master template files go in /WEB-INF/templates, include files go there in /WEB-INF/includes, decorate files go in /WEB-INF/decorations, and tag files go in /WEB-INF/tags.

Then, create the following /WEB-INF/example.taglib.xml:

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
    xmlns:="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_3.xsd"
    version="2.3"
>
    <namespace>http://example.com/tags</namespace>
    <short-name>t</short-name>


    <tag>
        <description>Renders label + input + message field.</description>
        <tag-name>field</tag-name>
        <source>tags/field.xhtml</source>
        <attribute>
            <description>The type of the input component.</description>
            <name>type</name>
            <required>false</required>
            <type>java.lang.String</type>
        </attribute>
        <attribute>
            <description>The ID of the input component.</description>
            <name>id</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
        <attribute>
            <description>The label of the input component.</description>
            <name>label</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
        <attribute>
            <description>The value of the input component.</description>
            <name>value</name>
            <required>false</required>
            <type>java.lang.Object</type>
        </attribute>
        <attribute>
            <description>Whether the field is rendered.</description>
            <name>rendered</name>
            <required>false</required>
            <type>boolean</type>
        </attribute>
    </tag>
</facelet-taglib>

That’s admittedly quite some boilerplate code. It is good to know that the <attribute> elements aren’t mandatory for the technical functioning of the tag file. You could even omit them altogether. But then the IDE won’t be able to load them into autosuggest boxes while attempting to autocomplete the custom tag. This is not really developer-friendly. So you’d better keep them in. The <required> property of the tag attribute, by the way, only results in a runtime error when the JSF project stage is set to Development. In other JSF project stages, it’s ignored. And the average IDE will immediately prompt those required attributes during autocompleting the tag.

The file name, example.taglib.xml, is free to your choice. In order for JSF to automatically pick up a taglib file during the application’s startup, there are only two requirements: it must have a .taglib.xml extension and it must be placed in /WEB-INF folder (or in case of a JAR file which ends up in /WEB-INF/lib, then in /META-INF folder of that JAR file). Unfortunately, placing the file in /WEB-INF doesn’t always work quite well in some servers, such as GlassFish/Payara. In that case, you’d have to explicitly register it via the following context parameter in web.xml whose value represents the full path to the *.taglib.xml file from the web root on.

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/example.taglib.xml</param-value>
</context-param>

In order to use any tag defined in the *.taglib.xml, you first have to declare exactly the <namespace> URI of the taglib in your Facelet, along with an arbitrary XML namespace prefix. For better maintainability of the code it’s recommended to pick the taglib’s preferred XML namespace prefix as specified in its <short-name>, which is “t” in case of our example.taglib.xml.

<ui:composition template="/WEB-INF/templates/layout.xhtml"
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:t="http://example.com/tags"
>
    <ui:param name="title" value="Log In" />


    <ui:define name="content">
        <h:form>
            <fieldset>
                <header>
                    <h1>Log In</h1>
                </header>
                <t:field type="email" id="email" label="Email"
                    value="#{login.email}">
                </t:field>
                <t:field type="password" id="password" label="Password"
                    value="#{login.password}">
                </t:field>
                <footer>
                    <t:button id="submit" label="Log In"
                         action="#{login.submit()}">
                    </t:button>
                </footer>
            </fieldset>
        </h:form>
    </ui:define>
</ui:composition>

Do note that the type="email" of the e-mail field thus ends up in <c:otherwise> of the tag file implementation wherein it gets passed through the a:type="#{type}" attribute of <h:inputText>. This allows you to easily use HTML5 input fields, such as type="email", type="number", type="tel", etc. The type attribute being defined as a pass-through attribute a:type is mandatory, because the <h:inputText> by default ignores any custom type attribute and stubbornly renders type="text".

You might also have noticed another custom tag, <t:button>. Here’s how it is implemented in /WEB-INF/tags/button.xhtml.

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
>
    <div class="button" jsf:rendered="#{rendered ne false}">
        <h:commandButton id="#{id}" value="#{label}">
            <f:actionListener binding="#{action}" />
            <f:ajax execute="@form" render="@form" />
        </h:commandButton>
        <h:messages id="#{id}_m" globalOnly="true" redisplay="false" />
    </div>
</ui:composition>

It’s registered in example.taglib.xml nearly the same way as <t:field>, with one exception for the action attribute. Technically, you need to specify a <method-signature> instead of a (property) <type>:

<attribute>
    <description>
        Action method of the button.
        NOTE: must include method parenthesis.
    </description>
    <name>action</name>
    <required>true</required>
    <method-signature>void action()</method-signature>
</attribute>

You might have noticed that the actual tag implementation uses <f:actionListener binding="#{action}"> instead of action="#{action}". This is actually a necessary trick in order to get it to properly invoke the method. That is, the <method-signature> was initially intended for UI components, not for tag files. It’s ignored in tag files. This may be worked on for JSF.next. For now, you can get away with the <f:actionListener binding> trick. This has only one additional requirement: you need to explicitly include the method parenthesis in the tag file client as in <t:button action="#{login.submit()}">.<t:button action="{login.submit}"> will otherwise fail with javax.el.PropertyNotFoundException: The class ‘com.example.project.view.Login’ does not have the property ‘submit’.

In case you would like to customize tag files from the tag file client side on, e.g., by adding more specific input attributes, or nesting core tags, or by prepending or appending content to the label or message, then you can use <ui:define> and <ui:insert> the same way you’re used to doing with master template files and decorate files. The following example demonstrates how you can enhance the /WEB-INF/tags/field.xhtml on this with a bunch of new <ui:insert> tags:

<ui:composition
    xmlns:="http://www.w3.org/1999/xhtml"
    xmlns:jsf="http://xmlns.jcp.org/jsf "
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:a="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
>
    <div class="field" jsf:rendered="#{rendered ne false}">
        <ui:insert name="beforeLabel" />
        <ui:insert name="label">
            <h:outputLabel id="#{id}_l" for="#{id}" value="#{label}">
                <span><ui:insert name="insideLabel" /></span>
            </h:outputLabel>
        </ui:insert>
        <ui:insert name="beforeInput" />
        <ui:insert name="input">
            <c:choose>
                <c:when test="#{type eq 'password'}">
                    <h:inputSecret id="#{id}" label="#{label}"
                        value="#{value}">
                        <ui:insert />
                    </h:inputSecret>
                </c:when>
                <c:when test="#{type eq 'textarea'}">
                    <h:inputTextarea id="#{id}" label="#{label}"
                        value="#{value}">
                        <ui:insert />
                    </h:inputTextarea>
                </c:when>
                <!-- More types can be added as c:when here -->
                <c:otherwise>
                    <h:inputText id="#{id}" label="#{label}"
                        value="#{value}" a:type="#{type}">
                        <ui:insert />
                    </h:inputText>
                </c:otherwise>
            </c:choose>
        </ui:insert>
        <ui:insert name="beforeMessages" />
        <ui:insert name="messages">
            <h:messages id="#{id}_m" for="#{id}" styleClass="messages" />
        </ui:insert>
    </div>
</ui:composition>

Now, that’s a lot of flexibility! In the tag file client you can use <ui:define name="beforeLabel"> to define some content which should appear before the label of the field. And you can use <ui:define name="label"> to override the label altogether. And you can use <ui:define name="insideLabel"> to append some (HTML) content inside the label, and so forth. The following example demonstrates how insideLabel can be used to append a “Forgot password?” link to the label of the password field:

<t:field ...>
    <ui:define name="insideLabel">
        <h:link outcome="/reset-password" value="Forgot password?" />
    </ui:define>
</t:field>

Note that <ui:insert name=" insideLabel"> is wrapped in an HTML <span>. This allows you to more easily select “anything” that ends up in there via CSS, so that you can, for example, let it float to the right using just .field label > span { float: right; }.

Anything else in the tag file client which is not <ui:define> will end up inside the nameless <ui:insert> tag nested in the chosen input component. This allows you to easily nest any <f:xxx> core tag specifically for the input component:

<t:field ...>
    <f:attribute name="onkeypress" value="return event.key != 'Enter'" />
    <f:validateRegex pattern="[0-9]{4}" />
    <f:ajax render="otherField" />
</t:field>

This specific example prevents the form from submitting when the Enter key is pressed by returning false when the KeyBoardEvent.key equals “Enter”, and registers a regex validator to accept only a value of four digits by matching against a regular expression pattern of “[0-9]{4}”, and instructs JSF to update the component identified by “otherField” by Ajax when the value change event has occurred.

Coming back to the tag file implementation in /WEB-INF/tags/field.xhtml, you might have noticed that good old JSTL is being used there instead of JSF’s own rendered attribute. This has advantages as JSTL has a different life cycle than JSF UI components. JSTL is executed when the JSF component tree is about to be built, during the view build time. JSF components are executed when HTML output is about to be generated, during the view render time. Moreover, if you were using JSF’s own rendered attribute, then you would face “duplicate component ID” errors because of multiple components with the same ID physically ending up in the JSF component tree.

Might it happen that you are considering the use of plain Java code to dynamically create the component tree based on at least a view-scoped model, you should absolutely reconsider using JSTL instead. As JSTL itself is also XML-based and you can thus just put together everything in an XHTML file, you will end up with much better readable and maintainable code for a “dynamic” component.

Composite Components

Sometimes, you would like to have a group of related input components to represent a single model value. A classic example is having three <h:selectOneMenu> drop-downs representing day, month, and year which are ultimately bound to a single java.time.LocalDate property in the backing bean. This is not trivial to implement with just an include file or a tag file. You would need some additional Java-based logic which makes sure that, e.g., the day drop-down doesn’t show the values 29, 30, or 31 depending on the currently selected month, and that it converts the submitted values to a full-fledged LocalDate instance, and vice versa. But you can’t and shouldn’t put any Java code in any Facelet.

You’ll perhaps think of just creating a dedicated backing bean for this case. But this is not sufficient either. It doesn’t allow you to cleanly hook on the component’s life cycle through the JSF phases: collecting the individual submitted values from multiple components, converting them into a single LocalDate instance, if necessary throwing a converter exception during the validations phase, and letting the JSF life cycle automatically skip the remaining phases. A backing bean’s setter method or action method is far from the right place for that logic. It would be invoked too late anyway. And, it would feel strange to be able to reference and potentially manipulate the very same backing bean via an EL expression on an arbitrary place in the Facelet.

This is exactly where composite components come into the picture: composing a bunch of existing JSF components into virtually a single component tied to a single model value and ultimately using it exactly the same way as you would be using a plain <h:inputText>. Imagine a <t:inputLocalTime> composite component composed of two <h:selectOneMenu> components tied to a single java.time.LocalTime model value. Instead of a backing bean, you can use a full-fledged UIComponent instance as a so-called backing component.

First create a dedicated subfolder in main/webapp/resources folder (and thus not main/java/resources!), for example, main/webapp/resources/components. There you can put Facelets files representing composite components. The subfolder is then to be used in the XML namespace URI after http://xmlns.jcp.org/jsf/composite as shown next.

xmlns:t="http://xmlns.jcp.org/jsf/composite/components"

Note that the XML namespace prefix of “t” clashes with one which we already defined before for tag files. This is of course not the intent. You may choose a different XML namespace for composite components. It’s, however, also possible to let them share the same custom XML namespace URI http://example.com.tags . This can be achieved by adding a <composite-library-name> to the *.taglib.xml which in turn must represent the name of the dedicated subfolder.

<composite-library-name>components</composite-library-name>

This way all composite components are also available by the same XML namespace as tag files.

<... xmlns:t="http://example.com/tags">
...
<t:inputLocalTime ... />

The file name of the Facelets file representing the composite component will become the tag name. So, in order to have a <t:inputLocalTime>, we need an inputLocalTime.xhtml file in the main/webapp/resources/components folder. Following is a kickoff example of what it can look like:

<ui:component
    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"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite"
>
    <cc:interface componentType="inputLocalTime">
        <cc:attribute name="value" type="java.time.LocalTime"
            shortDescription="Selected time. Defaults to 00:00.">
        </cc:attribute>
        <cc:attribute name="required" type="boolean"
            shortDescription="Required state. Defaults to false.">
        </cc:attribute>
    </cc:interface>
    <cc:implementation>
        <span id="#{cc.clientId}" class="inputLocalTime">
            <h:selectOneMenu id="hour" binding="#{cc.hour}"
                required="#{cc.attrs.required}">
                <f:selectItem itemValue="#{null}" />
                <f:selectItems value="#{cc.hours}" />
            </h:selectOneMenu>
            :
            <h:selectOneMenu id="minute" binding="#{cc.minute}"
                required="#{cc.attrs.required}">
                <f:selectItem itemValue="#{null}" />
                <f:selectItems value="#{cc.minutes}" />
            </h:selectOneMenu>
        </span>
    </cc:implementation>
</ui:component>

There are several things to notice here which makes a composite component different from a tag file. First, the composite component’s body is always divided into two sections: an interface and an implementation.

The interface declares a componentType attribute which should reference the value of either the @FacesComponent annotation on a UIComponent subclass or the <component-type> entry of a <component> as declared in either faces-config.xml or *taglib.xml. When the componentType attribute is absent, it defaults to UINamingContainer. The interface also declares the supported attributes. To keep it simple, we restrict to only two: value and required. There are also implicitly inherited attributes from the UIComponent superclass, which we don’t need to explicitly define as <cc:attribute>: id, binding, and rendered. That makes it a total of five attributes which you can use in the implementation.

The implementation defines the actual markup of the composite component. There you can find the two <h:selectOneMenu> drop-downs wrapped in a <span> element. There you can also find several occurrences of the special EL variable #{cc} which refers to the current UIComponent instance behind the composite component, which is thus one of the type as declared in the componentType attribute, or, if absent, a UINamingContainer. #{cc.attrs} is a shortcut to the component attribute map as available by UIComponent#getAttributes(). #{cc.attrs.required} as used in <t:inputLocalTime> thus refers to <cc:attribute name="required">.

#{cc.clientId} in the <span> element just prints the composite component’s client ID as the id attribute of <span>. This is actually a trick in order to be able to reference the “whole” composite component using a client ID search expression from the template client on. Imagine the following case:

<h:inputText ...>
    <f:ajax render="time" />
</h:inputText>
<t:inputLocalTime id="time" ... />

This case wouldn’t have worked without the #{cc.clientId} being rendered as an ID of any plain HTML element which wraps the entire body of <cc:implementation>, usually a <span> or <div>. The technical problem is, while the composite component itself is findable in the JSF component tree by the component ID search expression, the HTML representation of the composite component is by default not available by document.getElementById(clientId) in JavaScript. In other words, JSF Ajax wouldn’t be able to update it. Explicitly adding a plain HTML element with the composite component’s client ID thus solves that.

Finally, there are a bunch of #{cc} expressions which don’t reference the attributes directly. Both of the <h:selectOneMenu> drop-downs are directly bound as properties of the so-called backing component, the concrete UIComponent instance behind the composite component. And, both <f:selectItems> options obtain their values directly from the backing component as well. Here’s the backing component class, com.example.project.composite.InputLocalTime.

@FacesComponent("inputLocalTime")
public class InputLocalTime extends UIInput implements NamingContainer {


    private static final List<String> HOURS =
        IntStream.rangeClosed(0, 23).boxed()
            .map(InputLocalTime::pad).collect(Collectors.toList());
    private static final List<String> MINUTES =
        IntStream.rangeClosed(0, 59).boxed()
            .map(InputLocalTime::pad).collect(Collectors.toList());


    private UIInput hour;
    private UIInput minute;


    @Override
    public String getFamily() {
        return UINamingContainer.COMPONENT_FAMILY;
    }


    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        LocalTime localTime = (LocalTime) getValue();


        if (localTime != null) {
            hour.setValue(pad(localTime.getHour()));
            minute.setValue(pad(localTime.getMinute()));
        }


        super.encodeBegin(context);
    }


    @Override
    public Object getSubmittedValue() {
        String submittedHour = (String) hour.getSubmittedValue();
        String submittedMinute = (String) minute.getSubmittedValue();


        if (submittedHour == null || submittedMinute == null) {
            return null;
        }
        else if (submittedHour.isEmpty() || submittedMinute.isEmpty()) {
            return "";
        }
        else {
            return submittedHour + ":" + submittedMinute;
        }
    }


    @Override
    protected Object getConvertedValue
        (FacesContext context, Object submittedValue)
    {
        String submittedTime = (String) submittedValue;


        if (submittedTime == null || submittedTime.isEmpty()) {
            return null;
        }


        try {
            return LocalTime.parse(submittedTime,
                DateTimeFormatter.ISO_LOCAL_TIME);
        }
        catch (DateTimeParseException e) {
            throw new ConverterException(e);
        }
    }


    private static String pad(Integer value) {
        return String.format("%02d", value);
    }


    public UIInput getHour() { return hour; }
    public void setHour(UIInput hour) { this.hour = hour; }
    public UIInput getMinute() { return minute; }
       public void setMinute(UIInput minute) { this.minute = minute; }
    public List<String> getHours() { return HOURS; }
    public List<String> getMinutes() { return MINUTES; }
}

Now, that was a bit of code. Not only will you see that the getters and setters are collapsed for brevity, but you’ll also see that our composite extends UIInput and implements NamingContainer. Extending from UIInput gives us the benefit that we don’t need to repeat most of the default encoding and decoding behavior of UIInput in our backing component, so we only need to override a few methods. Implementing NamingContainer is a technical requirement of <cc:interface>. This enables you to use multiple instances of the composite component in the same context without facing “duplicate component ID” errors. This requirement is also reflected by the overridden getFamily() method, which must as per the composite component’s contract return the UINamingContainer.COMPONENT_FAMILY constant.

The actual UIInput components composing the composite component are declared as properties of the backing component. In this case they are both <h:selectOneMenu> drop-downs which are, via the binding attribute, tied to those properties. This enables us to easily set their values during encoding (read: processing the HTTP response), and to obtain the submitted values during decoding (read: processing the HTTP request). You can find the logic for that in the overridden encodeBegin() and getSubmittedValue() methods, respectively.

In the encodeBegin() method you thus have the opportunity to prepare the displayed values based on the model value, if any. The getValue() method is inherited from the UIInput superclass and is tied to the value attribute. You can break down the model value and set the desired values in the individual UIInput components of the composite component. The pad() helper method just pads the digit with a leading zero so that, e.g., the “1” gets displayed as “01”. This helper method is also used during static initialization of the lists of available hours and minutes specifically for <f:selectItems>.

In the getSubmittedValue() method you should compose the submitted values of the individual UIInput components together to a single String. In the specific case of <t:inputLocalTime>, we compose a String following the ISO local time pattern HH:mm. In turn, the UIInput superclass passes this value through the getConvertedValue() wherein we thus have the opportunity to convert the composed String to the concrete model value, which is in our case the LocalTime. Ultimately the UIInput superclass will make sure that this gets set in the backing bean during the update model values phase. Now you can use it as follows:

<ui:composition template="/WEB-INF/templates/layout.xhtml"
    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"
    xmlns:cc="http://xmlns.jcp.org/jsf/composite/components"
>
    <ui:define name="content">
        <h:form>
            <h:outputLabel for="time:hour" value="Time" />
            <t:inputLocalTime id="time" value="#{bean.time}" />
            <h:commandButton value="Submit" action="#{bean.submit}">
                <f:ajax execute="@form" />
            </h:commandButton>
        </h:form>
    </ui:define>
</ui:composition>

where the backing bean represented by #{bean} looks as follows:

@Named @RequestScoped
public class Bean {


    private LocalTime time;

    public void submit() {
        System.out.println("Submitted local time: " + time);
    }


    public LocalTime getTime() {
        return time;
    }


    public void setTime(LocalTime time) {
        this.time = time;
    }
}

Might it happen that you need to nest <f:ajax> inside the composite component in order to run some Ajax during the change event of any of the individual drop-downs, then you can achieve that by adding <cc:clientBehavior> targeting both drop-downs as follows:

<cc:interface ...>
    ...
    <cc:clientBehavior name="change" default="true"
        targets="hour minute" event="change">
    </cc:clientBehavior>
</cc:interface>

The name attribute represents the event name which you should declare in template client in order to trigger it.

<t:inputLocalTime id="time" ...>
    <f:ajax event="change" execute="time" ... />
</t:inputLocalTime>

The default="true" indicates that this is the default event, which means that you could just omit it, as you could do with event="change" for existing input text and drop-down components, and with event="click" for existing check box and radio button components, and with event="action" for existing command components.

<t:inputLocalTime id="time" ...>
    <f:ajax execute="time" ... />
</t:inputLocalTime>

The targets attribute must define a space-separated collection of IDs of target UIInput components resembling the composite component on which you would like to trigger the Ajax event, and the event attribute must define the desired event name to be actually triggered on the target UIInput components. In other words, this does, under the hood, effectively the same as if the following is implemented in the composite component:

<h:selectOneMenu id="hour" ...>
    <f:ajax event="change" ... />
</h:selectOneMenu>
<h:selectOneMenu id="minute" ...>
    <f:ajax event="change" ... />
</h:selectOneMenu>

In this specific example, the event attribute coincidentally has just the same value as the name attribute. This is perhaps confusing at first, but it allows you to easily define a custom event name. For example, following is the code to use when you want to trigger an event solely on the change of the hour drop-down:

<cc:interface ...>
    ...
    <cc:clientBehavior name="hourChange"
        targets="hour" event="change">
    </cc:clientBehavior>
</cc:interface>

With this, the following Ajax listener will thus be fired only when the hour drop-down is changed and not when the minute drop-down is changed.

<t:inputLocalTime id="time" ...>
    <f:ajax event="hourChange" execute="time"
        listener="#{bean.hourChanged}">
    </f:ajax>
</t:inputLocalTime>

Note that execute="time" is consistently explicitly specified in the given examples. This is because the default of execute="@this" still does not, in the current JSF 2.3 version, work correctly within the context of the composite component implementation. JSF could have derived the target components from any <cc:clientBehavior default="true">, but it isn’t specified as such yet.

All in all, it must be said that composite components have been overhyped after they were first introduced in JSF 2.0. People started using them to “composite” whole templates, includes, decorations, and even multiple tags, without using any backing component. That is, the zero-configuration nature as compared to tag files is very attractive. Everything is declared in the composite component file itself via <cc:interface>. And they can be directly used in the template client just by following a convention without the need to configure it in some XML file.

The caveat is that composite components are, due to their internal design, relatively expensive during building and restoring the view as compared to plain include files, decorate files, and tag files, especially when deeply nested. The best practice is therefore to use them only if you actually need a backing component via <cc:interface componentType>. For any other case, just use an include, a decorate, or a tag file instead. In the previous section you may already have learned that tag files can be quite powerful with help of JSTL.

Recursive Composite Component

You can safely nest composite components in each other. However, when you nest the very same composite component recursively in itself, then it would fail with a stack overflow error when EL attempts to resolve the concrete composite component instance behind #{cc}.5

Imagine that you’ve got a recursive tree model which represents some sort of discussion thread, such as e-mail messages and all their replies, or blog comments and all their replies, whereby each reply can in turn have another set of replies. This can be represented as a single JPA entity as follows:

@Entity
public class Message {


    @Id @GeneratedValue(strategy=IDENTITY)
    private Long id;


    @Lob
    @Column(nullable = false)
    private @NotNull String text;


    @ManyToOne
    private Message replyTo;


    @OneToMany(mappedBy = "replyTo")
    private List<Message> replies = Collections.emptyList();


    // Add/generate remaining getters and setters.
}

Note that the replyTo property represents the parent message which the current message is a reply to, and that the replies property represents all replies to the current message. The tree structure can then be queried as follows in a MessageService:

public List<Message> tree() {
    return entityManager.createQuery(
        "SELECT DISTINCT m FROM Message m"
            + " LEFT JOIN FETCH m.replies r"
            + " ORDER BY m.id ASC", Message.class)
        .getResultList().stream()
        .filter(m -> m.getReplyTo() == null)
        .collect(toList());
}

Note that the filtering of the result list afterward is at first glance inefficient, but in reality every single message is retrieved only once and simply referenced in the replies property.

Now, you’d intuitively implement the <t:message> composite component as something like the following:

<cc:interface>
    <cc:attribute name="value" type="com.example.Message" />
</cc:interface>
<cc:implementation>
    #{cc.attrs.value.text}
    <c:if test="#{not empty cc.attrs.value.replies}">
        <ul>
            <c:forEach items="#{cc.attrs.value.replies}" var="reply">
                <li>
                    <t:message value="#{reply}" />
                </li>
            </c:forEach>
        </ul>
    </c:if>
</cc:implementation>

which is in turn used as follows:

<c:forEach items="#{messages.tree}" var="message">
    <t:message value="#{message}" />
</c:forEach>

You’ll perhaps only wonder why <c:forEach> is being used instead of <ui:repeat>. The explanation is relatively simple: <ui:repeat> is ignored during view build time. In other words, <t:message> would include itself in an infinite loop. If you need to remember the why and how, head back to the section “JSTL Core Tags” in Chapter 3.

But even with the above implementation you would still run into an infinite loop. You know that #{cc} references the current instance of the composite component. Under the hood, when #{reply} is passed to the nested composite, then in reality a reference to #{cc.attrs.value.replies[index]} is being passed. This is, on its own, no problem. But when the nested composite in turn evaluates the #{cc} part from this alias, then it would reference itself instead of the parent composite. Hence, the infinite loop.

Theoretically, you could solve this by replacing #{cc} with #{cc.parent} which returns UIComponent#getParent().

<c:forEach items="#{cc.attrs.value.replies}" varStatus="loop">
    ...
    <t:message value="#{cc.parent.attrs.value.replies[loop.index]}" />
    ...
</c:forEach>

However, it still doesn’t work. Under the hood, inside the nested composite, when the EL evaluator comes to #{cc.parent} and attempts to evaluate “attrs.value” on it, then the parent composite component would return yet another EL expression in form of #{cc.attrs.value} which ultimately gets evaluated. However, the #{cc} part still gets interpreted as “current composite component,” which is inside the nested composite component and thus the nested composite itself.

We could only solve it to let the parent composite component not return yet another EL expression but instead the already-evaluated value. This can be achieved by overriding UIComponent#setValueExpression() in the backing component where you check whether the ValueExpression representing #{cc.attrs.value} is about to be set on the component and then immediately evaluate it and store the result as a local variable of the composite component. This shouldn’t cause harm as it’s supposed to be a read-only attribute.

@FacesComponent("messageComposite")
public class MessageComposite extends UINamingContainer {


    private Message message;

    @Override
    public void setValueExpression
        (String attributeName, ValueExpression expression)
    {
        if ("value".equals(attributeName)) {
            ELContext elContext = getFacesContext().getELContext();
            message = (Message) expression.getValue(elContext);
        }
        else {
            super.setValueExpression(attributeName, expression);
        }
    }


    public Message getMessage() {
        return message;
    }
}

With this backing component in place, and replacing “attrs.value” by “message”, it finally works.

<cc:interface componentType="messageComposite">
    <cc:attribute name="value" type="com.example.Message" />
</cc:interface>
<cc:implementation>
    #{cc.message.text}
    <c:if test="#{not empty cc.message.replies}">
        <ul>
            <c:forEach items="#{cc.message.replies}" varStatus="loop">
                <li>
                    <t:message
                        value="#{cc.parent.message.replies[loop.index]}">
                    </t:message>
                </li>
            </c:forEach>
        </ul>
    </c:if>
</cc:implementation>

Implicit EL Objects

In Facelets files a bunch of implicit EL objects available. They are mainly shortcuts to important artifacts, scopes, maps, and components available in the current faces context. Table 7-1 provides an overview of them.

Table 7-1 Implicit EL Objects Available in EL Context of JSF

Implicit EL object

Resolves to

Returns

Since

#{facesContext}

FacesContext#getCurrentInstance()

FacesContext

2.0

#{externalContext}

FacesContext#getExternalContext()

ExternalContext

2.3

#{view}

FacesContext#getViewRoot()

UIViewRoot

2.0

#{component}

UIComponent#getCurrentComponent()

UIComponent

2.0

#{cc}

UIComponent#getCurrentCompositeComponent()

UIComponent

2.0

#{request}

ExternalContext#getRequest()

HttpServletRequest

1.0

#{session}

ExternalContext#getSession()

HttpSession

1.0

#{application}

ExternalContext#getContext()

ServletContext

1.0

#{flash}

ExternalContext#getFlash()

Flash

2.0

#{requestScope}

ExternalContext#getRequestMap()

Map<String, Object>

1.0

#{viewScope}

UIViewRoot#getViewMap()

Map<String, Object>

2.0

#{flowScope}

FlowHandler#getCurrentFlowScope()

Map<Object, Object>

2.2

#{sessionScope}

ExternalContext#getSessionMap()

Map<String, Object>

1.0

#{applicationScope}

ExternalContext#getApplicationMap()

Map<String, Object>

1.0

#{initParam}

ExternalContext#getInitParameterMap()

Map<String, String>

1.0

#{param}

ExternalContext#getRequestParameterMap()

Map<String, String>

1.0

#{paramValues}

ExternalContext#getRequestParameterValuesMap()

Map<String, String[]>

1.0

#{header}

ExternalContext#getRequestHeaderMap()

Map<String, String>

1.0

#{headerValues}

ExternalContext#getRequestHeaderValuesMap()

Map<String, String[]>

1.0

#{cookie}

ExternalContext#getRequestCookieMap()

Map<String, Cookie>

1.0

#{resource}

ResourceHandler#createResource()

Resource

2.0

For the JSF artifacts and components, if the class in turn specifies a getter method somewhere, such as HttpServletRequest#getContextPath(), then you can of course access it in EL the usual way as in #{request.contextPath}.

For scoped maps, any property will be interpreted as the map key. If the property happens to contain period characters, then you can use the brace notation as in #{map['key.with.periods']} in order to access the map value. Note that #{flash} essentially extends from Map<String, Object>, so it could be treated as such. It should also be said that #{flowScope} indeed deviates from other scoped maps by accepting Object instead of String as a map key. This is most likely a historical mistake. The canonical approach to access scoped maps is to use a String-based key.

#{cookie} is mapped by the cookie name and the value actually returns a javax.servlet.http.Cookie which in turn has a getValue() property. So, in order to access the JSESSIONID cookie, you basically need #{cookie.JSESSIONID.value}. Of course, you can also just use #{session.id} instead.

#{resource} actually has its own EL resolver which interprets any property as a resource identifier in “library:name” format and then passes it to ResourceHandler#createResource() and finally returns the URL of the resource via Resource#getRequestPath(). This is very useful in CSS resources in order to reference a JSF image resource as a CSS background image. The following example will actually render the URL of src/main/webapp/resources/images/background.svg.

body {
    background-image: url("#{resource['images/background.svg']}");
    background-size: cover;
}

Note that resolving EL expressions in CSS resources only works when the CSS resource itself is included via <h:outputStylesheet> instead of <link>. Also noted should be that JSF remembers by default only on the very first request of the CSS resource whether it contains EL expressions or not. If it didn’t, then JSF won’t recheck it on a later request, even not in the development stage. So if you notice that your first EL expression in an existing CSS resource doesn’t seem to work, you’d better restart the web application. This feature of EL resolving in CSS resources is actually pretty useful. If SCSS (Sassy CSS) is a step too far for you, then you could use EL to parameterize some repeated CSS properties, such as colors.

.color-gray {
    color: #{applicationScope['gray']='#B8B8B8'};
}


...

.someSelector {
    border: 1px solid #{gray};
}
.otherSelector {
    color: #{gray};
}


...

No, this feature of EL resolving in CSS resources isn’t available in JS resources. For that, you’d instead need to print a JS object in the global scope and let your JS resources intercept it if necessary. For example,

<h:outputScript>var config = #{configuration.script};</h:outputScript>
<h:outputScript name="scripts/some.js" />

whereby the #{configuration.script} just returns a JSON object as string from your managed bean. Or, you could let EL print it as a data attribute of an HTML element

<html lang="en" data-baseuri="#{request.contextPath}/">
    ...
</html>

which is in turn accessible in JS as follows:

var baseuri = document.documentElement.dataset.baseuri;

or if you’re a jQuery fan:

var baseuri = $   ("html").data("baseuri");

That said, when creating managed beans on the Java side, or when declaring custom EL variables on the Facelets side, such as <h:dataTable var="foo">, <ui:repeat var="foo">, or <c:set var="foo">, you need to make absolutely sure that you don’t explicitly or implicitly choose a managed bean name or EL variable name which clashes with one of the previously listed implicit EL objects, because implicit EL objects have higher precedence in EL resolving than user defined names. So, for example, the following construct wouldn’t work as you might expect:

<ui:repeat value="#{bean.parameters}" var="param">
    #{param}<br />
</ui:repeat>

It would print literally “{}” for each iteration round, which is basically the default Map#toString() format of an empty Map. When you reopen the same page with a query string like ?foo=bar, then it would print literally “{foo=bar}” for each iteration round. You’d better rename the var="param" to something else then.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.228.19