© Luciano Manelli and Giulio Zambon 2020
L. Manelli, G. ZambonBeginning Jakarta EE Web Developmenthttps://doi.org/10.1007/978-1-4842-5866-8_8

8. JavaServer Faces 2.3

Luciano Manelli1  and Giulio Zambon2
(1)
Taranto, Italy
(2)
Harrison, ACT, Australia
 
In this chapter, I’ll introduce you to JSF and show you how to use it to create user interfaces for web-based applications. Within the MVC application architecture I described in Chapter 3 (refer to Figure 3-2), JSF takes the place of the controller, thereby mediating every interaction between JSP (the View) and the Model, which encapsulates the application data. JSF makes the development of web applications easier by
  • Letting you create user interfaces from a set of standard UI components wired to server-side objects

  • Making available four custom-tag libraries to handle those UI components

  • Providing a mechanism for extending the standard UI components

JSF transparently saves state information of the UI components and repopulates forms when they redisplay. This is possible because the states of the components live beyond the lifespan of HTTP requests. JSF operates by providing a controller servlet and a component model that includes event handling, server-side validation, data conversion, and component rendering. Not surprisingly, JSF doesn’t change the basic page life cycle that you already know from JSP: the client makes an HTTP request, and the server replies with a dynamically generated HTML page.

Be warned that JSF isn’t very easy to use, and it requires a non-negligible initial effort to get it going. However, the reward comes once you’ve familiarized yourself with JSF and can then develop user interfaces more quickly and efficiently.

You can download the latest JSF specification (JSR 372—JSF 2.3) by going to www.jcp.org/en/jsr/detail?id=372 and clicking the download page link.

JavaServer Faces may be built-in or not depending on the used server: Tomcat needs to manually install the JSF components. So, you have to download the latest version of JSF that is currently developed in two implementations of the specification: Mojarra and MyFaces. I chose the second one: you will find the latest version of Apache MyFaces JSF at http://myfaces.apache.org/download.html. In the zip file, you can find the following jar:
  • myfaces-impl-2.3.6.jar

  • myfaces-api-2.3.6.jar

  • commons-beanutils-1.9.4.jar

  • commons-collections-3.2.2.jar

  • commons-digester-1.8.jar

  • commons-logging-1.1.1.jar

To be able to use JSF, you will need to copy these jars (or a newer version) into the lib folder of your project or to Tomcat’s lib folder.

You also need JAXB libraries that give an efficient and standard way of mapping between XML and Java code. Go to https://eclipse-ee4j.github.io/jaxb-ri/, download the library jakarta.xml.bind-api.jar, and copy it into your lib project folder or Tomcat server.

Let’s begin with a simple JSF application, so that you can see how JSF works in practice.

The simplef Application

You should start by importing in Eclipse the project named simplef you will find in the software package for this chapter. You can try it out by typing http://localhost:8080/simplef/ in your web browser. Figure 8-1 is an example of what you’ll see.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig1_HTML.jpg
Figure 8-1

The first page of simplef

As you can see, there isn’t much to it. If you type, say, “qwerty” and click Submit, you will see the page shown in Figure 8-2.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig2_HTML.jpg
Figure 8-2

The second page of simplef

Apart from the URL, which is not what you might expect, everything is pretty boring. If you click Another, you go back to the first page, as shown in Figure 8-3.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig3_HTML.jpg
Figure 8-3

Back to the first page of simplef

Again, nothing to get excited about. But notice that the string you typed in the first page appeared in the second one and again in the first one as the default for the input field. What is exciting in this example is how easily this was accomplished with JSF. Listings 8-1 and 8-2 show the two JSP pages of the example.
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html><head><title>First Page</title></head><body>
<f:view>
  <h:form>
    <h:outputText value="Type something here: "/>
    <h:inputText value=" #{aStringBean.str} " />
    <h:commandButton action="goOn" value="Submit" />
    </h:form>
  </f:view>
</body></html>
Listing 8-1

first.jsp

<%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html><head><title>Second page</title></head><body>
<f:view>
  <h:form>
    <h:outputText value="& quot;#{aStringBean.str}& quot; "/>
    <h:commandButton action="goBack" value="Another" />
    </h:form>
</f:view>
</body></html>
Listing 8-2

second.jsp

The first two lines of both JSP pages load two JSF libraries, core and html, that contain all custom-tag definitions that implement JSF.

The first JSF element you encounter in both pages is f:view, which is a container for all JSF actions. The next one is h:form, the JSF element that generates the pair <form>..</form> of HTML tags. The three JSF elements h:outputText, h:inputText, and h:commandButton generate, respectively, the three HTML elements <span>..</span>, <input type="text"../>, and <input type="submit"../>. If you had used h:commandLink instead of h:commandButton, JSF would have generated a hyperlink with the HTML-tag a and the attribute href instead of a submit button.

Notice that the value attributes of h:inputText in first.jsp and h:outputText in second.jsp contain the EL expression #{aStringBean.str}. This is the first time you encounter a practical example of an EL expression representing an lvalue (see the Expression Language section in Chapter 6).

The expression ${aStringBean.str} would have been evaluated by Tomcat immediately. Tomcat would have replaced it with the value obtained by executing the method aStringBean.getStr() .

But, with the # replacing the $, the only thing that happens is that JSF assigns an identifier to the attribute str of the object aStringBean .

Listing 8-3 shows the HTML page that first.jsp generates (reformatted by me for easy reading).
<html><head><title>First Page</title></head><body>
<form id="j_id_jsp_445772234_1" name="j_id_jsp_445772234_1" method="post" action="/simplef/first.jsf;jsessionid=5A9800A3233E5F9410006529CEDD234F" enctype="application/x-www-form-urlencoded">
Type something here: <input id="j_id_jsp_445772234_1:j_id_jsp_445772234_3" name="j_id_jsp_445772234_1:j_id_jsp_445772234_3" type="text" value="" />
<input id="j_id_jsp_445772234_1:j_id_jsp_445772234_4" name="j_id_jsp_445772234_1:j_id_jsp_445772234_4" type="submit" value="Submit" />
<input type="hidden" name="j_id_jsp_445772234_1_SUBMIT" value="1" />
<input type="hidden" name="javax.faces.ViewState" id="j_id__v_0:javax.faces.ViewState:1" value="RDgzRTFGQzg4MkVCQTQ0NTAwMDAwMDAx" autocomplete="off" />
</form>
</body></html>
Listing 8-3

HTML Generated by first.jsp

Whenever you see id, the generated code actually contained j_id_jsp_445772234. The two lines in bold are the result of the three JSF elements h:outputText, h:inputText, and h:commandButton.

JSF assigned to #{aStringBean.str} the identifier j_id_jsp_445772234_1:j_id_jsp_445772234_3. When processing on the server the request your browser sends when you click Submit, JSF will assign the value you have typed (e.g., the string "qwerty") to the str attribute of the object aStringBean . By saving the string in this way, JSF will have it available for the value of h:outputText in second.jsp and as the default value for h:inputText in first.jsp when it will need to render that page again.

To continue the explanation of how JSF works, I would like to direct your attention to the fact that the URLs that appear in the browser do not match the names of the JSP pages. For example, you start the application by typing in your browser http://localhost:8080/simplef/. What trick then takes you to first.jsp? If you open the default JSP page index.jsp that you find inside the simplef folder, you will see the one-liner shown in Listing 8-4.
<html><body><jsp:forward page="/first.jsf"/></body></html>
Listing 8-4

