Your First Cup: An Introduction to the Java EE Platform

Creating the Facelets Client

The Facelets client consists of a resource library, a composite component, and two XHTML files.

Resource Libraries in firstcup

A JavaServer Faces resource library is a collection of user-created components collected in a standard location in a web application. Resource libraries are identified according to a resource identifier, a string that represents a particular resource within a web application. Resources can be packaged either at the root of the web application or on the web application's classpath.

A resource packaged in the web application root must be in a subdirectory of a resources directory at the web application root.

resources/resource identifier

A resource packaged in the web application classpath must be in a subdirectory of the META-INF/resources directory within a web application.

META-INF/resources/resource identifier

Resource identifiers are unique strings that conform to the following format:

[localePrefix/][libraryName/][libraryVersion/]resource name[/resourceVersion]

Elements of the resource identifier in brackets ([]) are optional. A resource name, identifying a particular resource (a file or a graphic, for example), is required. In firstcup, a resource library with the name components is packaged in the web application root, and this library contains one resource, a file called inputDate.xhtml. The resource identifier for this resource is therefore components/inputDate.xhtml, and it is located in the web application root at resources/components/inputDate.xhtml.

The inputDate Composite Component

A composite component is a set of user-defined JavaServerFaces and Facelets components located in a resource. In firstcup, the inputDate.xhtml resource, located in the components resource library is a composite component that contains tags for reading in a date the user enters in a form. Composite components consist of an interface definition and an implementation.

The interface definition is specified with the <composite:interface> tag to define which attributes are exposed to pages that use the composite component. Attributes are identified with the <composite:attribute> tag.


Example 3–2 inputDate Composite Component Interface Definition

The inputDate.xhtml interface definition is as follows. It defines a single attribute, date, that must be specified in pages that use the inputDate composite component.

<composite:interface>
    <composite:attribute name="date" required="true" />
</composite:interface>

The implementation of the composite component is specified with the <composite:implementation> tag. The tags within the <composite:implementation> are the actual component tags that will be added to pages that use the composite component. They can be any HTML Render Kit, JavaServer Faces, or Facelets tags. The #{cc.attrs.attribute name} expression is used to get the value of the specified attribute from the page or component that is using the composite component.


Example 3–3 The inputDate Composite Component Implementation

The implementation of the inputDate composite component is as follows. An HTML input text component will store the entered text into the date attribute, accessed by the #{cc.attrs.date} expression. A JavaServer Faces convertDateTime component will convert the entered text to a date with the form of MM/dd/yyyy (04/13/2009, for example).

<composite:implementation>
    <h:inputText value="#{cc.attrs.date}">
        <f:convertDateTime pattern="MM/dd/yyyy" />
    </h:inputText>
</composite:implementation>

ProcedureCreating the inputDate Composite Component

Create the inputDate composite component as a resource in the components resource library.

  1. In the firstcup project, select File -> New File.

  2. Select JavaServer Faces under Categories, JSF Composite Component under File Types, and click Next.

  3. In the New JSF Composite Component dialog, enter inputDate under File Name, components under Folder, and click Finish.

  4. Add the composite component interface definition between the <body> and </body> tags in inputDate.xhtml:

    	<composite:interface>
    		<composite:attribute name="date" required="true" />
    	</composite:interface>
  5. Add the composite component implementation below the interface definition:

    	<composite:implementation>
    		<h:inputText value="#{cc.attrs.date}">
    			<f:convertDateTime pattern="MM/dd/yyyy" />
    		</h:inputText>
    	</composite:implementation>
  6. Right-click in the editor window and select Format.

  7. Select File -> Save.

The Facelets Web Interface

The firstcup web application interface has two XHTML files. The greeting.xhtml file displays Duke's current age and the form to the user for her to enter her birthday. The response.xhtml file displays the age difference between the user and Duke.

The greeting.xhtml contains several pieces of the firstcup application detailed previously. It uses the localized strings contained in WebMessages.properties and WebMessages_es.properties. It uses the DukesBDay managed bean to call both the DukesAgeResource JAX-RS web service and the DukesBirthdayBean enterprise bean. It uses the inputDate composite component to create the input for the user to enter her birthday.


Example 3–4 The greeting.xhtml File

Here's the content of the greeting.xhtml file.

<?xml version="1.0" encoding="UTF-8"?>
<!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" xml:lang="en" lang="en"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:fc="http://java.sun.com/jsf/composite/components">
<head>
    <title>Firstcup Greeting Page</title>
