Download FAQ History |  | API Search Feedback

> ## Creating Model Objects

> Previous releases of JavaServer Faces technology required the page author to create a model object by declaring it from the page using the `jsp:useBean` tag. This technique had its disadvantages, one of which was that if a user accessed the pages of an application out of order, the bean might not have been created before a particular page was referring to it.

> The new way to create model objects and store them in scope is with the Managed Bean Creation facility. This facility is configured in the application configuration resource file (see section Application Configuration) using managed-bean XML elements to define each bean. This file is processed at application startup time, which means that the objects declared in it are available to the entire application before any of the pages are accessed.

> The Managed Bean Creation facility has many advantages over the `jsp:useBean` tag, including:

> - You can create model objects in one centralized file that is available to the entire application, rather than conditionally instantiating model objects throughout the application.
> - You can make changes to the model object without any additional code
> - When a managed bean is created, you can customize the bean's property values directly from within the configuration file.
> - Using `value-ref` elements, you can set the property of one managed bean to be the result of evaluating another value reference expression.
> - Managed beans can be created programmatically as well as from a JSP page. You'd do this by creating a `ValueBinding` for the value reference expression and then calling `getValue` on it.

> This section shows you how to initialize model objects using the `Managed Bean Creation Facility`. The section Writing a Model Object Class explains how to write a model object class. The section Binding a Component to a Bean Property explains how to reference a managed bean from the component tags.

> ### Using the managed-bean Element

> You create a model object using a `managed-bean` element. The `managed-bean` element represents an instance of a bean class that must exist in the application. At runtime, the JavaServer Faces implementation processes the `managed-bean` element and instantiates the bean as specified by the element configuration.

> Most of the model objects used with `cardemo` are still created with `jsp:useBean`. The `Storefront.jsp` page uses the `useBean` tag to declare the `CurrentOptionServer` model object:

>     <jsp:useBean id="CurrentOptionServer"
>         class="cardemo.CurrentOptionServer" scope="session"
>       <jsp:setProperty name="CurrentOptionServer"
>         property="carImage" value="current.gif"/>
>       </jsp:useBean>

> To instantiate this bean using the Managed Bean Facility, you would add this `managed-bean` element configuration to the application configuration file:

>     <managed-bean>
>       <managed-bean-name> CurrentOptionServer </managed-bean-name>
>       <managed-bean-class>
>         cardemo.CurrentOptionServer
>       </managed-bean-class>
>       <managed-bean-scope> session </managed-bean-scope>
>       <managed-property>
>         <property-name>carImage</property-name>
>         <value>current.gif</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 to map to this bean, the component tag's `valueRef` must match the `managed-bean-name` up to the first period. For example, consider this `valueRef` expression that maps to the `carImage` property of the `CurrentOptionServer` bean:

>     valueRef="CurrentOptionServer.carImage"

> The part before the "." matches the `managed-bean-name` of `CurrentOptionServer`. The section Using the HTML Tags has more examples of using `valueRef` 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 resources file. For example, the property definitions must match those configured for the bean.

> 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 when a managed bean references another `managed-bean`. The second bean should be in none scope if it is only supposed to be created when it is referenced. See Initializing Managed Bean Properties for an example of initializing a managed-bean property.

> 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. To map to a property defined by a `managed-property` element, the part of a component tag's `valueRef` expression after the "." must match the `managed-property` element's `property-name` element. In the example above, the `carImage` property is initialized with the value `current.gif`. 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 21-4 on page 817) 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 21-4 on page 817 lists all of the elements used to initialize a value.

