Tuesday, October 20, 2009

Configuring Beans



Configuring Beans


This section describes how you can
configure a bean in a configuration file. The details are rather technical. You
may want to have a glance at this section and return to it when you need to
configure beans with complex properties.


The most commonly used
configuration file is WEB-INF/faces-config.xml. However, you can also place configuration
information inside the following locations:




  • Files named META-INF/faces-config.xml inside any JAR files loaded by the external context's
    class loader. (You use this mechanism if you deliver reusable components in a
    JAR file.)



  • Files listed in the
    javax.faces.CONFIG_FILES initialization parameter inside
    WEB-INF/web.xml. For example,


    <web-app>
    <context-param>
    <param-name>javax.faces.CONFIG_FILES</param-name>
    <param-value>WEB-INF/navigation.xml,WEB-INF/beans.xml</param-value>
    </context-param>
    ...
    </web-app>

    (This mechanism is attractive for builder tools because it
    separates navigation, beans, etc.)


For simplicity, we use WEB-INF/faces-config.xml in
this chapter.


A bean is defined with a managed-bean element inside
the top-level faces-config element. Minimally, you must specify the
name, class, and scope of the bean.


  <faces-config> 
<managed-bean>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>com.corejsf.UserBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


The scope can be request, session,
application, or none. The none
scope denotes an object that is not kept in one of the three scope maps. You use
objects with scope none as building blocks when
wiring up complex beans. You will see an example in the section "Chaining Bean
Definitions" on page 61.



Setting Property Values


We start with a simple example.
Here we customize a UserBean instance:


  <managed-bean> 
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>com.corejsf.UserBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>name</property-name>
<value>me</value>
</managed-property>
<managed-property>
<property-name>password</property-name>
<value>secret</value>
</managed-property>
</managed-bean>


When the user bean is first looked up, it is
constructed with the UserBean() default constructor. Then the
setName and setPassword methods are executed.


To initialize a property with null, use a
null-value element. For example,


  <managed-property>
<property-name>password</property-name>
<null-value/>
</managed-property>


Initializing Lists and Maps


A special syntax initializes values that are of type
List or Map. Here is an example of a list:


  <list-entries>
<value-class>java.lang.Integer</value.class>
<value>3</value>
<value>1</value>
<value>4</value>
<value>1</value>
<value>5</value>
</list-entries>


Here we use the java.lang.Integer wrapper type since a
List cannot hold values of primitive type.


The list can contain a mixture of value and
null-value elements. The value-class is optional. If it is
omitted, a list of java.lang.String objects is produced.


A map is more complex. You specify optional key-class
and value-class elements (again, with a default of
java.lang.String). Then you provide a sequence of map-entry
elements, each of which has a key element, followed by a value
or null-value element.


Here is an example:


  <map-entries>
<key-class>java.lang.Integer</key-class>
<map-entry>
<key>1</key>
<value>George Washington</value>
</map-entry>
<map-entry>
<key>3</key>
<value>Thomas Jefferson</value>
</map-entry>
<map-entry>
<key>16</key>
<value>Abraham Lincoln</value>
</map-entry>
<map-entry>
<key>26</key>
<value>Theodore Roosevelt</value>
</map-entry>
</map-entries>


You can use list-entries and
map-entries elements to initialize either a managed-bean or a
managed-property, provided that the bean or property type is a
List or Map.


Figure
2-7 shows a syntax diagram for the
managed-bean element and all of its child
elements. Follow the arrows to see which constructs are legal inside a
managed-bean element. For example, the second
graph tells you that a managed-property element
starts with zero or more description elements,
followed by zero or more display-name elements, zero
or more icons, then a mandatory property-name, an optional
property-class, and exactly one of the elements
value, null-value, map-entries, or
list-entries.





Figure 2-7. Syntax diagram for managed-bean
elements


[View full size image]




Chaining Bean Definitions


You can achieve more complex
arrangements by using value expressions inside the value element to chain beans together. Consider the quiz bean in
the number-quiz application.


The quiz contains a collection of
problems, represented as the write-only problems property. You can
configure it with the following instructions:


  <managed-bean>
<managed-bean-name>quiz</managed-bean-name>
<managed-bean-class>com.corejsf.QuizBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>problems</property-name>
<list-entries>
<value-class>com.corejsf.ProblemBean</value-class>
<value>#{problem1}</value>
<value>#{problem2}</value>
<value>#{problem3}</value>
<value>#{problem4}</value>
<value>#{problem5}</value>
</list-entries>
</managed-property>
</managed-bean>


Of course, now we must define beans with names
problem1 through problem5, like this:




  <managed-bean>
<managed-bean-name>problem1</managed-bean-name>
<managed-bean-class>
com.corejsf.ProblemBean
</managed-bean-class>
<managed-bean-scope>none</managed-bean-scope>
<managed-property>
<property-name>sequence</property-name>
<list-entries>
<value-class>java.lang.Integer</value-class>
<value>3</value>
<value>1</value>
<value>4</value>
<value>1</value>
<value>5</value>
</list-entries>
</managed-property>
<managed-property>
<property-name>solution</property-name>
<value>9</value>
</managed-property>
</managed-bean>



When the quiz bean is requested, then the creation
of the beans problem1 through problem5
is triggered automatically. You need not worry about the order in which you
specify managed beans.


Note that the problem beans have scope
none since they are never requested from
a JSF page but are instantiated when the quiz bean is requested.


When you wire beans together, make
sure that their scopes are compatible. Table 2-1 lists the permissible combinations.


























Table 2-1. Compatible Bean Scopes
When defining a bean of this scope
...
... you can use beans of these scopes
nonenone
applicationnone,
application
sessionnone,
application, session
requestnone,
application, session,
request



String Conversions


You specify property values and elements
of lists or maps with a value element that
contains a string. The enclosed string needs to be converted to the type of the
property or element. For primitive types, this conversion is straightforward.
For example, you can specify a boolean value with the string
true or false.


Starting with JSF 1.2, values of
enumerated types are supported as well. The conversion is performed by calling
Enum.valueOf(propertyClass,
valueText).


For other property types, the JSF
implementation attempts to locate a matching PropertyEditor. If a property editor exists, its setAsText method is invoked to convert strings to property values.
Property editors are heavily used for client-side beans, to convert between
property values and a textual or graphical representation that can be displayed
in a property sheet (see Figure 2-8).





Figure 2-8. A property sheet in
a GUI builder




Defining a property editor is
somewhat involved, and we refer the interested reader to Horstmann and Cornell,
2004, 2005. Core Java 2, vol. 2,
chap. 8.


Note that the
rules are fairly restrictive. For example, if you have a property of type
URL, you cannot simply specify the URL as a
string, even though there is a constructor URL(String). You would need to supply a property editor for the
URL type or reimplement the property type
as String.


Table
2-2 summarizes these conversion rules. They are identical to
the rules for the jsp:setProperty action of the
JSP specification.





























Table 2-2. String Conversions
Target TypeConversion
int, byte,
short, long, float, double, or the corresponding wrapper type
The valueOf method of the wrapper type, or 0 if the string is
empty.
boolean or
Boolean
The result of
Boolean.valueOf, or false if the string
is empty.
char or
Character
The first character of the string,
or (char) 0 if the string is empty.
String or
Object
A copy of the string; new
String("")
if the string is empty.
bean propertyA type that calls the
setAsText method of the property editor if it
exists. If the property editor does not exist or it throws an exception, the
property is set to null if the string is empty. Otherwise, an error
occurs.


No comments:

Post a Comment