</head>
<body>
<h:form>
    <h2>
        <h:outputText value="#{bundle.Welcome}"/>
    </h2>
    <h:outputText value="#{bundle.DukeIs} "/>
    <h:outputText value="#{DukesBDay.age} #{bundle.YearsOldToday}"/>
    <p/>
    <h:outputText value="#{bundle.Instructions}"/>
    <p/>
    <h:outputText value="#{bundle.YourBD} "/>
    <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" />
    <h:outputText value=" #{bundle.Pattern}"/>
    <p/>
    <h:commandButton value="#{bundle.Submit}" action="response"/>
    <p/>
    <h:message for="userBirthday" style="color:red"/>
</h:form>
</body>
</html>

The greeting.xhtml file uses the JSF Core, HTML Render Kit, and the components resource library tag libraries. The components tag library has a prefix of fc, and is used to specify the inputDate composite component in the form below. The <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" /> tag has the required date attribute, and stores the value in the yourBD property in the DukesBDay managed bean by using the EL expression #{DukesBDay.yourBD}.

The localized strings are referred to by using the EL expressions #{bundle.property name}. For example, the <h:outputText value="#{bundle.Welcome}"/> tag will display the following string in English locales:


Hi. I'm Duke. Let's find out who's older -- You or I.

The <h:commandButton value="#{bundle.Submit}" action="response"/> tag creates a submit button and specifies that a successful submission should render the response.xhtml file by setting the action attribute to response. The action attribute is used to define navigation rules for forms in Facelets pages.

If the form submission is unsuccessful, a warning message is displayed. This is done with the <h:message for="userBirthday" style="color:red"/> tag, which is connected to the inputDate composite component with the id userBirthday. That is, if there's an error with the input of the inputDate component, a warning message is displayed.


The response.xhtml displays the age difference between the user and Duke. Different strings are displayed based on whether the user is the same age, younger, or older than duke. The text can be displayed or not based on the conditions specified by the rendered attribute of the <h:outputText> tag. The conditions used in the rendered attribute are EL language alternatives to the Java programming language conditional operators to allow XML parsing of the XHTML file.

Table 3–1 Conditional Operator EL Language Alternatives

Logical Condition 

Java Programming Language Conditional Operator 

EL Language Alternative 

AND 

&&

&&

EQUALS 

==

==

LESS THAN 

<

lt

GREATER THAN 

>

gt


Example 3–5 The response.xhtml File

<?xml version="1.0" encoding="UTF-8"?>
<!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" xml:lang="en" lang="en"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<head>
    <title>Response Page</title>
</head>
<body>
<h:form>
    <h:outputText value="#{bundle.YouAre} "/>
    <h:outputText value="#{bundle.SameAge}"
                  rendered="#{DukesBDay.ageDiff == 0}"/>
    <h:outputText value="#{DukesBDay.absAgeDiff}"
                  rendered="#{DukesBDay.ageDiff lt 0}"/>
    <h:outputText value=" #{bundle.Year} "
                  rendered="#{DukesBDay.ageDiff == -1}"/>
    <h:outputText value=" #{bundle.Years} "
                  rendered="#{DukesBDay.ageDiff lt -1}"/>
    <h:outputText value="#{bundle.Younger}"
                  rendered="#{DukesBDay.ageDiff lt 0}"/>
    <h:outputText value="#{DukesBDay.absAgeDiff}"
                  rendered="#{DukesBDay.ageDiff gt 0}"/>
    <h:outputText value=" #{bundle.Year} "
                  rendered="#{DukesBDay.ageDiff == 1}"/>
    <h:outputText value=" #{bundle.Years} "
                  rendered="#{DukesBDay.ageDiff gt 1}"/>
    <h:outputText value="#{bundle.Older}" rendered="#{DukesBDay.ageDiff gt 0}"/>    <p/>
    <h:commandButton id="back" value="#{bundle.Back}" action="greeting"/>
</h:form>
</body>
</html>

For example, the #{bundle.SameAge} string is displayed if the user and Duke have the same birthday as specified by the condition #{DukesBDay.ageDiff == 0} in the rendered attribute. That is, display the following string if the ageDiff property of DukesBDay equals 0:


You are the same age as Duke!

The form also contains a <h:commandButton> tag that creates a back button that will direct the user back to the greeting.xhtml page, as specified in the action attribute.

ProcedureCreating the XHTML Files

Create the Facelets XHTML files in NetBeans IDE.

  1. In the firstcup project select Web Pages in the left pane in NetBeans IDE.

  2. Select File -> New File.

  3. Select Java Server Faces under Categories, New JSF Page under File Types, and click Next.

  4. Enter greeting under File Name and click Finish.

  5. Repeat the previous steps to create a new Facelets Simple File named response.