> Table 21-4 subelements of managed-property that define property values
> element | value that it defines
> --- | ---
> `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
> `values` | defines an aggregate value, such as an array or List
> `value-ref` | references another object

> The section 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 type `java.util.Map`, `array` and `Collection`, and initialization parameters.

> #### Referencing an Initialization Parameter

> Another powerful feature of the Managed Bean 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 zip code. You can make the zip code component render with this zip code by saving it in an implicit object and referencing it when the page is rendered.

> You can save the zip code as an initial default value in the context `initParam` implicit object by setting the `context-param` element in your `web.xml` file:

>     <context-param>
>       <param-name>defaultZipCode</param-name>
>       <param-value>94018</param-name>
>     </context-param>

> Next, you write a `managed-bean` declaration with 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>zipCode</property-name>
>             <value-ref>initParam.defaultZipCode</value-ref>
>           </managed-property>
>           ...
>     </managed-bean>

> To access the zip code at the time the page is rendered, refer to the property from the `zip` component tag's `valueRef` attribute:

>     <h:input_text id=zip valueRef="customer.zipCode"

> Retrieving values from other implicit objects are done in a similar way. See Table 21-7 on page 825 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`. Here is the definition of `map-entries` from the `web-facesconfig_1_0.dtd` (located in the `<``JWSDP_HOME``>/jsf/lib` directory) that defines the application configuration file:

>     <!ELEMENT map-entries (key-class?, value-class?, map-entry*) >

> As this definition shows, a `map-entries` element contains an optional `key-class` element, an optional `value-class` element and zero or more `map-entry` elements.

> Here is the definition of `map-entry` from the DTD:

>     <!ELEMENT map-entry (key, (null-value|value|value-ref)) >

> According to this definition, each of the `map-entry` elements must contain a `key` element and either a `null-value`, `value`, or `value-ref` element. Here is an example that uses the `map-entries` element:

>     <managed-bean>
>       ...
>       <managed-property>
>         <property-name>cars</property-name>
>         <map-entries>
>           <map-entry>
>             <key>Jalopy</key>
>             <value>50000.00</value>
>           </map-entry>
>           <map-entry>
>             <key>Roadster</key>
>             <value-ref>
>               sportsCars.roadster
>             </value-ref>
>           </map-entry>
>         </map-entries>
>       </managed-property>
>     </managed-bean>

> The map that is created from this map-entries tag contains two entries. By default, the keys and values are all 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 of the keys into `java.math.BigDecimal`. Of course, you need to 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 of 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 only sets the type of all the `value` subelements.

> The first `map-entry` in the example above 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-ref` element, which references a property on another bean. Referencing another bean from within a bean property is useful for building a system out of 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 exist already.

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

> #### Initializing Array and Collection Properties

> The `values` element is used to initialize the values of an `array` or `Collection` property. Each individual value of the array or `Collection` is initialized using a `value`, `null-value`, or `value-ref` element. Here is an example:

>     <managed-bean>
>       ...
>       <managed-property>
>         <property-name>cars</property-name>
>         <values>
>           <value-type>java.lang.Integer</value-type>
>           <value>Jalopy</value>
>           <value-ref>myCarsBean.luxuryCar</value-ref>
>           <null-value/>
>         </values>
>       </managed-property>
>     </managed-bean>

> This example initializes an `array` or a `Collection`. The type of the corresponding property in the bean determines which data structure is created. The `values` element defines the list of values in the `array` or `Collection`. The `value` element specifies a single value in the `array` or `Collection`. The `value-ref` element references a property in another bean. The `null-value` element will cause the property's set 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 are also beans. 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-ref>addressBean</value-ref>
>       </managed-property>
>       <managed-property>
>         <property-name>streetAddress</property-name>
>         <value-ref>addressBean</value-ref>
>       </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, called `mailingAddress` and `streetAddress`. These properties use the `value-ref` 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 only created when something else references it. Since both the `mailingAddress` and `streetAddress` properties both reference `addressBean` using the `value-ref` 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 only point to other "none" scoped objects. Table 21-5 outlines all of the allowed connections:

> Table 21-5 Allowable Connections Between Scoped Objects
> An object of this scope | May point to a object of this scope
> --- | ---
> none | none
> application | none, application
> session | none, application, session
> request | none, application, session, request

> Cycles are not permitted in forming these connections to avoid issues involving order of initialization.

Download FAQ History |  | API Search Feedback

All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.