index.jsp

But in the same folder, there is no file named first.jsf! To begin understanding what happens, you have to look at the web.xml file (see Listing 8-5).
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:="http://xmlns.jcp.org/xml/ns/javaee"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
  </servlet>
<servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
Listing 8-5

web.xml

It defines a servlet of type javax.faces.webapp.FacesServlet. It is the JSF servlet, which I have informally called “JSF”. It is that servlet that assigns IDs to attributes and transfers data between pages. web.xml also maps the extension jsf to the servlet, thereby forcing all requests for pages with extension jsf to be sent to it.

This reveals part of the mystery: when you type http://localhost:8080/simplef/ in your browser, Tomcat executes index.jsp, which forwards the request to first.jsf (which actually doesn’t exist). But, because of the servlet mapping in web.xml, Tomcat diverts your request to the JSF servlet.

The rest of the mystery is easily explained: JSF replaces the extension jsf with jsp, which means that the request can finally reach first.jsp. The extension jsp is the default, but you can replace it by inserting in the web-app element of web.xml an element like that shown in Listing 8-6.
<context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.jspx</param-value>
  </context-param>
Listing 8-6

Defining the JSF Default Suffix in web.xml

The next mystery that we have to solve is how the request generated by the form in first.jsp reaches second.jsp. In other words, how does the action "goOn" cause a request to reach second.jsp?

To solve this second mystery, you have to look at another file you find in WEB-INF: faces-config.xml (see Listing 8-7).
<?xml version="1.0" encoding="UTF-8"?>
<faces-config 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-facesconfig_2_3.xsd"
        version="2.3" >
  <managed-bean>
    <managed-bean-name>aStringBean</managed-bean-name>
    <managed-bean-class>AString</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
      <property-name>str</property-name>
      <property-class>java.lang.String</property-class>
      <null-value></null-value>
      </managed-property>
    </managed-bean>
  <navigation-rule>
    <from-view-id>/first.jsp</from-view-id>
    <navigation-case>
      <from-outcome>goOn</from-outcome>
      <to-view-id>/second.jsp</to-view-id>
      </navigation-case>
    </navigation-rule>
  <navigation-rule>
    <from-view-id>/second.jsp</from-view-id>
    <navigation-case>
      <from-outcome>goBack</from-outcome>
      <to-view-id>/first.jsp</to-view-id>
      </navigation-case>
    </navigation-rule>
  </faces-config>
Listing 8-7

faces-config.xml

Concentrate for the time being on the part I have highlighted. It tells JSF that when the page first.jsp ends with outcome goOn (i.e., executes h:commandButton with action goOn), control should go to second.jsp. In a more complex application, first.jsp would include different actions, which would correspond to different navigation-case elements. Then, the JSF servlet would have a function analogous to that of a Java switch statement.

We are almost there. The next thing that needs some explanation is the managed-bean element that you see in faces-config.xml immediately above the first navigation rule. It tells JSF to manage a session-scoped object named aStringBean of type AString, and to manage its attribute named str, which should be initialized to null. This also means that the JSF servlet will instantiate the object automatically.

This is where the name aStringBean you saw in the EL expressions of both first.jsp and second.jsp comes from. I could have chosen any name, but it is good practice to end the names of such managed beans with Bean.

Also, the default scope is request. But by specifying session, I ensured that the aStringBean is not destroyed after the first request. In the example, it would have meant that the input element in the second execution of first.jsp would have been without default. The request scope would have been sufficient to “remember” the default if first.jsp had executed itself instead of second.jsp. Note that you should be careful not to go overboard with storing information in the session, because you could affect the performance of your application. Remember that every new user causes a new session to be created.

The last piece that you need in order to complete the resolution of the JSF puzzle is the definition of the class AString . For this, see Listing 8-8.
import java.io.Serializable;
public class AString implements Serializable {
  String str;
  public String getStr() { return str; }
  public void setStr(String s) { str = s; }
  }
Listing 8-8

AString.java

For simplef to work, AString.class should be in the classes subdirectory of WEB-INF.

AString is the simplest possible bean that you need for JSF. The implementation of Serializable is there because it makes possible for Tomcat to save the object to disk and to retrieve it from disk. The server possibly uses a hard disk to park session data when it is under a heavy load or when it is restarted. This is one more reason for keeping the session’s size as contained as possible. Note that Tomcat can only save objects that it is able to convert to output streams of data, and that requires the objects to be serializable.

The simplefx Application

In the previous section, I showed you how to build a simple JSF application with JSP pages. To use JSF with JSP documents (i.e., in XML format), you only have to make minimal changes. To convert first.jsp (Listing 8-1) to first.jspx, you only need to make the standard changes described in the last section of Chapter 7 and replace the two JSF taglib actions with the corresponding namespace declarations, as shown in Listing 8-9. You can find in the software package for this chapter the project simplefx.
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
  xmlns:jsp="http://xmlns.jcp.org/JSP/Page"
  xmlns:f="http://xmlns.jcp.org/jsf/core"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  version="2.1"
  >
<jsp:directive.page
  language="java"
  contentType="application/xhtml+xml;charset=UTF-8"
  />
<jsp:output omit-xml-declaration="false"/>
<jsp:output
  doctype-root-element="html"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  />
<html xmlns:="http://www.w3.org/1999/xhtml">
<head><title>First Page</title></head>
<body>
<f:view>
  <h:form>
    <h:outputText value="Type something here: "/>
    <h:inputText value="#{aStringBean.str}"/>
    <h:commandButton action="goOn" value="Submit"/>
    </h:form>
  </f:view>
</body>
</html>
</jsp:root>
Listing 8-9

first.jspx

After converting second.jsp to second.jspx in the same way, you also need to insert into web.xml the context-param element shown in Listing 8-6; otherwise, JSF will keep looking for files with extension jsp. Finally, to complete the conversion to XML, you will need to make a global replace from jsp to jspx in faces-config.xml, so that the navigation rules will keep working.

Notice that we didn’t need to do any conversion inside the body elements of the JSP pages. This is because there were no scripting elements to convert. With JSTL, JSF, and other custom actions that you acquire or develop yourself, you can write JSP in XML format without much effort.

You saw that in faces-config.xml you need to specify to which document you want the control to move when you request a particular action from within a particular document. The navigation elements for the simplexf applications are those shown in Listing 8-10.
<navigation-rule>
  <from-view-id>/first.jspx</from-view-id>
  <navigation-case>
    <from-outcome>goOn</from-outcome>
    <to-view-id>/second.jspx</to-view-id>
    </navigation-case>
  </navigation-rule>
  <navigation-rule>
  <from-view-id>/second.jspx</from-view-id>
  <navigation-case>
    <from-outcome>goBack</from-outcome>
    <to-view-id>/first.jspx</to-view-id>
    </navigation-case>
  </navigation-rule>
Listing 8-10

Navigation Rules for simplexf

In particular, the first navigation rule tells JSF that when it executes the element <h:commandButton action="goOn" value="Submit"/> in first.jspx, it should transfer control to second.jspx (which JSF renames second.jsf so that a subsequent request from the user goes back to the JSF servlet).

The JSF Life Cycle

Now that you have seen an example of JSF, let’s have a closer look at how JSF does its job. For that, refer to Figure 8-4. Note that the figure only shows what JSF does when the user types valid values into the input fields of the page that sends the request. Read on for more details.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig4_HTML.jpg
Figure 8-4

