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:

  • Create beans in one centralized file that is available to the entire application, rather than conditionally instantiate beans throughout the application.

  • Customize the bean's properties without any additional code.

  • Customize the bean's property values directly from within the configuration file so that that it is initialized with these values when it is created.

  • Using value elements, set the property of one managed bean to be the result of evaluating another value expression.

This section shows you how to initialize beans using the managed bean creation facility. See Writing Bean Properties (page 390) and Writing Backing Bean Methods (page 418) for information on programming backing beans. Binding Component Values and Instances to External Data Sources (page 371) 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 5.5, you can add a managed bean declaration by doing the following:

1.

After opening your project in NetBeans 5.5, 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:

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

b. Click Browse to locate the bean's class.

7.

In the Browse Class dialog:

a. 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.

b. Select the class from the Matching Classes box.

c. Click OK.

8.

In the Add Managed Bean dialog:

a. Select the bean's scope from the Scope menu.

b. Click Add.

9.

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

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 (page 326) 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 (page 467) 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 131) 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 131 lists all the elements used to initialize a value.

Table 131. Subelements of managed-property Elements That Define Property Values

Element

ValueThat 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 (page 460) 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/j2se/1.5.0/docs/api/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 (page 130) 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 132 outlines all of the allowed connections.

Table 132. 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 (page 353) for more information on SelectItem. Note that, unlike the example in Initializing Map Properties (page 465), 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.



The JavaT EE 5 Tutorial
The JavaT EE 5 Tutorial
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 309

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net