The Java EE 5 Tutorial

Chapter 14 Configuring JavaServer Faces Applications

The responsibilities of the application architect include the following:

This chapter explains how to perform all the responsibilities of the application architect.

Application Configuration Resource File

JavaServer Faces technology provides a portable configuration format (as an XML document) for configuring resources. An application architect creates one or more files, called application configuration resource files, that use this format to register and configure objects and to define navigation rules. An application configuration resource file is usually called faces-config.xml.

The application configuration resource file must be valid against the schema located at http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd.

In addition, each file must include the following, in this order:

You can have more than one application configuration resource file. The JavaServer Faces implementation finds the file or files by looking for the following:

To access resources registered with the application, an application developer uses an instance of the Application class, which is automatically created for each application. The Application instance acts as a centralized factory for resources that are defined in the XML file.

When an application starts up, the JavaServer Faces implementation creates a single instance of the Application class and configures it with the information you configure in the application configuration resource file.

Configuring Beans

To instantiate backing beans and other managed beans used in a JavaServer Faces application and store them in scope, you use the managed bean creation facility. This facility is configured in the application configuration resource file using managed-bean XML elements to define each bean. This file is processed at application startup time. When a page references a bean, the JavaServer Faces implementation initializes it according to its configuration in the application configuration resource file.

With the managed bean creation facility, you can:

This section shows you how to initialize beans using the managed bean creation facility. See Writing Bean Properties and Writing Backing Bean Methods for information on programming backing beans. Binding Component Values and Instances to External Data Sources explains how to reference a managed bean from the component tags.

Using the managed-bean Element

You create a bean using a managed-bean element, which represents an instance of a bean class that must exist in the application. At runtime, the JavaServer Faces implementation processes the managed-bean element. If a page references the bean, the JavaServer Faces implementation instantiates the bean as specified by the element configuration if no instance exists.

Here is an example managed bean configuration from the Duke’s Bookstore application:

<managed-bean>
    <managed-bean-name> NA </managed-bean-name>
        <managed-bean-class>
             com.sun.bookstore6.model.ImageArea
         </managed-bean-class>
        <managed-bean-scope> application </managed-bean-scope>
        <managed-property>
            <property-name>shape</property-name>
            <value>poly</value>
        </managed-property>
        ...
    </managed-bean-name>
</managed-bean>

    Using NetBeans IDE, you can add a managed bean declaration by doing the following:

  1. After opening your project in NetBeans IDE, expand the project node in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes of the project node.

  3. Double-click faces-config.xml.

  4. After faces-config.xml opens in the editor pane, right-click in the editor pane.

  5. Select JavaServer Faces -> Add Managed Bean.

  6. In the Add Managed Bean dialog:

    1. Enter the display name of the bean in the Bean Name field.

    2. Click Browse to locate the bean’s class.

  7. In the Browse Class dialog:

    1. Start typing the name of the class you are looking for in the Class Name field. While you are typing, the dialog will show the matching classes.

    2. Select the class from the Matching Classes box.

    3. Click OK.

  8. In the Add Managed Bean dialog:

    1. Select the bean’s scope from the Scope menu.

    2. Click Add.

  9. In the Projects tab, right-click the bookstore1 project, and select Undeploy and Deploy.

The preceding steps will add the managed-bean element and three elements inside of it: a managed-bean-name element, a managed-bean-class element and a managed-bean-scope element. You will need to edit the XML of the configuration file directly to further configure this managed bean.

The managed-bean-name element defines the key under which the bean will be stored in a scope. For a component’s value to map to this bean, the component tag’s value attribute must match the managed-bean-name up to the first period. For example, this value expression maps to the shape property of the ImageArea instance, NA:

value="#{NA.shape}"

The part before the period (.) matches the managed-bean-name of ImageArea. Adding UI Components to a Page Using the HTML Component Tags has more examples of using the value attribute to bind components to bean properties.

The managed-bean-class element defines the fully qualified name of the JavaBeans component class used to instantiate the bean. It is the application developer’s responsibility to ensure that the class complies with the configuration of the bean in the application configuration resource file. This includes making sure that the types of the properties in the bean match those configured for the bean in the configuration file.

The managed-bean-scope element defines the scope in which the bean will be stored. The four acceptable scopes are none, request, session, or application. If you define the bean with a none scope, the bean is instantiated anew each time it is referenced, and so it does not get saved in any scope. One reason to use a scope of none is that a managed bean references another managed bean. The second bean should be in none scope if it is supposed to be created only when it is referenced. See Initializing Managed Bean Properties for an example of initializing a managed bean property.

If you are configuring a backing bean that is referenced by a component tag’s binding attribute, you should define the bean with a request scope. If you placed the bean in session or application scope instead, the bean would need to take precautions to ensure thread safety because UIComponent instances depend on running inside of a single thread.

The managed-bean element can contain zero or more managed-property elements, each corresponding to a property defined in the bean class. These elements are used to initialize the values of the bean properties. If you don’t want a particular property initialized with a value when the bean is instantiated, do not include a managed-property definition for it in your application configuration resource file.