The JSF life cycle

  1. 1.

    Restore View: The JSF servlet builds the view of the requested page as a component tree that contains the information associated with all components of the page. If the page is requested for the first time, JSF creates an empty view, wires event handlers and validators (if any) to its components, and saves it in a FacesContext object, before jumping directly to Render Response. By saving the view, JSF makes it possible to repopulate the page if necessary, for example, when the user doesn’t fill out a form as required. If the same page was displayed before and component states were saved, JSF uses that information to restore the page to its current state.

     
  2. 2.

    Apply Request Values: JSF goes through the component tree and executes each component’s decode method , which extracts values from the request parameters, or possibly from cookies or headers. It also automatically converts the parameters that are associated with object properties of nonstring types. Conversion errors cause error messages to be queued to the FacesContext object. In some cases, typically when the user clicks controls, the servlet also generates request events and queues them to FacesContext. For components that have the immediate event-handling property set to true, JSF also validates them and saves them in their component instances within FacesContext.

     
  3. 3.

    Process Validation: The servlet invokes the validate methods for all components of the validators that had been registered during Restore View. The validation rules are those you define or, by default, those predefined by JSF. For each validate method that returns false, the servlet marks the component as invalid and queues an error message to the FacesContext. At the end of this phase, if there are validation errors, JSF jumps directly to Render Response, so that error messages can be displayed to the user.

     
  4. 4.

    Update Model Values: During this phase, the values of the components are copied to the corresponding properties of the managed beans that are wired to them. JSF does it by executing the component method updateModel , which also performs type conversions when necessary. Conversion errors cause error messages to be queued to FacesContext.

     
  5. 5.

    Invoke Application: During this phase, the servlet processes the application-level events by executing the corresponding handlers. When the user submits a form or clicks a link of a JSF application, the JSF servlet generates a corresponding application-level event. One of the tasks you have to do when developing a JSF application is to assign a handler to each one of the possible application events. This is where you also specify what should happen next, by returning outcomes that you have linked to possible next pages, either with a navigation case or implicitly, as I showed you in the previous section.

     
  6. 6.

    Render Response: The servlet creates a response component tree and delegates the rendering of the page to Tomcat. Each component renders itself as Tomcat goes through the corresponding JSF tags. At the end of this phase, the state of the response is saved so that the servlet can access it during the Restore View phase of subsequent requests to the same page.

     

Event Handling

Before looking at an application, I need to spend a few words on the JSF mechanism to handle events, because you cannot really understand how JSF works unless you know a thing or two about event handling.

As an example, let’s see what role the event handling plays when a user clicks a Submit button . The JSF UI components used to represent button HTML elements are objects of type javax.faces.component.html.HtmlCommandButton, which is a class extending the more general javax.faces.component.UICommand. As with any other HTML page, by clicking the Submit button in a JSF application, the user triggers the sending to the server of an HTTP request that contains the ID of the button as a parameter name.

As I’ve already mentioned, during the Apply Request Values phase, JSF executes the decode method of each component of the page. First, the decode method scans the parameter names to see whether one matches the ID of the component the method belongs to. In our example, the decode method of the UICommand object associated with the button clicked by the user finds the component ID among the request parameters, precisely because the user clicked the button. As a result of finding its own ID, the component instantiates an event object of type javax.faces.event.ActionEvent and queues it up.

At this point, you have to distinguish between situations in which all the input fields of a form need to be validated and those in which only a partial validation is appropriate. For example, in an online shop such as the eshop application, the shopper must be able to add further books to the shopping cart even after reaching the checkout page, where the shopper is asked to provide payment information. To make that possible, you must ensure that the validation of the payment data is skipped if the user selects a book category or searches for new titles. If you allowed the validation of empty or partially filled payment fields to proceed, the application would report one or more errors and prevent the shopper from going back to look for new books.

You solve this issue by specifying that the handling of both the book search and the category selection be done during Apply Request Values while leaving the handling of the payment data to follow the normal life cycle. If it turns out that the user wants to shop for new books rather than complete the checkout, control then jumps directly to the Render Response phase, thereby skipping the intermediate phases where payment data would have been validated and processed.

In the next chapter, you will see in detail how this is done in the JSF version of eshop.

The JSF Tag Libraries

The first two sections of this chapter showed you examples of simple JSF applications that used a handful of elements: f:view, h:form, h:outputText, h:inputText, and h:commandButton. You will recall that the prefix h was associated with the HTML component library and the prefix f with the JSF core library. Besides those two libraries, JSF consists of two additional custom-tag libraries: facelets, normally associated with the prefix ui, and composite, with prefix composite.

In the rest of this chapter, I will briefly describe the four libraries and show you more examples. In the next chapter, I will describe how to use more of the tags by referring to a JSF version of the eshop application.

The html Library

As its name suggests, JSF’s HTML library collects the tags associated with rendering HTML components. As you have already seen in the examples (e.g., with h:inputText), you associate objects of your data model to the corresponding components by assigning value expressions that refer to the objects to specific attributes of the component tags (e.g., <h:inputText value="#{aStringBean.str}"/>).

Although in most cases the names of the tags should already tell you their purpose, I have summarized the correspondence between tags and HTML elements in Table 8-1.
Table 8-1

html Tags and HTML Elements

Tag Name

HTML Element

h:body

body

h:button

input type="button"

h:column

--

h:commandButton

input  type="submit"

h:commandLink

a

h:dataTable

table

h:doctype

<!DOCTYPE> declaration

h:form

form

h:graphicImage

img

h:head

head

h:inputHidden

input type="hidden"

h:inputSecret

input type="password"

h:inputText

input type="text"

h:inputTextarea

input type="textarea"

h:link

a

h:message

span or text

h:messages

span or text

h:outputFormat

span or text

h:outputLabel

label

h:outputLink

a

h:outputScript

script

h:outputStylesheet

link

h:outputText

span or text

h:panelGrid

table

h:panelGroup

div or span

h:selectBooleanCheckbox

input  type="checkbox"

h:selectManyCheckbox

multiple input  type="checkbox"

h:selectManyListbox

select and multiple option

h:selectManyMenu

select and multiple option

h:selectOneListbox

select and multiple option

h:selectOneMenu

select and multiple option

h:selectOneRadio

multiple input  type="radio"

The h:select* Elements

There are seven JSF HTML tags to render selections. To show how they differ from each other, I created in Eclipse the small project testf. You will find it in the testf project subfolder of the software package for this chapter. If you import testf.war in Eclipse, you will be able to try it out by typing http://localhost:8080/testf/ in your web browser. Figure 8-5 shows you what you will see in your browser after selecting values in the controls (and hitting the Submit button , although it is not necessary to do so).
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig5_HTML.jpg
Figure 8-5

The output of testf

Listing 8-11 shows the JSP document.
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
  xmlns:jsp="http://xmlns.jcp.org/JSP/Page"
  xmlns:f="http://xmlns.jcp.org/jsf/core"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  version="2.1"
  >
<jsp:directive.page
  language="java"
  contentType="application/xhtml+xml;charset=UTF-8"
  />
<jsp:output omit-xml-declaration="false"/>
<jsp:output
  doctype-root-element="html"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  />
