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 to 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. Writing Bean Properties (page 380) explains how to write backing bean properties. Writing Backing Bean Methods (page 409) explains how to write backing bean methods. Binding Component Values and Instances to External Data Sources (page 361) 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 themanaged-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>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'svalue
attribute must match themanaged-bean-name
up to the first period. For example, this value expression maps to theshape
property of theImageArea
instance,NA
:The part before the . matches the
managed-bean-name
ofImageArea
. Adding UI Components to a Page Using the HTML Component Tags (page 316) has more examples of using thevalue
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 arenone
,request
,session
, orapplication
. If you define the bean with anone
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 ofnone
is that a managed bean references another managed bean. The second bean should be innone
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 becauseUIComponent
instances depend on running inside of a single thread.The
managed-bean
element can contain zero or moremanaged-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 amanaged-property
definition for it in your application configuration resource file.If a
managed-bean
element does not contain othermanaged-bean
elements, it can contain onemap-entries
element orlist-entries
element. Themap-entries
element configures a set of beans that are instances ofMap
. Thelist-entries
element configures a set of beans that are instances ofList
.To map to a property defined by a
managed-property
element, you must ensure that the part of a component tag'svalue
expression after the . matches themanaged-property
element'sproperty-name
element. In the earlier example, theshape
property is initialized with the valuepoly
. The next section explains in more detail how to use themanaged-property
element.Initializing Properties using the managed-property Element
A
managed-property
element must contain aproperty-name
element, which must match the name of the corresponding property in the bean. Amanaged-property
element must also contain one of a set of elements (listed in Table 13-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 13-1 lists all the elements used to initialize a value.
Using the managed-bean Element includes an example of initializing
String
properties using thevalue
subelement. You also use thevalue
subelement to initialize primitive and other reference types. The rest of this section describes how to use thevalue
subelement and other subelements to initialize properties of Java Enum types,java.util.Map
,array
, andCollection
, 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 themanaged-property
element must be aString
that matches one of theString
constants of the Enum. In other words, theString
must be one of the valid values that can be returned if you were to callvalueOf(Class, String)
on enum, whereClass
is theEnum
class andString
is the contents of thevalue
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: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 thevalue
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 calleddefaultAreaCode
to650
, add a context-param element to the deployment descriptor, give the parameter the namedefaultAreaCode
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'svalue
attribute:Retrieving values from other implicit objects is done in a similar way. See Implicit Objects (page 125) 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 ofjava.util.Map
if themap-entries
element is used within amanaged-property
element. Here is the definition ofmap-entries
from theweb-facesconfig_1_2.xsd
schema, located athttp://java.sun.com/xml/ns/javaee/
that defines the application configuration resource file:As this definition shows, a
map-entries
element contains an optionalkey-class
element, an optionalvalue-class
element, and zero or moremap-entry
elements.Here is the definition of
map-entry
from the DTD:According to this definition, each of the
map-entry
elements must contain akey
element and either anull-value
orvalue
element. Here is an example that uses themap-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 tojava.lang.String
. If you want to specify a different type for the keys in the map, embed thekey-class
element just inside themap-entries
element: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 ajava.math.BigDecimal
because it is aString
.If you also want to specify a different type for all the values in the map, include the
value-class
element after thekey-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 avalue
subelement. Thevalue
subelement defines a single value, which will be converted to the type specified in the bean.The second
map-entry
defines avalue
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 avalue
element that specifies a map-typed expression.Initializing Array and List Properties
The
list-entries
element is used to initialize the values of anarray
orList
property. Each individual value of the array orList
is initialized using avalue
ornull-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 aList
. The type of the corresponding property in the bean determines which data structure is created. Thelist-entries
element defines the list of values in thearray
orList
. Thevalue
element specifies a single value in thearray
orList
and can reference a property in another bean. Thenull-value
element will cause thesetBooks
method to be called with an argument ofnull
. Anull
property cannot be specified for a property whose data type is a Java primitive, such asint
orboolean
.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 aCustomerBean
instance that has twoAddressBean
properties: one representing the mailing address, and the other representing the street address. This declaration results in a tree of beans withCustomerBean
as its root and the twoAddressBean
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 themanaged-bean-name
ofcustomer
) creates aCustomerBean
in request scope. This bean has two properties:mailingAddress
andstreetAddress
. These properties use thevalue
element to reference a bean namedaddressBean
.The second managed bean declaration defines an
AddressBean
but does not create it because itsmanaged-bean-scope
element defines a scope ofnone
. Recall that a scope ofnone
means that the bean is created only when something else references it. Because both themailingAddress
and thestreetAddress
properties referenceaddressBean
using thevalue
element, two instances ofAddressBean
are created whenCustomerBean
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 othernone
scoped objects. Table 13-2 outlines all of the allowed connections.
You should also not allow cyclical references between objects. For example, neither of the
AddressBean
objects in the preceding example should point back to theCustomerBean
object becauseCustomerBean
already points to theAddressBean
objects.Initializing Maps and Lists
In addition to configuring
Map
andList
properties, you can also configure aMap
and aList
directly so that you can reference them from a tag rather than referencing a property that wraps aMap
or aList
.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 thebookcashier.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
callednewsletters
. This list is composed ofSelectItem
instances, which are also managed beans. See Using the selectItem Tag (page 343) for more information onSelectItem
. 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 amanaged-property
element.) Instead, the list is the managed bean.