If a managed-bean element does not contain other managed-bean elements, it can contain one map-entries element or list-entries element. The map-entries element configures a set of beans that are instances of Map. The list-entries element configures a set of beans that are instances of List.

To map to a property defined by a managed-property element, you must ensure that the part of a component tag’s value expression after the period matches the managed-property element’s property-name element. In the earlier example, the shape property is initialized with the value poly. The next section explains in more detail how to use the managed-property element.

Initializing Properties Using the managed-property Element

A managed-property element must contain a property-name element, which must match the name of the corresponding property in the bean. A managed-property element must also contain one of a set of elements (listed in Table 14–1) that defines the value of the property. This value must be of the same type as that defined for the property in the corresponding bean. Which element you use to define the value depends on the type of the property defined in the bean. Table 14–1 lists all the elements used to initialize a value.

Table 14–1 Subelements of managed-property Elements That Define Property Values

Element 

Value That It Defines 

list-entries

Defines the values in a list 

map-entries

Defines the values of a map 

null-value

Explicitly sets the property to null

value

Defines a single value, such as a String or int, or a JavaServer Faces EL expression

Using the managed-bean Element includes an example of initializing String properties using the value subelement. You also use the value subelement to initialize primitive and other reference types. The rest of this section describes how to use the value subelement and other subelements to initialize properties of Java Enum types, java.util.Map, array, and Collection, as well as initialization parameters.

Referencing a Java Enum Type