<html xmlns:="http://www.w3.org/1999/xhtml">
<head><title>Test</title></head>
<body><f:view><h:form id="form">
  <h:panelGrid columns="2" border="1" cellpadding="5">
    <h:outputText value="h:selectBooleanCheckbox"/>
    <h:panelGroup>
      <h:selectBooleanCheckbox id="checkbox" value="#{myBean.oneValue}"/>
      <h:outputText value=" just a checkbox"/>
      </h:panelGroup>
    <h:outputText value="h:selectManyCheckbox"/>
    <h:selectManyCheckbox id="checkboxes" value="#{myBean.choices1}">
      <f:selectItems value="#{myBean.selects}"/>
      <f:selectItem itemLabel="everything" itemValue="42"/>
      </h:selectManyCheckbox>
    <h:outputText value="h:selectManyListbox"/>
    <h:selectManyListbox id="listboxes" value="#{myBean.choices2}">
      <f:selectItems value="#{myBean.selects}"/>
      <f:selectItem itemLabel="too much" itemValue="999"/>
      </h:selectManyListbox>
    <h:outputText value="h:selectManyMenu"/>
    <h:selectManyMenu id="menus" value="#{myBean.choices3}"
        style="min-height:48px">
      <f:selectItems value="#{myBean.selects}"/>
      <f:selectItem itemLabel="ninety-nine" itemValue="99"/>
      </h:selectManyMenu>
    <h:outputText value="h:selectOneListbox"/>
    <h:selectOneListbox id="listbox" value="#{myBean.choice1}">
      <f:selectItems value="#{myBean.selects}"/>
      <f:selectItem itemLabel="nine" itemValue="9"/>
      </h:selectOneListbox>
    <h:outputText value="h:selectOneMenu"/>
    <h:selectOneMenu id="menu" value="#{myBean.choice2}">
      <f:selectItem itemLabel="zero" itemValue="0"/>
      <f:selectItems value="#{myBean.selects}"/>
      </h:selectOneMenu>
    <h:outputText value="h:selectOneRadio"/>
    <h:selectOneRadio id="radio" value="#{myBean.choice3}">
      <f:selectItem itemLabel="nothing" itemValue="-1"/>
      <f:selectItems value="#{myBean.selects}"/>
      </h:selectOneRadio>
    </h:panelGrid>
    <h:commandButton value="Submit"/>
  </h:form></f:view></body>
</html>
</jsp:root>
Listing 8-11

index.jspx for the testf Project

I have highlighted in bold the selection components. h:selectBooleanCheckbox renders a single checkbox; h:selectManyCheckbox, h:selectManyListbox, and h:selectManyMenu render multiple selections; and h:selectOneListbox, h:selectOneMenu, and h:selectOneRadio render single selections.

In all cases in which you can select one or more of several items, I have included a hard-coded item in addition to a list of items provided by the managed bean through an attribute I chose to name selects:
<f:selectItems value="#{myBean.selects}"/>

The tags wire to each HTML control a different property of the managed bean. Notice the use of the core JSF tags f:selectItem and f:selectItems to provide the information needed for the options of the HTML select elements.

From this example, you can also see how to use h:panelGrid and h:panelGroup to render an HTML table. Differently from HTML, where you need to identify rows with tr elements and cells within rows with td elements, with h:panelGrid you specify at the beginning the number of columns, and all the components between its begin and end tags “flow” from left to right into the table. If you need more than one component within the same cell, you group them together with h:panelGroup.

Listing 8-12 shows the managed bean used to hold the items you select in the browser.
package myPkg;
import java.util.ArrayList;
import javax.faces.model.SelectItem;
public class MyBean {
  @SuppressWarnings("unchecked")
  private ArrayList<String>[] choices = new ArrayList[3];
  private String choice1, choice2, choice3;
  private Object oneValue;
  private SelectItem[] selects;
  public MyBean()  {
    selects = new SelectItem[3];
    selects[0] = new SelectItem("1", "one");
    selects[1] = new SelectItem("2", "two");
    selects[2] = new SelectItem("3", "three");
    for (int kC = 0; kC < choices.length; kC++) {
      choices[kC] = new ArrayList<String>();
      }
    }
  // ---------- Getters
  public Object[] getChoices1() { return choices[0].toArray(); }
  public Object[] getChoices2() { return choices[1].toArray(); }
  public Object[] getChoices3() { return choices[2].toArray(); }
  public String getChoice1() { return choice1; }
  public String getChoice2() { return choice2; }
  public String getChoice3() { return choice3; }
  public Object getOneValue() { return oneValue; }
  public SelectItem[] getSelects() { return selects; }
  // ---------- Setters
  public void setChoices(Object[] cc, int kC) {
            int len=0;
            if (cc != null) len = cc.length;
            if (len != 0) {
              choices[kC].clear();
              choices[kC] = new ArrayList<String>(len);
              for (int k = 0; k < len; k++) {
                choices[kC].add((String)cc[k]);
                }
              }
            }
  public void setChoices1(Object[] cc) { setChoices(cc, 0); }
  public void setChoices2(Object[] cc) { setChoices(cc, 1); }
  public void setChoices3(Object[] cc) { setChoices(cc, 2); }
  public void setChoice1(String c) { choice1 = c; }
  public void setChoice2(String c) { choice2 = c; }
  public void setChoice3(String c) { choice3 = c; }
  public void setOneValue(Object v) { oneValue = v; }
  }
Listing 8-12

myPkg.MyBean.java for the testf Project

There isn’t really much to explain. JSF takes care of executing the initialization method of the bean, which initializes three values to be provided for selection through the select attribute and sets up the arrays needed to save the user’s choices.

The core Library

JSF’s core library gives you access to APIs that are independent of a particular render kit:
  • Converters: Converters let you convert between the data types of the components and those of your application objects.

  • Listeners: You register a listener with a component to handle events that the component generates.

  • Events: After the listener is registered with a component, the FacesServlet fires the events by invoking an event notification method of the corresponding listener.

  • Validators: Validators examine the value of a component and ensure that it conforms to a set of predefined rules.

In the previous examples, you have already encountered f:view, f:selectItem, and f:selectItems. Most of the core tags perform operations on components. Table 8-2 provides the list of all core tags and the corresponding operations. In the table, I have highlighted in italics the few operations that do not apply to individual components.
Table 8-2

core Tags

Tag Name

Operation

f:actionListener

Adds an action listener

f:ajax

Registers an Ajax behavior for one or more components

f:attribute

Sets an attribute

f:convertDateTime

Adds a date-time converter

f:converter

Adds a converter

f:convertNumber

Adds a number converter

f:event

Adds a system-event listener

f:facet

Adds a facet

f:loadBundle

Loads a resource bundle into a Map

f:metadata

Declares the metadata facet for a view

f:param

Adds a parameter

f:phaseListener

Adds a phase listener to a view

f:selectItem

Specifies an item for :selectMany* and h:selectOne*

f:selectItems

Specifies items for :selectMany* and h:selectOne*

f:setPropertyActionListener

Adds an action listener that sets a property

f:subview

Container for all JSF actions on pages included via jsp:include or c:import

f:validateBean

Adds a bean validator

f:validateDoubleRange

Adds a double-range validator

f:validateLength

Adds a length validator

f:validateLongRange

Adds a long-range validator

f:validateRegex

Adds a validator against a regular expression

f:validateRequired

Adds a check that a value is present

f:validator

Adds a validator

f:valueChangeListener

Adds a value change listener

f:view

Container for all JSF actions of a page

f:viewAction

Specifies an application-specific action

f:viewParam

Adds a parameter to the metadata facet of a view

