The Java EE 7 Tutorial
16.4 Configuring Managed Beans
When a page references a managed bean for the first time, the JavaServer Faces implementation initializes it either based on a @Named
annotation and scope annotation in the bean class or according to its configuration in the application configuration resource file. For information on using annotations to initialize beans, see Using Annotations to Configure Managed Beans.
You can use either annotations or the application configuration resource file to instantiate managed beans that are used in a JavaServer Faces application and to store them in scope. The managed bean creation 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. For information on using this facility, see Using the managed-bean Element.
Managed beans created in the application configuration resource file are JavaServer Faces managed beans, not CDI managed beans.
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 a bean's properties without any additional code
-
Customize a bean's property values directly from within the configuration file so that it is initialized with these values when it is created
-
Using
value
elements, set a 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 and Writing Managed Bean Methods for information on programming managed beans.
16.4.1 Using the managed-bean Element
A managed bean is initiated in the application configuration resource file 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 and no bean instance exists, the JavaServer Faces implementation instantiates the bean as specified by the element configuration.
Here is an example managed bean configuration from the Duke's Bookstore case study:
<managed-bean eager="true"> <managed-bean-name>Book201</managed-bean-name> <managed-bean-class>dukesbookstore.model.ImageArea</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> <managed-property> <property-name>shape</property-name> <value>rect</value> </managed-property> <managed-property> <property-name>alt</property-name> <value>Duke</value> </managed-property> <managed-property> <property-name>coords</property-name> <value>67,23,212,268</value> </managed-property> </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.
The managed-bean-class
element defines the fully qualified name of the JavaBeans component class used to instantiate the bean.
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
.
In the following example, the newsletters
managed bean, representing a UISelectItems
component, is configured as an ArrayList
that represents a set of SelectItem
objects. Each SelectItem
object is in turn configured as a managed bean with properties:
<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 approach may be useful for quick-and-dirty creation of selection item lists before a development team has had time to create such lists from the database. Note that each of the individual newsletter beans has a managed-bean-scope
setting of none
so that they will not themselves be placed into any scope.
See Initializing Array and List Properties for more information on configuring collections as beans.
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. The next section, Initializing Properties Using the managed-property Element, explains in more detail how to use the managed-property
element. See Initializing Managed Bean Properties for an example of initializing a managed bean property.
16.4.2 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 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 16-1 lists all the elements that are used to initialize a value.
Table 16-1 Subelements of managed-property Elements That Define Property Values
Element | Value It Defines |
---|---|
Defines the values in a list |
|
Defines the values of a map |
|
Explicitly sets the property to |
|
Defines a single value, such as a |
Using the managed-bean Element includes an example of initializing an int
property (a primitive type) using the value
subelement. You also use the value
subelement to initialize String
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, Map
, array
, and Collection
, as well as initialization parameters.
16.4.2.1 Referencing a Java Enum Type
A managed bean property can also be a Java Enum
type (see http://docs.oracle.com/javase/7/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 you want to configure this property in the application configuration resource file, the corresponding managed-property
element looks 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.
16.4.2.2 Referencing a Context Initialization Parameter
Another powerful feature of the managed bean creation facility is the ability to reference implicit objects from a managed bean property.
Suppose 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 and give the parameter the name defaultAreaCode
and the value 650
.
Next, 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}"
Values are retrieved from other implicit objects in a similar way.
16.4.2.3 Initializing Map Properties
The map-entries
element is used to initialize the values of a bean property with a type of 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 created from this map-entries
tag contains two entries. By default, all the keys and values are converted to 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 you specify. The key from the example in this section cannot be converted to a BigDecimal
, because it is a String
.
If you 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.
Each 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.
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.
16.4.2.4 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
.
16.4.2.5 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 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.example.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.example.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 16-2 outlines all of the allowed connections.
Table 16-2 Allowable Connections between Scoped Objects
An Object of This Scope | May Point to an Object of This Scope |
---|---|
|
|
|
|
|
|
|
|
|
|
Be sure not to 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.