As of version 1.2 of JavaServer Faces technology, a managed bean property can also be a Java Enum type (see http://java.sun.com/javase/6/docs/api/java/lang/Enum.html). In this case, the value element of the managed-property element must be a String that matches one of the String constants of the Enum. In other words, the String must be one of the valid values that can be returned if you were to call valueOf(Class, String) on enum, where Class is the Enum class and String is the contents of the value subelement. For example, suppose the managed bean property is the following:

public enum Suit { Hearts, Spades, Diamonds, Clubs}
 ...
public Suit getSuit() { ... return Suit.Hearts; }

Assuming that you want to configure this property in the application configuration file, the corresponding managed-property element would look like this:

<managed-property>
    <property-name>Suit</property-name>
    <value>Hearts</value>
</managed-property>

When the system encounters this property, it iterates over each of the members of the enum and calls toString() on each member until it finds one that is exactly equal to the value from the value element.

Referencing an Initialization Parameter

Another powerful feature of the managed bean creation facility is the ability to reference implicit objects from a managed bean property.

Suppose that you have a page that accepts data from a customer, including the customer’s address. Suppose also that most of your customers live in a particular area code. You can make the area code component render this area code by saving it in an implicit object and referencing it when the page is rendered.

You can save the area code as an initial default value in the context initParam implicit object by adding a context parameter to your web application and setting its value in the deployment descriptor. For example, to set a context parameter called defaultAreaCode to 650, add a context-param element to the deployment descriptor, give the parameter the name defaultAreaCode and the value 650.

Next, you write a managed-bean declaration that configures a property that references the parameter:

<managed-bean>
    <managed-bean-name>customer</managed-bean-name>
        <managed-bean-class>CustomerBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>areaCode</property-name>
                <value>#{initParam.defaultAreaCode}</value>
            </managed-property>
            ...
</managed-bean>

To access the area code at the time the page is rendered, refer to the property from the area component tag’s value attribute:

<h:inputText id=area value="#{customer.areaCode}"

Retrieving values from other implicit objects is done in a similar way. See Implicit Objects for a list of implicit objects.

Initializing Map Properties

The map-entries element is used to initialize the values of a bean property with a type of java.util.Map if the map-entries element is used within a managed-property element. A map-entries element contains an optional key-class element, an optional value-class element, and zero or more map-entry elements.

Each of the map-entry elements must contain a key element and either a null-value or value element. Here is an example that uses the map-entries element:

<managed-bean>
    ...
    <managed-property>
        <property-name>prices</property-name>
        <map-entries>
            <map-entry>
                <key>My Early Years: Growing Up on *7</key>
                <value>30.75</value>
            </map-entry>
            <map-entry>
                <key>Web Servers for Fun and Profit</key>
                <value>40.75</value>
            </map-entry>
        </map-entries>
    </managed-property>
</managed-bean>

The map that is created from this map-entries tag contains two entries. By default, all the keys and values are converted to java.lang.String. If you want to specify a different type for the keys in the map, embed the key-class element just inside the map-entries element:

<map-entries>
    <key-class>java.math.BigDecimal</key-class>
    ...
</map-entries>

This declaration will convert all the keys into java.math.BigDecimal. Of course, you must make sure that the keys can be converted to the type that you specify. The key from the example in this section cannot be converted to a java.math.BigDecimal because it is a String.

If you also want to specify a different type for all the values in the map, include the value-class element after the key-class element:

<map-entries>
    <key-class>int</key-class>
    <value-class>java.math.BigDecimal</value-class>
    ...
</map-entries>

Note that this tag sets only the type of all the value subelements.

The first map-entry in the preceding example includes a value subelement. The value subelement defines a single value, which will be converted to the type specified in the bean.

The second map-entry defines a value element, which references a property on another bean. Referencing another bean from within a bean property is useful for building a system from fine-grained objects. For example, a request-scoped form-handling object might have a pointer to an application-scoped database mapping object. Together the two can perform a form-handling task. Note that including a reference to another bean will initialize the bean if it does not already exist.

Instead of using a map-entries element, it is also possible to assign the entire map using a value element that specifies a map-typed expression.

Initializing Array and List Properties

The list-entries element is used to initialize the values of an array or List property. Each individual value of the array or List is initialized using a value or null-value element. Here is an example:

<managed-bean>
    ...
    <managed-property>
        <property-name>books</property-name>
        <list-entries>
            <value-class>java.lang.String</value-class>
            <value>Web Servers for Fun and Profit</value>
            <value>#{myBooks.bookId[3]}</value>
            <null-value/>
        </list-entries>
    </managed-property>
</managed-bean>

This example initializes an array or a List. The type of the corresponding property in the bean determines which data structure is created. The list-entries element defines the list of values in the array or List. The value element specifies a single value in the array or List and can reference a property in another bean. The null-value element will cause the setBooks method to be called with an argument of null. A null property cannot be specified for a property whose data type is a Java primitive, such as int or boolean.

Initializing Managed Bean Properties

Sometimes you might want to create a bean that also references other managed beans so that you can construct a graph or a tree of beans. For example, suppose that you want to create a bean representing a customer’s information, including the mailing address and street address, each of which is also a bean. The following managed-bean declarations create a CustomerBean instance that has two AddressBean properties: one representing the mailing address, and the other representing the street address. This declaration results in a tree of beans with CustomerBean as its root and the two AddressBean objects as children.

<managed-bean>
    <managed-bean-name>customer</managed-bean-name>
    <managed-bean-class>
        com.mycompany.mybeans.CustomerBean
    </managed-bean-class>
    <managed-bean-scope> request </managed-bean-scope>
    <managed-property>
        <property-name>mailingAddress</property-name>
        <value>#{addressBean}</value>
    </managed-property>
    <managed-property>
        <property-name>streetAddress</property-name>
        <value>#{addressBean}</value>
    </managed-property>
    <managed-property>
        <property-name>customerType</property-name>
        <value>New</value>
    </managed-property>
</managed-bean>
<managed-bean>
    <managed-bean-name>addressBean</managed-bean-name>
    <managed-bean-class>
        com.mycompany.mybeans.AddressBean
    </managed-bean-class>
    <managed-bean-scope> none </managed-bean-scope>
    <managed-property>
        <property-name>street</property-name>
        <null-value/>
    <managed-property>
    ...
</managed-bean>

The first CustomerBean declaration (with the managed-bean-name of customer) creates a CustomerBean in request scope. This bean has two properties: mailingAddress and streetAddress. These properties use the value element to reference a bean named addressBean.

The second managed bean declaration defines an AddressBean but does not create it because its managed-bean-scope element defines a scope of none. Recall that a scope of none means that the bean is created only when something else references it. Because both the mailingAddress and the streetAddress properties reference addressBean using the value element, two instances of AddressBean are created when CustomerBean is created.

When you create an object that points to other objects, do not try to point to an object with a shorter life span because it might be impossible to recover that scope’s resources when it goes away. A session-scoped object, for example, cannot point to a request-scoped object. And objects with none scope have no effective life span managed by the framework, so they can point only to other none scoped objects. Table 14–2 outlines all of the allowed connections.

Table 14–2 Allowable Connections between Scoped Objects

An Object of This Scope 

May Point to an Object of This Scope 

none

none

application

none, application

session

none, application, session

request

none, application, session, request

Be sure not allow cyclical references between objects. For example, neither of the AddressBean objects in the preceding example should point back to the CustomerBean object because CustomerBean already points to the AddressBean objects.

Initializing Maps and Lists

In addition to configuring Map and List properties, you can also configure a Map and a List directly so that you can reference them from a tag rather than referencing a property that wraps a Map or a List.

The Duke’s Bookstore application configures a List to initialize the list of free newsletters, from which users can choose a set of newsletters to subscribe to on the bookcashier.jsp page:

<managed-bean>
    ...
<managed-bean-name>newsletters</managed-bean-name>
    <managed-bean-class>
        java.util.ArrayList
    </managed-bean-class>
    <managed-bean-scope>application</managed-bean-scope>
    <list-entries>
        <value-class>javax.faces.model.SelectItem</value-class>
        <value>#{newsletter0}</value>
        <value>#{newsletter1}</value>
        <value>#{newsletter2}</value>
        <value>#{newsletter3}</value>
    </list-entries>
</managed-bean>
<managed-bean>
    <managed-bean-name>newsletter0</managed-bean-name>
    <managed-bean-class>
        javax.faces.model.SelectItem
    </managed-bean-class>
    <managed-bean-scope>none</managed-bean-scope>
    <managed-property>
        <property-name>label</property-name>
        <value>Duke’s Quarterly</value>
    </managed-property>
    <managed-property>
        <property-name>value</property-name>
        <value>200</value>
    </managed-property>
</managed-bean>
...

This configuration initializes a List called newsletters. This list is composed of SelectItem instances, which are also managed beans. See Using the selectItem Tag for more information on SelectItem. Note that, unlike the example in Initializing Map Properties, the newsletters list is not a property on a managed bean. (It is not wrapped with a managed-property element.) Instead, the list is the managed bean.

Registering Custom Error Messages

If you create custom error messages (which are displayed by the message and messages tags) for your custom converters or validators, you must make them available at application startup time. You do this in one of two ways: by queuing the message onto the FacesContext instance programmatically (as described in Performing Localization) or by registering the messages with your application using the application configuration resource file.

Here is the part of the file that registers the messages for the Duke’s Bookstore application:

<application>
    <message-bundle>
        com.sun.bookstore6.resources.ApplicationMessages
    </message-bundle>
    <locale-config>
        <default-locale>en</default-locale>
        <supported-locale>es</supported-locale>
        <supported-locale>de</supported-locale>
        <supported-locale>fr</supported-locale>
    </locale-config>
</application>

This set of elements will cause your Application instance to be populated with the messages contained in the specified resource bundle.

The message-bundle element represents a set of localized messages. It must contain the fully qualified path to the resource bundle containing the localized messages (in this case, resources.ApplicationMessages).

The locale-config element lists the default locale and the other supported locales. The locale-config element enables the system to find the correct locale based on the browser’s language settings. Duke’s Bookstore manually sets the locale and so it overrides these settings. Therefore, it’s not necessary to use locale-config to specify the default or supported locales in Duke’s Bookstore.

The supported-locale and default-locale tags accept the lowercase, two-character codes as defined by ISO 639 (see http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt). Make sure that your resource bundle actually contains the messages for the locales that you specify with these tags.

To access the localized message, the application developer merely references the key of the message from the resource bundle. See Performing Localization for more information.

Registering Custom Localized Static Text

Any custom localized static text you create that is not loaded into the page using the loadBundle tag must be registered with the application using the resource-bundle element in the application configuration resource file for your pages to have access to the text. Likewise, any custom error messages that are referenced by the converterMessage, requiredMessage, or validatorMessage attributes of an input component tag must also be made available to the application by way of the loadBundle tag or the resource-bundle element of the application configuration file.

Here is the part of the file that registers some custom error messages for the Duke’s Bookstore application:

<application>
    ...
    <resource-bundle>
        <base-name>
            com.sun.bookstore6.resources.CustomMessages
        </base-name>
        <var>customMessages</var>
    </resource-bundle>    
    ...
</application>

Similarly to the loadBundle tag, the value of the base-name subelement specifies the fully-qualified class name of the ResourceBundle class, which in this case is located in the resources package of the application.

Also similarly to the var attribute of the loadBundle tag, the var subelement of the resource-bundle element is an alias to the ResourceBundle class. This alias is used by tags in the page to identify the resource bundle.

The locale-config element shown in the previous section also applies to the messages and static text identified by the resource-bundle element. As with resource bundles identified by the message-bundle element, make sure that the resource bundle identified by the resource-bundle element actually contains the messages for the locales that you specify with these locale-config elements.

To access the localized message, the page author uses a value expression to reference the key of the message from the resource bundle. See Performing Localization for more information.

Registering a Custom Validator

If the application developer provides an implementation of the Validator interface to perform validation, you must register this custom validator in the application configuration resource file by using the validator XML element:

<validator>
    ...
    <validator-id>FormatValidator</validator-id>
    <validator-class>
        com.sun.bookstore6.validators.FormatValidator
    </validator-class>
    <attribute>
        ...
        <attribute-name>formatPatterns</attribute-name>
        <attribute-class>java.lang.String</attribute-class>
    </attribute>
</validator>

The validator-id and validator-class elements are required subelements. The validator-id element represents the identifier under which the Validator class should be registered. This ID is used by the tag class corresponding to the custom validator tag.

The validator-class element represents the fully qualified class name of the Validator class.

The attribute element identifies an attribute associated with the Validator implementation. It has required attribute-name and attribute-class subelements. The attribute-name element refers to the name of the attribute as it appears in the validator tag. The attribute-class element identifies the Java type of the value associated with the attribute.

Creating a Custom Validator explains how to implement the Validator interface.

Using a Custom Validator explains how to reference the validator from the page.

Registering a Custom Converter

As is the case with a custom validator, if the application developer creates a custom converter, you must register it with the application. Here is the converter configuration for CreditCardConverter from the Duke’s Bookstore application:

<converter>
    <description>
        Converter for credit card
         numbers that normalizes
         the input to a standard format
    </description>
    <converter-id>CreditCardConverter</converter-id>
    <converter-class>
        com.sun.bookstore6.converters.CreditCardConverter
    </converter-class>
</converter>

The converter element represents a Converter implementation and contains required converter-id and converter-class elements.

The converter-id element identifies an ID that is used by the converter attribute of a UI component tag to apply the converter to the component’s data. Using a Custom Converter includes an example of referencing the custom converter from a component tag.

The converter-class element identifies the Converter implementation.

Creating a Custom Converter explains how to create a custom converter.

Configuring Navigation Rules

As explained in Navigation Model, navigation is a set of rules for choosing the next page to be displayed after a button or hyperlink component is clicked. Navigation rules are defined in the application configuration resource file.

Each navigation rule specifies how to navigate from one page to a set of other pages. The JavaServer Faces implementation chooses the proper navigation rule according to which page is currently displayed.

After the proper navigation rule is selected, the choice of which page to access next from the current page depends on two factors:

The outcome can be anything the developer chooses, but Table 14–3 lists some outcomes commonly used in web applications.

Table 14–3 Common Outcome Strings

Outcome 

What It Means 

success

Everything worked. Go on to the next page. 

failure

Something is wrong. Go on to an error page. 

logon

The user needs to log on first. Go on to the logon page. 

no results

The search did not find anything. Go to the search page again. 

Usually, the action method performs some processing on the form data of the current page. For example, the method might check whether the user name and password entered in the form match the user name and password on file. If they match, the method returns the outcome success. Otherwise, it returns the outcome failure. As this example demonstrates, both the method used to process the action and the outcome returned are necessary to determine the proper page to access.

Here is a navigation rule that could be used with the example just described:

<navigation-rule>
    <from-view-id>/logon.jsp</from-view-id>
    <navigation-case>
        <from-action>#{LogonForm.logon}</from-action>
        <from-outcome>success</from-outcome>
        <to-view-id>/storefront.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-action>#{LogonForm.logon}</from-action>
        <from-outcome>failure</from-outcome>
        <to-view-id>/logon.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

This navigation rule defines the possible ways to navigate from logon.jsp. Each navigation-case element defines one possible navigation path from logon.jsp. The first navigation-case says that if LogonForm.logon returns an outcome of success, then storefront.jsp will be accessed. The second navigation-case says that logon.jsp will be re-rendered if LogonForm.logon returns failure.

The configuration of an application’s page flow consists of a set of navigation rules. Each rule is defined by the navigation-rule element in the faces-config.xml file.

The navigation rules of the Duke’s Bookstore application are very simple. Here are two complex navigation rules that could be used with the Duke’s Bookstore application:

<navigation-rule>
    <from-view-id>/catalog.jsp</from-view-id>
    <navigation-case>
        <from-outcome>success</from-outcome>
        <to-view-id>/bookcashier.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-outcome>out of stock</from-outcome>
        <from-action>
            #{catalog.buy}
        </from-action>
        <to-view-id>/outofstock.jsp</to-view-id>
    </navigation-case>
    <navigation-case>
        <from-outcome>error</from-outcome>
        <to-view-id>/error.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

The first navigation rule in this example says that the application will navigate from catalog.jsp to

The second navigation rule says that the application will navigate from any page to error.jsp if the application encountered an error.

Each navigation-rule element corresponds to one component tree identifier defined by the optional from-view-id element. This means that each rule defines all the possible ways to navigate from one particular page in the application. If there is no from-view-id element, the navigation rules defined in the navigation-rule element apply to all the pages in the application. The from-view-id element also allows wildcard matching patterns. For example, this from-view-id element says that the navigation rule applies to all the pages in the books directory:

<from-view-id>/books/*</from-view-id>

As shown in the example navigation rule, a navigation-rule element can contain zero or more navigation-case elements. The navigation-case element defines a set of matching criteria. When these criteria are satisfied, the application will navigate to the page defined by the to-view-id element contained in the same navigation-case element.

The navigation criteria are defined by optional from-outcome and from-action elements. The from-outcome element defines a logical outcome, such as success. The from-action element uses a method expression to refer to an action method that returns a String, which is the logical outcome. The method performs some logic to determine the outcome and returns the outcome.

The navigation-case elements are checked against the outcome and the method expression in this order:

When any of these cases is matched, the component tree defined by the to-view-id element will be selected for rendering.

    Using NetBeans IDE, you can configure a navigation rule by doing the following:

  1. After opening your project in NetBeans IDE, expand the project node in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes of the project node.

  3. Double-click faces-config.xml.

  4. After faces-config.xml opens in the editor pane, right-click in the editor pane.

  5. Select JavaServer Faces->Add Navigation Rule.

  6. In the Add Navigation Rule dialog:

    1. Enter or browse for the page that represents the starting view for this navigation rule.

    2. Click Add.

  7. Right-click again in the editor pane.

  8. Select JavaServer Faces -> Add Navigation Case.

  9. In the Add Navigation Case dialog:

    1. From the From View menu, select the page that represents the starting view for the navigation rule (from step 6a).

    2. (optional) In the From Action field, enter the action method invoked when the component that triggered navigation is activated.

    3. (optional) In the From Outcome field, enter the logical outcome string that the activated component references from its action attribute.

    4. From the To View menu, select or browse for the page that will be opened if this navigation case is selected by the navigation system.

    5. Click Add.

      Referencing a Method That Performs Navigation explains how to use a component tag’s action attribute to point to an action method. Writing a Method to Handle Navigation explains how to write an action method.

Registering a Custom Renderer with a Render Kit

When the application developer creates a custom renderer, as described in Delegating Rendering to a Renderer, you must register it using the appropriate render kit. Because the image map application implements an HTML image map, AreaRenderer (as well as MapRenderer) should be registered using the HTML render kit.

You register the renderer using the render-kit element of the application configuration resource file. Here is the configuration of AreaRenderer from the Duke’s Bookstore application:

<render-kit>
    <renderer>
        <component-family>Area</component-family>
        <renderer-type>DemoArea</renderer-type>
        <renderer-class>
            com.sun.bookstore6.renderers.AreaRenderer
        </renderer-class>
        <attribute>
            <attribute-name>onmouseout</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
        <attribute>
            <attribute-name>onmouseover</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
        <attribute>
            <attribute-name>styleClass</attribute-name>
            <attribute-class>java.lang.String</attribute-class>
        </attribute>
    </renderer>
    ...

The render-kit element represents a RenderKit implementation. If no render-kit-id is specified, the default HTML render kit is assumed. The renderer element represents a Renderer implementation. By nesting the renderer element inside the render-kit element, you are registering the renderer with the RenderKit implementation associated with the render-kit element.

The renderer-class is the fully qualified class name of the Renderer.

The component-family and renderer-type elements are used by a component to find renderers that can render it. The component-family identifier must match that returned by the component class’s getFamily method. The component family represents a component or set of components that a particular renderer can render. The renderer-type must match that returned by the getRendererType method of the tag handler class.

By using the component family and renderer type to look up renderers for components, the JavaServer Faces implementation allows a component to be rendered by multiple renderers and allows a renderer to render multiple components.

Each of the attribute tags specifies a render-dependent attribute and its type. The attribute element doesn’t affect the runtime execution of your application. Instead, it provides information to tools about the attributes the Renderer supports.

The object that is responsible for rendering a component (be it the component itself or a renderer to which the component delegates the rendering) can use facets to aid in the rendering process. These facets allow the custom component developer to control some aspects of rendering the component. Consider this custom component tag example:

<d:dataScroller>
    <f:facet name="header">
        <h:panelGroup>
            <h:outputText value="Account Id"/>
            <h:outputText value="Customer Name"/>
            <h:outputText value="Total Sales"/>
        </h:panelGroup>
    </f:facet>
    <f:facet name="next">
        <h:panelGroup>
            <h:outputText value="Next"/>
            <h:graphicImage url="/images/arrow-right.gif" />
        </h:panelGroup>
    </f:facet>
        ...
</d:dataScroller>

The dataScroller component tag includes a component that will render the header and a component that will render the Next button. If the renderer associated with this component renders the facets you can include the following facet elements in the renderer element:

<facet>
    <description>This facet renders as the
         header of the table. It should be a panelGroup
         with the same number of columns as the data
    </description>
    <display-name>header</display-name>
    <facet-name>header</facet-name>
</facet>
 <facet>
    <description>This facet renders as the content
         of the "next" button in the scroller. It should be a
         panelGroup that includes an outputText tag that
         has the text "Next" and a right arrow icon.
    </description>
     <display-name>Next</display-name>
    <facet-name>next</facet-name>
</facet>

If a component that supports facets provides its own rendering and you want to include facet elements in the application configuration resource file, you need to put them in the component’s configuration rather than the renderer’s configuration.

Registering a Custom Component

In addition to registering custom renderers (as explained in the preceding section), you also must register the custom components that are usually associated with the custom renderers.

Here is the component element from the application configuration resource file that registers AreaComponent:

<component>
    <component-type>DemoArea</component-type>
    <component-class>
        com.sun.bookstore6.components.AreaComponent
    </component-class>
    <property>
        <property-name>alt</property-name>
        <property-class>java.lang.String</property-class>
    </property>
    <property>
        <property-name>coords</property-name>
        <property-class>java.lang.String</property-class>
    </property>
    <property>
        <property-name>shape</property-name>
        <property-class>java.lang.String</property-class>
    </property>
</component>

The component-type element indicates the name under which the component should be registered. Other objects referring to this component use this name. For example, the component-type element in the configuration for AreaComponent defines a value of DemoArea, which matches the value returned by the AreaTag class’s getComponentType method.

The component-class element indicates the fully qualified class name of the component. The property elements specify the component properties and their types.

If the custom component can include facets, you can configure the facets in the component configuration using facet elements, which are allowed after the component-class elements. See Registering a Custom Renderer with a Render Kit for further details on configuring facets.

Basic Requirements of a JavaServer Faces Application

In addition to configuring your application, you must satisfy other requirements of JavaServer Faces applications, including properly packaging all the necessary files and providing a deployment descriptor. This section describes how to perform these administrative tasks.

JavaServer Faces applications must be compliant with the Servlet specification, version 2.3 (or later) and the JavaServer Pages specification, version 1.2 (or later). All applications compliant with these specifications are packaged in a WAR file, which must conform to specific requirements in order to execute across different containers. At a minimum, a WAR file for a JavaServer Faces application must contain the following:

The WAR file typically has this directory structure:

index.html
JSP pages
WEB-INF/
   web.xml
   faces-config.xml
   tag library descriptors (optional)
   classes/
      class files
         Properties files
   lib/
      JAR files

The web.xml file (or deployment descriptor), the set of JAR files, and the set of application files must be contained in the WEB-INF directory of the WAR file.

Configuring an Application with a Deployment Descriptor

Web applications are configured using elements contained in the web application deployment descriptor. The deployment descriptor for a JavaServer Faces application must specify certain configurations, which include the following:

The deployment descriptor can also specify other, optional configurations, including:

This section gives more details on these configurations. Where appropriate, it also describes how you can make these configurations using NetBeans IDE.

Identifying the Servlet for Life Cycle Processing

One requirement of a JavaServer Faces application is that all requests to the application that reference previously saved JavaServer Faces components must go through FacesServlet. A FacesServlet instance manages the request processing life cycle for web applications and initializes the resources required by JavaServer Faces technology.

Before a JavaServer Faces application can launch the first JSP page, the web container must invoke the FacesServlet instance in order for the application life cycle process to start. The application life cycle is described in the section The Life Cycle of a JavaServer Faces Page.

To make sure that the FacesServlet instance is invoked, you provide a mapping to it. The mapping to FacesServlet can be a prefix mapping, such as /guess/*, or an extension mapping, such as *.faces. The mapping is used to identify a JSP page as having JavaServer Faces content. Because of this, the URL to the first JSP page of the application must include the mapping.

In the case of prefix mapping, there are two ways to accomplish this:

The second method allows users to start the application from the first JSP page, rather than start it from an HTML page. However, the second method requires users to identify the first JSP page. When you use the first method, users need only enter

http://localhost:8080/guessNumber

In the case of extension mapping, if a request comes to the server for a JSP page with a .faces extension, the container will send the request to the FacesServlet instance, which will expect a corresponding JSP page of the same name to exist containing the content. For example, if the request URL is http://localhost/bookstore6/bookstore.faces, FacesServlet will map it to the bookstore.jsp page.

    If you are using NetBeans IDE, the time to map the FacesServlet instance is when you create your JavaServer Faces project with NetBeans IDE:

  1. In NetBeans IDE, select File->New Project.

  2. In the New Project dialog, select Web from the Categories tree.

  3. Select Web Application from the Projects panel.

  4. Click Next.

  5. Fill out the information in the Name and Location screen of the wizard.

  6. Click Next.

  7. Select the JavaServer Faces check box in the Framewoks screen.

  8. Enter the mapping, such as *.faces, to the FacesServlet instance in the Servlet URL Mapping field.

  9. Click Finish.

    After your project is open in NetBeans IDE, you can change the mapping to the FacesServlet instance by doing the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click Servlets at the top of the editor pane. The FacesServlet configuration appears in the editor pane.

    If you prefer to edit the web.xml file directly, perform the following steps to configure a mapping to the FacesServlet instance:

  1. Include a servlet element in the deployment descriptor.

  2. Inside the servlet element, include a display-name element and set it to FacesServlet.

  3. Also inside the servlet element, add a servlet-name element and set it to FacesServlet.

  4. Add a third element, called servlet-class, inside the servlet element and set it to javax.faces.webapp.FacesServlet. This is the fully-qualified class name of the FacesServlet class.

  5. After the servlet element, add a servlet-mapping element.

  6. Inside the servlet-mapping element, add a servlet-name element and set it to FacesServlet. This must match the name identified by the servlet-name element described in step 3.

  7. Also inside the servlet-mapping element, add a url-pattern element and set it to whatever mapping you prefer. This will be the path to FacesServlet. Users of the application will include this path in the URL when they access the application. For the guessNumber application, the path is /guess/*.

Specifying a Path to an Application Configuration Resource File

As explained in Application Configuration Resource File, an application can have multiple application configuration resource files. If these files are not located in the directories that the implementation searches by default or the files are not named faces-config.xml, you need to specify paths to these files.

    To specify these paths using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter javax.faces.CONFIG_FILES in the Param Name field.

    2. Enter the path to your configuration file in the Param Value field.

    3. Click OK.

  8. Repeat steps 1 through 7 for each configuration file.

    To specify paths to the files by editing the deployment descriptor directly follow these steps:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-value element inside the context-param element and call it javax.faces.CONFIG_FILES.

  3. Add a param-value element inside the context-param element and give it the path to your configuration file. For example, the path to the guessNumber application’s application configuration resource file is /WEB-INF/faces-config.xml.

  4. Repeat steps 2 and 3 for each application configuration resource file that your application contains.

Specifying Where State Is Saved

When implementing the state-holder methods (described in Saving and Restoring State), you specify in your deployment descriptor where you want the state to be saved, either client or server. You do this by setting a context parameter in your deployment descriptor.

    To specify where state is saved using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter javax.faces.STATE_SAVING_METHOD in the Param Name field.

    2. Enter client or server in the Param Value field.

    3. Click OK.

    To specify where state is saved by editing the deployment descriptor directly follow these steps:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name javax.faces.STATE_SAVING_METHOD.

  3. Add a param-value element to the context-param element and give it the value client or server, depending on whether you want state saved in the client or the server.

If state is saved on the client, the state of the entire view is rendered to a hidden field on the page. The JavaServer Faces implementation saves the state on the client by default. Duke’s Bookstore saves its state in the client.

Encrypting Client State

When you are choosing to save state on the client, you are essentially saying that you want state to be sent over the wire and saved on the client in a hidden field. Clearly, this opens the door to potential tampering with the state information. To prevent this from happening, you can specify that the state must be encrypted before it is transmitted to the client.

    To specify that state must be encrypted using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click References at the top of the editor pane.

  5. Expand the Environment Entries node.

  6. Click Add.

  7. In the Add Environment Entry dialog:

    1. Enter com.sun.faces.ClientStateSavingPassword in the Entry Name field.

    2. Select java.lang.String from the Entry Type menu.

    3. Click OK.

    To specify that state must be encrypted by editing the deployment descriptor directly, do the following:

  1. Add an env-entry element to your deployment descriptor.

  2. Add an env-entry-name element to the env-entry element and give it the name com.sun.faces.ClientStateSavingPassword.

  3. Add an env-entry-value element to the env-entry element, and give it your password. The password that you provide is used to generate keys and ciphers for encryption.

  4. Add an env-entry-type element and give it the type of your password, which must be java.lang.String.

If your deployment descriptor does not contain this environment entry then no encryption of client-side state will occur.

Restricting Access to JavaServer Faces Components

In addition to identifying the FacesServlet instance and providing a mapping to it, you should also ensure that all applications use FacesServlet to process JavaServer Faces components. You do this by setting a security constraint.

    To set a security constraint using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click Security at the top of the editor pane.

  5. Click Add Security Constraint.

  6. Enter a name for the constraint in the Display Name field.

  7. Click Add to add a web resource collection.

  8. In the Add Web Resource dialog:

    1. Enter a name for the web resource collection in the Resource Name field.

    2. In the URL pattern field, enter the path to a JSP page to which you want to restrict access, such as /response.jsp. Use commas to separate multiple patterns.

    3. Click OK.

    To set a security constraint by editing the deployment descriptor directly, add a security-constraint element, and inside the security-constraint element, add the following:

  1. Add a display-name element to identify the name of the constraint.

  2. Add a web-resource-collection element.

  3. Inside the web-resource-collection element, add a web-resource-name element that identifies the purpose of the collection.

  4. Add a url-pattern element inside the web-resource-collection element and enter the path to a JSP page to which you want to restrict access, such as /response.jsp.

  5. Continue to add URL patterns for all the JSP pages to which you want to restrict access.

Turning On Validation of XML Files

Your application contains one or more application configuration resource files written in XML. You can force the JavaServer Faces implementation to validate the XML of these files by setting the validateXML flag to true.

    To set the flag using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter com.sun.faces.validateXml in the Param Name field.

    2. Enter true in the Param Value field.

    3. Click OK.

    To set the flag in the deployment descriptor directly, do the following:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name com.sun.faces.validateXml.

  3. Add a param-value element to the context-param element and give it the value true. The default value is false.

Verifying Custom Objects

If your application includes custom objects, such as custom components, converters, validators, and renderers, you can verify when the application starts that they can be created. To do this, you set the verifyObjects flag to true.

    To set the flag using NetBeans IDE, do the following:

  1. Expand the node of your project in the Projects pane.

  2. Expand the Web Pages and WEB-INF nodes that are under the project node.

  3. Double-click web.xml.

  4. After the web.xml file appears in the editor pane, click General at the top of the editor pane.

  5. Expand the Context Parameters node.

  6. Click Add.

  7. In the Add Context Parameter dialog:

    1. Enter com.sun.faces.verifyObjects in the Param Name field.

    2. Enter true in the Param Value field.

    3. Click OK.

    To set the flag in the deployment descriptor directly, do the following:

  1. Add a context-param element to the deployment descriptor.

  2. Add a param-name element inside the context-param element and give it the name com.sun.faces.verifyObjects.

  3. Add a param-value element to the context-param element and give it the value true. The default value is false.

Normally, this flag should be set to false during development because it takes extra time to check the objects.

Including the Required JAR Files

JavaServer Faces applications require several JAR files to run properly. These JAR files are as follows:

The jsf-api.jar and the jsf-impl.jar files are located in as-install/lib. The jstl.jar file is bundled in appserv-jstl.jar. The other JAR files are bundled in the appserv-rt.jar, also located in as-install/lib/.

When packaging and deploying your JavaServer Faces application, you do not need to explicitly package any of the JAR files.

Including the Classes, Pages, and Other Resources

When packaging web applications using the included build scripts, you’ll notice that the scripts package resources as described here:

When packaging your own applications, you can use NetBeans IDE or you can use the build scripts included with the tutorial examples, as explained throughout the preceding chapters. You can modify the build scripts to fit your situation. However, it is recommended that you continue to package your WAR files as described in this section because this technique complies with commonly-accepted practice for packaging web applications.