I expect that you will find many of the tags listed in Table 8-2 obscure. You will be able to understand most of them after the next sections and chapters, but the use of some of them definitely falls outside the scope of this book.

If you are curious about what a facet is, I can tell you that it is a named subcomponent specific to a particular component. For example, h:gridPanel (which renders an HTML table) supports the two facets header and footer. If you include <f:facet "header"><h:outputText value="Whatever"/></f:facet> anywhere within the body of h:gridPanel, the rendered table will have the header “Whatever”.

I will talk about converters and validators in the next chapter, where I will describe a JSF version of the eshopx project I introduced in Chapter 7. In this chapter, as an interesting example of core tags, I will describe how to use f:ajax. In order to do that, I will first tell you about Ajax in general and show you how it was used before the introduction of f:ajax.

Ajax

I introduced JavaScript in the previous chapter: Asynchronous JavaScript and XML (Ajax) is a mechanism for letting JavaScript communicate with the server asynchronously, that is, without reloading the page. This is possible by means of the JavaScript built in object XMLHttpRequest.

In practical terms, it works like this: you create an XMLHttpRequest object within JavaScript, use it to send a request to the server, get the response, and have fresh data for your web page without having to reload it. Well, it sounds easy, but it’s not obvious how to do it, and it’s even more tricky to maintain. To explain how to use Ajax, I’ll show you a simple example of a page that displays the server time. First, you need to write a JSP page to return the time (see Listing 8-13).
<%@page language="java" contentType="text/html"
  %><%@page import="java.util.*"
  %><% out.print(new GregorianCalendar().getTime()); %>
Listing 8-13

time.jsp

If you type the URL of this script in a browser, you’ll get something like this:
Sun May 03 12:57:53 CEST 2020

You’ll perhaps see some other time zone, but the format will be identical. A good place to check out the abbreviation for your time zone is www.timeanddate.com/time/zones/.

Now that you have a way of getting the server time, you can write the page to display it with Ajax, as shown in Listing 8-14.
<?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">
<head>
  <title>Example of Ajax</title>
  <script type="text/javascript" src="ajax.js"></script>
  </head>
<body>
  <form name="tForm" action="">
    <span>The time on the server is:</span>
    <input type="text" name="tElement" readonly="readonly" size="30"/>
    <input type="button" value="Update"
        onclick="ajaxFun('tForm', 'tElement');"
        />
    </form>
  </body>
</html>
Listing 8-14

ajax.xhtml

As you can see, I’ve highlighted two lines. The first is where you load the file ajax.js, which contains the JavaScript code to support the Ajax operation. The second line is where you execute the ajaxFun JavaScript function whenever you click the Update button. Notice that you pass to ajaxFun the names of the form and of the input element to be updated. You could have hard-coded the string "tForm.tElement" within JavaScript, but it would have been bad programming practice to use within ajax.js identifiers defined elsewhere. Global variables invariably lead to code that’s a nightmare to maintain and should be avoided whenever possible.

To complete this brief introduction to Ajax, I still need to show you the JavaScript code. However, before I do that, check out Figure 8-6 to see how the browser renders the page. To test the application, import the ajax project from the software package for this chapter into Eclipse. Then, type in your browser http://localhost:8080/ajax/.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig6_HTML.jpg
Figure 8-6

Server time with Ajax

Listing 8-15 shows the JavaScript code.
function ajaxFun(tf, te){
  var tElem = eval("document." + tf + "." + te)
  var ajaxReq;
  try { // Firefox, Opera, IE 9, Chrome
    ajaxReq = new XMLHttpRequest();
    }
  catch (e) { // older IEs
    try{
      ajaxReq = new ActiveXObject("Msxml2.XMLHTTP");
      }
    catch (e) {
      try{ // still older IEs
        ajaxReq = new ActiveXObject("Microsoft.XMLHTTP");
        }
      catch (e) {
        alert("Your browser does not support Ajax!");
        return false;
        }
      }
    }
  ajaxReq.open("GET", "time.jsp");
  ajaxReq.send(null);
  ajaxReq.onreadystatechange = function() {
    if(ajaxReq.readyState == 4) {
      tElem.value = ajaxReq.responseText;
      }
    }
  }
Listing 8-15

ajax.js

First, you instantiate an object of type XMLHttpRequest.

When ajaxReq “holds” an object of the correct type, you set up the HTML request method (e.g., GET) and the target URL (in this case, the JSP module time.jsp). At this point, you can send off the request.

The control comes immediately back to JavaScript (the first letter of Ajax stands for asynchronous). In general, you don’t want the browser to wait for the response, and you want your page to be able to do other things. This asynchronicity makes Ajax more useful than if its operations had to be done in sequence. When the state of the request changes, the browser executes the function ajaxReq.onreadystatechange. In that function, you need to check that the request has been completed: in which case, you can then display the content of the response in the time field. Cool! In case you are curious to know the possible status codes, check out Table 8-3.
Table 8-3

List of ajaxReq.readyState Codes

Code

Meaning

0

Uninitiated

1

Loading

2

Loaded

3

Processing

4

Complete

I’ve taken a minimalist approach for this example. The idea is for your server to send back an XML document, which you can then parse on the client side.

One last thing: Listing 8-16 shows the deployment descriptor for this application.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
  <display-name>Ajax example</display-name>
  <welcome-file-list>
    <welcome-file>index.xhtml</welcome-file>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>
Listing 8-16

web.xml

As you can see, it is almost empty. I have only added a couple of welcome-file elements so that Tomcat tries index.html (which is the default) only if index.xhtml is not there.

Now that you know how Ajax works without JSF, let’s see how to use f:ajax to achieve the same result.

f:ajax

Using f:ajax instead of the mechanism I described in the previous section has several advantages, the most important of which, in my opinion, is that you no longer need to write code in JavaScript, which adds another flavor of Java to the mix. Further, f:ajax is fully integrated with the other JSF libraries.

Figure 8-4 showed the six phases of the JSF life cycle. With f:ajax you can selectively execute components on the server by processing them through the first five phases or render them by passing them through the last phase. You ajaxify a component by enclosing it within the body of f:ajax or by passing to f:ajax the component id.

To convert the Ajax example of the previous section to JSF’s Ajax, let’s start from ajaxf.xhtml, shown in Listing 8-17. The interesting bits are those highlighted in bold.

To test the application, import the ajaxf project from the software package for this chapter into Eclipse. After deploying, type http://localhost:8080/ajaxf in your web browser.
<?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"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      >
<h:head><title>Example of Ajax with JSF</title></h:head>
<h:body>
  <h:form>
    <h:outputText value="The time on the server is: "/>
    <h:outputText id="timeField" value="#{serverTimeBean.when}"/>
    <h:outputText value=" "/>
    <h:commandButton value="Update">
      <f:ajax render="timeField"/>
      </h:commandButton>
    </h:form>
  </h:body>
</html>
Listing 8-17

ajaxf.xhtml

The first highlighted line simply displays the value of the property when of the managed bean serverTimeBean. It is almost identical to the line
<h:outputText value="&quot;#{aStringBean.str}&quot; "/>

of second.jsp (Listing 8-2) that you encountered at the very beginning of this chapter.

But this time, I have added to h:outputText the setting of the id attribute. This is because we need to pass it to f:ajax, in the second group of highlighted lines.