ProcedureSet the Welcome File in the web.xml Deployment Descriptor

Configure the application to use greeting.xhtml as the welcome file by modifying web.xml

  1. In the firstcup project under Configuration Files double-click web.xml.

  2. Click Pages.

  3. Click Browse under Welcome Files, expand Web Pages, select greeting.xhtml, and click Select File.

  4. Select File -> Save.

ProcedureAdding Tag Libraries to the XHTML Files

Modify greeting.xhtml to include the components tag library.

  1. In the firstcup project open greeting.xhtml by double-clicking the file name under Web Pages in the left pane.

  2. Add the components tag library to the <html> tag.

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:fc="http://java.sun.com/jsf/composite/components">

    The components resource library is referred to by the fc prefix. The JSF Core and HTML Render Kit tag libraries are also used in greeting.xhtml.

  3. Add a title directly after the <html> tag.

    <head>
        <title>Firstcup Greeting Page</title>
    </head>
  4. Select File -> Save.

  5. Open response.xhtml and add the following title:

    <head>
        <title>Response Page</title>
    </head>
  6. Select File -> Save.

ProcedureAdding the Form to greeting.xhtml

Add the form that provides the user interface for displaying Duke's age and entering the user's birthday.

  1. In the firstcup project in greeting.xhtml add the following tags between the <body> and </body> tags.

    <h:form>
        <h2>
            <h:outputText value="#{bundle.Welcome}"/>
        </h2>
        <h:outputText value="#{bundle.DukeIs} "/>
        <h:outputText value="#{DukesBDay.age} #{bundle.YearsOldToday}"/>
        <p/>
        <h:outputText value="#{bundle.Instructions}"/>
        <p/>
        <h:outputText value="#{bundle.YourBD} "/>
        <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" />
        <h:outputText value=" #{bundle.Pattern}"/>
        <p/>
        <h:commandButton value="#{bundle.Submit}" action="#{DukesBDay.processBirthday}"/>
        <p/>
        <h:message for="userBirthday" style="color:red"/>
    </h:form>
  2. Right-click in the editor window and select Format.

  3. Select File -> Save.

ProcedureAdding the Form to response.html

Add a form that displays the age difference between Duke and the user, displays the average age difference of all users, and allows the user to navigate back to greeting.xhtml.

  1. In the firstcup project in response.xhtml add the following tags between the <body> and </body> tags.

    <h:form>
        <h:outputText value="#{bundle.YouAre} "/>
        <h:outputText value="#{bundle.SameAge}"
                      rendered="#{DukesBDay.ageDiff == 0}"/>
        <h:outputText value="#{DukesBDay.absAgeDiff}"
                      rendered="#{DukesBDay.ageDiff lt 0}"/>
        <h:outputText value=" #{bundle.Year} "
                      rendered="#{DukesBDay.ageDiff == -1}"/>
        <h:outputText value=" #{bundle.Years} "
                      rendered="#{DukesBDay.ageDiff lt -1}"/>
        <h:outputText value="#{bundle.Younger}"
                      rendered="#{DukesBDay.ageDiff lt 0}"/>
        <h:outputText value="#{DukesBDay.absAgeDiff}"
                      rendered="#{DukesBDay.ageDiff gt 0}"/>
        <h:outputText value=" #{bundle.Year} "
                      rendered="#{DukesBDay.ageDiff == 1}"/>
        <h:outputText value=" #{bundle.Years} "
                      rendered="#{DukesBDay.ageDiff gt 1}"/>
        <h:outputText value="#{bundle.Older}" rendered="#{DukesBDay.ageDiff gt 0}"/>
        <p/>
        <h:outputText value="#{bundle.AverageAge}": #{DukesBday.averageAgeDifference}" />
        <p/>
        <h:commandButton id="back" value="#{bundle.Back}" action="greeting"/>
    </h:form>
  2. Right-click in the editor window and select Format.

  3. Select File -> Save.

ProcedureSetting the Navigation for firstcup

Add a navigation rule to faces-config.xml that forwards the user to response.xhtml when the returned status of the DukeBDay.processBirthday method is success.

  1. With the firstcup project selected in the Projects pane, expand Configuration File and double-click faces-config.xml.

  2. Click PageFlow in the top left corner of the editor pane to display the visual navigation editor.

  3. Select greeting.xhtml click and hold the navigation arrow box on the far right, and drag a navigation arrow to the response.xhtml file.

  4. Double-click the default case1 outcome associated with the navigation arrow and change it to success.

  5. Select File -> Save.