The h:commandButton element , contrary to what you saw in previous examples, doesn’t transfer control to another page. Its purpose is only to create an event that triggers f:ajax. Accordingly, the action attribute is not there, and if you look at the WEB-INF folder of the application, you will see that no faces-config.xml to handle navigation is present.

Every time the user clicks the Update button, f:ajax sends a request to the server to obtain the value of serverTimeBean.when, which then the h:outputText element with id timeField displays. You don’t need to write JavaScript because JSF automatically generates the little script that sends the Ajax request.

But you do need a Java bean like that shown in Listing 8-18.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ManagedProperty;
import java.util.GregorianCalendar;
public class ServerTime implements Serializable {
  String when;
  public ServerTime() { when = new GregorianCalendar().getTime().toString(); }
  public String getWhen() { return new GregorianCalendar().getTime().toString(); }
  public void setWhen(String w) { when = w; }
  }
Listing 8-18

ServerTime.java

The code is almost identical to that of AString.java (Listing 8-8), the major differences being that it has an initialization method and, obviously, generates a string with the current server time. In the software package, you will also find the files that complete the application, index.jsp and web.xml, but they are very similar to the equivalent files you already encountered with other applications.

You will obtain the same result if you replace in ajaxf.html the content of the h:body with the code shown in Listing 8-19.
<h:form>
  <f:ajax render="@form" event="click"/>
  <h:outputText value="The time on the server is: "/>
  <h:outputText value="#{serverTimeBean.when} "/>
  <h:commandButton value="Update"/>
  </h:form>
Listing 8-19

Alternate h:body for ajaxf.xhtml

With this setting, you ajaxify all components of the form. As a result, when you click the Update button, JSF sends an Ajax request, as it did before, and because the render attribute is set to @form, serverTimeBean.when is updated, as before. Events applicable to whole forms are click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, and mouseup.

With input elements in the form, when the user changes the content in any of them, that also triggers an Ajax request. To test it, replace h:commandButton with an h:inputText element as shown in Listing 8-20.
<h:form>
  <h:outputText value="The time on the server is: "/>
  <h:outputText id="timeField" value="#{serverTimeBean.when} "/>
  <h:inputText value="#{serverTimeBean.when}" size="30">
    <f:ajax render="@this timeField" event="blur"/>
    </h:inputText>
  </h:form>
Listing 8-20

Yet Another h:body for ajaxf.xhtml

The resulting page is shown in Figure 8-7.
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig7_HTML.jpg
Figure 8-7

A modified ajaxf.xhtml

As long as you remain within the input field, nothing happens. When you hit enter or click outside it, Ajax sends a request to the server to update the property specified in h:inputText. In the example, it sends a request to set serverTimeBean.when to “Tue Apr 28 020”. JSF does it in the Update Model Value phase. Then, during Render Response, Tomcat prepares the Javax response with two values obtained from serverTimeBean.when, one for h:outputText and one for h:inputText. As ServerTime.java always produces a fresh time string, that’s what is returned to the browser, and what you typed in the input field remains unused in the bean’s variable when.

Possible events for input fields are blur, change, click, dblclick, focus, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, mouseup, select, and valueChange. The default is valueChange.

The value of the render attribute can be a single identifier, a space-delimited list of identifiers, or one of the special strings @all, @this, @form, and @none.

The facelet Library

What makes JSF’s facelet library interesting is that it supports templating. That is, a mechanism that allows you to minimize duplication of code when developing pages with the same layout or common content.

While JSP with jsp:include provides an easy mechanism to reuse content, it doesn’t provide any easy way to define the same layout for different pages. It is up to you to ensure that the pages look identical when viewed in a browser.

The JSF facelet library lets you form a page by defining a layout in an XHTML file and then filling it up with content defined in one or more other XHTMLs. I will show you an example shortly, but first, have a look at Table 8-4, which lists all tags of the facelet library. To help you make sense of the tags, I have flagged those that are part of the templating mechanism.
Table 8-4

facelet Tags

Tag Name

Description

Templating

ui:component

Creates a component

N

ui:composition

Creates a composition

Y

ui:debug

Creates a component to help you debug the page

N

ui:decorate

Defines a fragment containing a composition

Y

ui:define

Defines content to be inserted into a template

Y

ui:fragment

Defines a fragment containing a component

N

ui:include

Includes content from an XHTML file

N

ui:insert

Inserts content into a template

Y

ui:param

Defines a parameter for an included file or a template

Y

ui:repeat

An alternative to h:dataTable and c:forEach

N

ui:remove

Removes what is in its body

N

The templ Application

In this section, I will describe templ , an application that uses facelet templating.

To create it, I started from the example simplefx I explained in this chapter. You will recall that it essentially consisted of two JSP documents that invoked each other: first.jspx asked you to type something into a text field, and second.jspx displayed what you had typed.

To make an example of templating, I added a third page almost identical to the second one, so that I could show you how to define a template for them. To get started, let’s look at how the first two pages appear in a web browser (Figures 8-8 and 8-9).
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig8_HTML.jpg
Figure 8-8

templ first page

../images/309332_3_En_8_Chapter/309332_3_En_8_Fig9_HTML.jpg
Figure 8-9

templ second page

Notice that the header of the second page is gray instead of black. The third page is identical to the second one, but its title is “Third page” and the text before the button starts with “Page 3”. To try it out, import in Eclipse the project templ from the software package for this chapter, and then type in a browser http://localhost:8080/templ/.

The application consists of the following folders and files (the folders are in bold for easy reading):
templ
    first.xhtml
    index.jsp
    page2.xhtml
    page3.xhtml
    resources
        css
            styles.css
    templates
        defaults
            header.xhtml
        layout.xhtml
    WEB-INF
        classes
            AString.class
            AString.java
        faces-config.xml
        web.xml
Listing 8-21 shows the code of the first page.
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
  xmlns:jsp="http://xmlns.jcp.org/JSP/Page"
  version="2.1"
  >
<jsp:directive.page
  language="java"
  contentType="application/xhtml+xml;charset=UTF-8"
  />
<jsp:output omit-xml-declaration="false"/>
<jsp:output
  doctype-root-element="html"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  />
<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"
      >
<h:head><title>First Page</title></h:head>
<h:body>
<f:view>
  <ui:include src="/templates/defaults/header.xhtml"/>
  <h:form>
    <h:outputText value="Type something here: "/>
    <h:inputText value="#{aStringBean.str}"/>
    <h:commandButton action="go2" value="Page 2"/>
    <h:commandButton action="go3" value="Page 3"/>
    </h:form>
  </f:view>
</h:body>
</html>
</jsp:root>
Listing 8-21

first.xhtml

First of all, notice that I renamed the file first.xhtml. This is because facelet elements (i.e., those with prefix ui) only work inside h:body. This means that you can no longer use the HTML body tag. As h:body requires the extension of the document to be xhtml, I had to ditch the extension jspx. The same applies to first.xhtml, which remains a valid JSP document despite the change of name.

Another difference from first.jspx is that I moved the namespace declarations for the core and HTML JSF libraries from jsp:root to the html tag and then added to them the declaration for the JSF facelet library. As none of the JSF tags are used outside the html element, it makes sense to keep them there, which is where they normally are in XHTML documents.

Finally, notice that first.xhtml includes a standard header with ui:include.

So far so good. Nothing too exciting. You could have done the same with jsp:include, without need for facelets. But now let’s look at page2.xhtml (Listing 8-22) and in particular to its h:body element.
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
  xmlns:jsp="http://xmlns.jcp.org/JSP/Page"
  version="2.1"
  >
<jsp:directive.page
  language="java"
  contentType="application/xhtml+xml;charset=UTF-8"
  />
<jsp:output omit-xml-declaration="false"/>
<jsp:output
  doctype-root-element="html"
  doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
  doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
  />
<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"
      >
<h:body>
  <ui:composition template="/templates/layout.xhtml">
    <ui:define name="title">Second page</ui:define>
    <ui:define name="pageNum">2</ui:define>
    </ui:composition>
</h:body>
</html>
</jsp:root>
Listing 8-22

page2.xhtml

Notice that there is no h:head element in page2.xhtml. This is because JSF, when it encounters a ui:composition element, it ignores everything other than the content of h:body. You got it right: JSF only looks at the lines I have highlighted in Listing 8-22.

But then, you might ask, why do we bother with all the stuff that precedes the h:body tag? The reason is that the file must be a valid XML document. But it is true that we can simplify it. That’s why I dropped the h:head element (which JSF ignores anyway), without which the code remains valid XML. With a page that doesn’t use JSP tags inside h:body, you can also get rid of the JSP elements. This is what I did with page3.xhtml, which you can see in Listing 8-23.
<?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"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      >
<h:body>
  <ui:composition template="/templates/layout.xhtml">
    <ui:define name="title">Third page</ui:define>
    <ui:define name="pageNum">3</ui:define>
    </ui:composition>
</h:body>
</html>
Listing 8-23

page3.xhtml

Obviously, you cannot remove the JSP header elements and jsp:root when you use JSP code inside h:body. But you can use JSTL and your own custom-tag libraries without declaring the jsp namespace, as long as you declare the appropriate namespaces in the html tag. What you certainly cannot use in any case, with or without JSP declaration, are JSP scripting and directive elements, because anything enclosed between <% and %> is not valid XML.

Let’s go back to describing how JSF handles the pages that make use of templates.

The presence of the ui:composition element with a defined template attribute means that it is the template document that generates the page to be sent back to the user as a response, not the page that contains the ui:composition element.

Listing 8-24 shows the template for page*.xhtml.
<?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"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      >
<h:head>
  <title>
    <ui:insert name="title">Default Title</ui:insert>
    </title>
  <h:outputStylesheet name="styles.css" library="css"/>
</h:head>
<h:body>
<f:view>
  <ui:insert name="header">
    <ui:include src="/templates/defaults/header.xhtml"/>
    </ui:insert>
  <h:form>
    <h:outputText value="Page "/>
    <ui:insert name="pageNum"/>
    <h:outputText value=" has received & quot;#{aStringBean.str}& quot; "/>
    <h:commandButton action="goBack" value="Back to first page"/>
    </h:form>
</f:view>
</h:body>
</html>
Listing 8-24

layout.xhtml

The two highlighted lines identify two places where the template expects the “client” pages to insert content. If you go back to page2.xhtml and page3.xhtml (Listings 8-22 and 8-23), you will see that the two ui:defines inside ui:composition have the same name attributes as the two ui:inserts of the template.

When layout.xhtml is used to generate the response to a request sent to page2.xhtml, the element <ui:insert name="title">Default Title</ui:insert> is replaced with the string “Second page” and the element <ui:insert name="pageNum"/> is replaced with “2”. For page3.xhtml, the string is “Third page” and the page number is “3”. Notice that the body of ui:insert is the default value for that insert, to be used when the “client” page doesn’t define any value.

Notice that both layout.xhtml and first.xhtml include a default header (shown in Listing 8-25).
<?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"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      >
<h:body>
  <ui:composition>
    <h1>Example of Templating</h1>
    </ui:composition>
</h:body>
</html>
Listing 8-25

header.xhtml

In header.xhtml, the element ui:composition doesn’t define a template attribute. Its presence ensures that the rest of the page is ignored when header.xhtml is included with ui:include. Actually, the only line needed in header.xhtml is the one I have highlighted. But the advantage of having a well-formed XHTML page is that you can view it in a browser. With more complex pages, it is sometimes useful to be able to do so.

There is still something I need to clarify. Have you noticed that the header shown in the first page (see Figure 8-8) is black, while the header of the second page (see Figure 8-9) is gray?

This is because the template, with the element
<h:outputStylesheet name="styles.css" library="css"/>

loads a style sheet that defines the color of headers to be gray.

As first.xhtml doesn’t use the template, the color of the headers remains the default black. Obviously, nothing prevents you from using the style sheet in first.xhtml by placing in its h:head the same element used in the template. Alternatively, you can also use the HTML element
<link rel="stylesheet" type="text/css" href="/templ/resources/css/styles.css"/>

Still on the subject of linking to the style sheet with h:outputStylesheet: notice that the name of the resources folder doesn’t appear anywhere. This means that it is hard-coded within the component and that you are stuck with it. But the folder names templates and defaults are entirely my choice. Therefore, you can choose the names you like.

To complete the description of the templ application, I still need to show you web.xml (Listing 8-26), which is pretty obvious, and faces-config.xml (Listing 8-27), which is also self-explanatory.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
  </servlet>
<servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
<context-param>
  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
  <param-value>.xhtml</param-value>
  </context-param>
</web-app>
Listing 8-26

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config 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-facesconfig_2_3.xsd"
        version="2.3" >
 <managed-bean>
                <managed-bean-name>aStringBean</managed-bean-name>
                <managed-bean-class>AString</managed-bean-class>
                <managed-bean-scope>session</managed-bean-scope>
                <managed-property>
                        <property-name>str</property-name>
                        <property-class>java.lang.String</property-class>
                        <null-value></null-value>
                </managed-property>
        </managed-bean>
  <navigation-rule>
    <from-view-id>/first.xhtml</from-view-id>
    <navigation-case>
      <from-outcome>go2</from-outcome>
      <to-view-id>/page2.xhtml</to-view-id>
      </navigation-case>
    <navigation-case>
      <from-outcome>go3</from-outcome>
      <to-view-id>/page3.xhtml</to-view-id>
      </navigation-case>
    </navigation-rule>
  <navigation-rule>
    <from-view-id>/page2.xhtml</from-view-id>
    <navigation-case>
      <from-outcome>goBack</from-outcome>
      <to-view-id>/first.xhtml</to-view-id>
      </navigation-case>
    </navigation-rule>
  <navigation-rule>
    <from-view-id>/page3.xhtml</from-view-id>
    <navigation-case>
      <from-outcome>goBack</from-outcome>
      <to-view-id>/first.xhtml</to-view-id>
      </navigation-case>
    </navigation-rule>
  </faces-config>
Listing 8-27

faces-config.xml

The composite Library

JSF is based on user-interface components, but for a long time, it was difficult to create new components or combine existing components into a new one. JSF introduced the composite library with release 2.0 to make those tasks easier.

Table 8-5 lists all the tags of the composite library. The two tags interface and implementation are special, in that they are containers for other tags.
Table 8-5

composite Tags

Tag Name

Description

Valid In

composite:implementation

Container of the XHTML code that implements the component

 

composite:interface

Container of interface components

 

composite:actionSource

Exposes components that generate action events

interface

composite:attribute

Declares attributes of components

interface

composite:editableValueHolder

Exposes components with editable values

interface

composite:extension

Inserts XML code in interface components

interface components

composite:facet

Declares a component’s facet

interface

composite:insertChildren

Inserts XHTML code into component

implementation

composite:insertFacet

Inserts a facet

implementation

composite:renderFacet

Renders a facet

implementation

composite:valueHolder

Exposes components with non-editable values interface

 
Conceptually, to define a new component, you need to go through the following steps:
  • Define its namespace (i.e., where it is).

  • Specify its functionality (i.e., what it does).

  • Define how you use it (i.e., its interface).

  • Design how you code it (i.e., its implementation).

Some Examples

To write the first example, let’s go through the four points I listed at the end of the previous section:
  • Define a namespace. I have chosen gz.

  • Specify its functionality. The component should compose a greeting message with a parameterized addressee.

  • Define how you use it. Just call it with an attribute to pass to it the addressee.

  • Design how you code it. Simple. An h:outputText will do.

The code for the new component is shown in Listing 8-28. To test it, import the project composite from the software package for this chapter into Eclipse, and then type in the browser http://localhost:8080/composite.
<?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"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:composite="http://xmlns.jcp.org/jsf/composite"
      >
<h:head><title>Example of a composite component</title></h:head>
<h:body>
  <composite:interface>
    <composite:attribute name="x"/>
    </composite:interface>
  <composite:implementation>
    <h:outputText value="Hello, #{cc.attrs.x}!"/>
    </composite:implementation>
  </h:body>
</html>
Listing 8-28

hello.xhtml

Not surprisingly, for such a trivial component, the code is also trivial. But it tells you a lot about developing components with the composite library.

First of all, inside h:body, you find two elements, a composite:interface and a composite:implementation. Inside the former, you define the attribute named x, and inside the latter, you define the logic of the component.

To access the attribute from within the implementation, you use the expression #{cc.attrs.x).

Listing 8-29 shows you how to use the new component, and Figure 8-10 shows how the page appears in a browser.
<?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"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:gz="http://java.sun.com/jsf/composite/gz"
      >
<h:head><title>Example of a composite component</title></h:head>
<h:body>
  <gz:hello x="wherever you are"/>
  </h:body>
</html>
Listing 8-29

comp.xhtml

../images/309332_3_En_8_Chapter/309332_3_En_8_Fig10_HTML.jpg
Figure 8-10

composite

Have you noticed anything unusual in comp.xhtml ? Instead of separately declaring the namespaces of the JSF composite library and of your custom components, you declare a single namespace composite/gz. For this to work, you need to create in the root of your application a folder named resources; create a folder (in the example, named gz) inside resources; and place your custom components there. The name of the component (e.g., hello) is obtained from the name of the component file (e.g., hello.xhtml) by removing its extension.

It is an established practice to use the same string for the prefix and for naming the folder inside resources, and I recommend that you follow it, but the two strings can be different.

Note that if you place elements in an interface body, you need to define a corresponding implementation. But you can have code in implementation with an empty interface, like in
  <composite:interface/>
  <composite:implementation>
    <h:outputText value="Hello, World!"/>
    </composite:implementation>

It simply means that your new component will not have any attribute to set.

To include in a composite component an input component, do exactly what you did for an output component in hello.xhtml. In fact, if you replace in hello.xhtml the line
    <h:outputText value="Hello, #{cc.attrs.x}!"/>
with
    <h:inputText value="Hello, #{cc.attrs.x}!"/>
you will see the page shown in Figure 8-11, but be aware that this is not a working page. It’s just to show you how to use composite:attribute .
../images/309332_3_En_8_Chapter/309332_3_En_8_Fig11_HTML.jpg
Figure 8-11

composite with input element

You can also use composite:attribute to set the action attribute of h:commandButton and h:commandLink. For example, if you want to build a composite component called, say, flip around the h:commandButton you used in templa a couple of pages back, the body of flip.xhtml would look something like this:
<composite:interface>
  <composite:attribute name="act" targets="myB" method-signature="java.lang.String action()"/>
  </composite:interface>
<composite:implementation>
  <h:commandButton id="myB" action="#{cc.attrs.act}" value="Page #{actionBean.n}"
      actionListener="#{actionBean.swapPages}"
      />
  </composite:implementation>
Then, you would use the new composite component like this:
<gz:flip act="#{actionBean.goThere}"/>

As it was in the previous examples, you use the expression #{cc.attrs.act} to access from the implementation the value of the act attribute declared in interface. In addition, unlike what happened in the previous examples, you also need a reference in the opposite direction, from interface to implementation. This is because JSF must be able to wire the method set in gz:flip to the h:commandButton component for which the method is meant. In fact, if there were more components in implementation, you could wire the same method to several of them by writing their identifiers in the targets attribute separated by spaces (this is why the name of the attribute is targets, plural, instead of target).

The value of method-signature specifies that the value of act must evaluate to a method and defines its signature. This means that <gz:flip act="go2"/> wouldn’t work. You would have to replace
method-signature="java.lang.String action()"
with
type="java.lang.String"
The two attributes are mutually exclusive, and if you leave out both of them, JSF assumes
type="java.lang.Object"
Now that you know how to make visible the action attribute of h:commandButton, you will perhaps be asking yourself how you expose its actionListener attribute as well. Here it is:
<composite:interface>
  <composite:attribute name="act" targets="myB" method-signature="java.lang.String action()"/>
  <composite:actionSource name="myB"/>
  </composite:interface>
<composite:implementation>
  <h:commandButton id="myB" action="#{cc.attrs.act}" value="Page #{actionBean.n}"/>
  </composite:implementation>
Then, you would use the new composite component like this:
<gz:flip act="#{actionBean.goThere}">
  <f:actionListener for="myB" binding="#{actionBean.swapPages}"/>
  </gz:flip>

The element composite:actionSource exposes the h:commandButton component, and f:actionListener wires to it the appropriate action listener. Notice that the attribute actionListener has disappeared from h:commandButton.

A few words about composite:facet and composite:renderFacet. Close to the beginning of the section about the core library, I mentioned that facets are a means to let components do something special with a block of code. Now, suppose that you want to include a special word in several places within the composite component you are developing and that the page that uses the component should be able to define that word. You could do it like this:
<composite:interface>
  <composite:facet name="aWord"/>
  </composite:interface>
<composite:implementation>
  <!-- ...some code... -->
  <composite:renderFacet name="aWord"/>   <!-- say it here -->
  <!-- ...some code... -->
  <composite:renderFacet name="aWord"/>   <!-- and here -->
  <!-- ...some code... -->
  <composite:renderFacet name="aWord"/>   <!-- and again here -->
  </composite:implementation>
And this is how you would use the component:
<gz:myFacetedComponent>
  <f:facet name="aWord"><h:outputText value="#@%!"/></f:facet>
  </gz:myFacetedComponent>

JSF will take the body of the facet element defined in the using page and insert it where you invoke composite:renderFacet. If you like to insert those components as a facet, you need to use composite:insertFacet instead.

Normally, JSF ignores what is inside the body of your custom component, like in
<gz:myComponent>
  <h:outputText value="#@%! "/>
  <h:inputText value="#{aBean.whatever}"/>
  </gz:myComponent>
If you want to include it in your composite component, you can do it with
<composite:insertChildren/>

Summary

In this chapter, we have covered a lot of ground. I gave you a first taste of JSF with simple applications. Then, after describing the JSF life cycle, I went on to talk about all four JSF tag libraries html, core, facelet, and composite. I listed their tags and showed you with simple examples how to use the most common or significant tags.

In the next chapter, we’ll go back to eshop to see how we can convert it to a JSF application.

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

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