CHAPTER 4
Managed Beans and the JSF Expression Language

Before server-side Java development was the norm, Java developers were fully responsible for instantiating and managing the properties of every single Java class or Java Bean in their application. This was perfectly logical because applications in the early days of Java were not multi-tiered, so all the logic for the entire application resided in the application developer’s domain, often in a single virtual machine (VM).

As Java matured into more of a server-side oriented, distributed application technology, lightweight Java server containers have become prevalent because the actual plumbing needed to deliver a server-oriented application is beyond the scope of the application developer. This is what has led to the notion of Inversion of Control (IoC), where the container takes control of managing a portion of the application’s Java Beans or Plain Old Java Objects (POJOs) so the application developer needn’t write all the often-repetitive code to manage them. Inversion of control is sometimes referred to as dependency injection because one of the main benefits is the ability to have POJOs pre-populated with values through a declarative configuration syntax.

Because the JavaServer Faces framework runs entirely on a server in a servlet/JSP container, it is only natural that JSF comes equipped with a robust ability to offer Inversion of Control, where management of server-side Java Beans can be done in a highly efficient and mostly automated fashion. This is exactly what JSF provides with its Managed Beans Facility.

In the previous chapters we touched on the basics of how to register managed beans in simple applications. In this chapter we will examine in detail precisely how JSF provides an IoC-enabled container in its Managed Beans Facility, which enables you to fully leverage its strengths.

This chapter will also cover JSF’s expression language (EL) in detail because the EL is the easiest way to access and manipulate managed beans and bind them to UI components in the View. The chapter concludes with important Web development information with regards to managed beans by showing how to access and work on managed beans programmatically and by introducing the backing bean concept as well as providing a few helpful hints on how to manage backing beans and pages.

What Are Managed Beans?

JavaServer Faces managed beans are essentially POJOs that store application data and are managed by the container. They are registered with the JSF runtime via an XML file and are lazily initialized at runtime when needed by the application. Any Java class (POJO) with a public, no-argument constructor that conforms to the Java Beans naming conventions for properties can be registered as a managed bean. Objects of type java.util.List and java.util.Map can also be registered as managed beans.

A Simple Managed Bean Example

Consider again from Chapter 2 the UserBean class, which holds the registration information of a new user. As you recall, UserBean was made available to a Faces application by registering it in the faces configuration file (faces-config.xml) using the following form:

<managed-bean>
  <managed-bean-name>userBean</managed-bean-name>
  <managed-bean-class>com.jsfcompref.register.UserBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

In this example, the class com.jsfcompref.register.UserBean is registered as a managed bean named “userBean” and has its scope set to session. The scope of a bean determines its lifetime. Scope settings are discussed later in this chapter. To access properties or methods of managed beans, you will use a compact, simple-to-use expression language, which will also be explained later in this chapter.

For example, to display the current value of the firstName property of UserBean in a JSF page, you can use an <h:outputText> tag (UIOutput component) and set its value attribute with the following JSF expression #{userBean.firstName}:

<h:outputText value="#{userBean.firstName}" />

At runtime, the JSF expression allows the value of the firstName property to be displayed in the page. As we’ll review later in the chapter, the JSF expression language allows for a shorthand way to call the getFirstName( ) method of UserBean and display its value in the page using the <h:outputText> tag.

Recall that in addition to displaying the current properties of a managed bean, properties can also be updated if the managed bean has setter methods for those properties. To update properties of a managed bean, you can bind a property of the bean to a UI component that accepts an input value (implements EditableValueHolder) such as UIInput. Recall again the registration form used the UIInput component (with the JSP tag <h:inputText>) with its value attribute set with a JSF expression to accept the registrant’s input values.

<h:inputText value="#{userBean.firstName}" />

In general, during a form submission (postback), the JSF request processing life cycle updates managed bean properties with new property values from UIInput components. In this example, it causes the setFirstName( ) method on UserBean to be called. More advanced uses of the JSF expression language will be provided later in the chapter.

Table 4-1 shows the basic elements used in a managed bean registration.

Initializing Managed Bean Properties

So far you have seen how to register a simple managed bean and relied on a JSF application to display or update bean properties. However, it is also possible to supply initial values to managed beans by providing additional information in the managed bean entry in the Faces configuration file. To do so, you will use the <managed-property> element.

Image

TABLE 4-1 Elements Needed for a Basic Managed Bean Declaration

For example, to initialize the firstName and lastName properties of the userBean managed bean, you can add the following to the configuration:

<managed-bean>
  <managed-bean-name>userBean</managed-bean-name>
  <managed-bean-class>com.jsfcompref.register.UserBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
  <managed-property>
    <property-name>firstName</property-name>
    <value>Jane</value>
  </managed-property>
  <managed-property>
    <property-name>lastName</property-name>
    <value>Doe</value>
  </managed-property>
</managed-bean>

This has the effect of executing the setter methods for the firstName and lastName properties just after the bean is instantiated by the Faces life cycle. At runtime the registration form in the register.jsp page would no longer appear completely empty. As shown in Figure 4-1, the input fields bound to the pre-initialized properties will now appear with values upon an initial (non-postback) request.

Table 4-2 illustrates the elements required for initializing simple managed bean properties. A managed bean can have 0 to N sets of <managed-property> element trees.

In addition to initializing simple properties, managed beans containing java.util.List or java.util.Map properties can also be registered and initialized as managed properties. This is done by using either the <list-entries> or <map-entries> elements in a managed property definition.

Image

FIGURE 4-1 An initial request of the registration page with pre-initialized lastName and firstName

Image

TABLE 4-2 The Managed Properties Elements

Initializing List Properties

For managed beans with a property of type array or of java.util.List, the <list-entries> element can initialize values for the list. Consider a slight augmentation to the registration example from Chapter 2 where UserBean now contains a java.util.List property named sportsInterests. In keeping with the overall sports theme presented in the Virtual Trainer example application in Chapter 9, the sportsInterests list could keep track of the different types of sports that this user may be interested in training for.

Here is how to initialize a set of sports for this user by using a managed property for a List.

<managed-bean>
…
  <managed-property>
    <property-name>sportsInterests</property-name>
    <list-entries>
      <value>Cycling</value>
      <value>Running</value>
      <value>Swimming</value>
      <value>Kayaking</value>
    </list-entries>
  </managed-property>
</managed-bean>

After initializing the sportsInterests property, the list values can be displayed in a JSF page using <h:dataTable> (HtmlDataTable UI component), as shown here.

<h:dataTable value="#{userBean.sportsInterests}" var="row" >
  <h:column>
    <h:outputText value="#{row}"/>
  </h:column>
</h:dataTable>

Individual items from the list can also be displayed by using an array style element reference in the JSF expression, like this:

<h:outputText value="#{userBean.sportsInterests[0]}"/>

The preceding code displays “Cycling” on a JSF page because this was the first value in the <list-entries> list.

The different list values shown in the previous example work fine since the default data type for <list-entries> is java.lang.String. However, if another data type is needed for the list then a <value-class> is added as a child to the <list-entries> element and is used to specify the data type of the list items.

Consider a new property to the UserBean called racePlacement where the finishing order is recorded for different racing events. In this example a java.lang.Integer type is specified with a <value-class> element.

<managed-bean>
…
  <managed-property>
    <property-name>racePlacement</property-name>
    <list-entries>
      <value-class>java.lang.Integer</value-class>
      <value>23</value>
      <value>12</value>
      <value>3</value>
      <value>1</value>
    </list-entries>
  </managed-property>
</managed-bean>

In a more generalized form, Table 4-3 shows the elements associated with defining a managed property with List entries.

As mentioned before, list entries can also support array type objects. For example, if the following states array (and the corresponding getter and setter methods) are added to a managed bean:

String states[] ={ "California", "Nevada", "Oregon" };

it is then possible to initialize further properties of the managed bean like this:

<managed-bean>
…
  <managed-property>
    <property-name>states</property-name>
    <list-entries>
      <value>New York</value>
      <value>Florida</value>
      <value>Texas</value>
    </list-entries>
  </managed-property>
</managed-bean>

This also illustrates the fact that although initial values may have been set in the original code, adding additional managed property list items simply adds to the existing list. At runtime the superset of list values will be available to the application.

Image

TABLE 4-3 Managed Property Elements for a List

Initializing Map Properties

In addition to offering the ability to initialize objects of type array and java.util.List, the JavaServer Faces Managed Bean Facility also offers a way to initialize managed beans with properties of type java.util.Map. Initializing Map values is very similar to initializing List values. Instead of <list-entries> the element <map-entries> is used as a parent element of a series of key and value pairs.

Consider an example that uses a java.util.Map instead of a java.util.List to define a set of sportsInterests. In this example, the key could be a short name of the sport such as “cycling,” and the actual value could be a more verbose definition of the sport: “Any competitive athletic event where a bicycle is used.”

So, for a Map version of the sportsInterest example, you could use the following to initialize the Map values:

<managed-bean>
…
  <managed-property>
    <property-name>sportsInterests</property-name>
    <map-entries>
      <map-entry>
        <key>Cycling</key>
        <value>Any competitive athletic event where a
bicycle is used.</value>
       </map-entry>
       <map-entry>
         <key>Running</key>
         <value>Any competitive athletic event where
the competitors are running or jogging.</value>
       </map-entry>
       <map-entry>
         <key>Swimming</key>
         <value>Any competitive athletic event where
the competitors are swimmming.</value>
       </map-entry>
       <map-entry>
         <key>Kayaking</key>
         <value>Any competitive athletic event where
the competitors use a kayak.</value>
       </map-entry>
     </map-entries>
  </managed-property>
</managed-bean>

To access the individual Map values at runtime, simply use a JSF expression with a key. For example, to access the value associated to the “swimming” key, the following expression can be used.

<h:outputText value="#{userBean.sportsInterests['Swimming']}"/>

Incidentally, it is possible to display all of the key/value pairs for a Map by simply referring to the Map in the expression: #{userBean.sportInterests}. This causes the entire map to be converted to a single string that contains all keys and values.

A more formalized listing of the elements needed for a managed Map property follows in Table 4-4.

Image

TABLE 4-4 Managed Property Elements for a Map

In Table 4-4, notice that the type of the key and value are specified by <key-class> and <value-class>, respectively. However, both are optional, with both defaulting to java.lang.String. For this reason, the types of the key and value in the previous example were of the default String data type. The next example uses a key class of type java.lang.Integer. In this example, the key/value pairs consist of an integer zip code and the string name of the city in which that zip code is found.

<managed-bean>
…
  <managed-property>
    <property-name>cityRegistry</property-name>
    <map-entries>
      <key-class>java.lang.Integer</key-class>
      <map-entry>
        <key>94065</key>
        <value>Redwood City</value>
       </map-entry>
       <map-entry>
         <key>95118</key>
         <value>San Jose</value>
       </map-entry>
       <map-entry>
         <key>32801</key>
         <value>Orlando</value>
       </map-entry>
     </map-entries>
  </managed-property>
</managed-bean>

Declaring Lists and Maps Directly as Managed Beans

So far we have examined cases where existing beans had certain properties of type List or Map registered as managed properties. In fact, it is possible to declare brand new Lists or Maps as managed beans entirely from the Faces configuration file. This is achieved by assigning the <managed-bean-class> directly as either a List or a Map.

NOTE When declaring a managed bean directly as a List or a Map, you must use the concrete class types—java.util.ArrayList or java.util.HashMap—since it is impossible to call a constructor on an interface.

The following example shows a List being declared entirely as a managed bean.

<managed-bean>
  <managed-bean-name>moreSports</managed-bean-name>
  <managed-bean-class>java.util.ArrayList</managed-bean-class>
  <managed-bean-scope>none</managed-bean-scope>
  <list-entries>
    <value>Skiing</value>
    <value>Tennis</value>
    <value>Rollerblading</value>
  </list-entries>
</managed-bean>

Notice that the <managed-bean-scope> is set to none. This simply means that this managed bean is not stored anywhere. Instead, it is instantiated on the fly whenever needed. The life cycles of managed beans are examined more closely a little later in the chapter, after you have seen how managed beans can be dependent on each other.

Managed Bean Interdependence

One of the most common criteria for IoC containers is that they be able to handle interdependencies between managed objects. The JavaServer Faces Managed Bean Facility does not fall short in this regard. Setting dependencies between managed beans can easily be done using the JSF expression language.

Consider the previous example where we declared a brand new moreSports managed bean from scratch that listed a new set of sports as moreSports. This list can now be referred in another bean through an expression. For example, you can add the values from the new list to the existing sportsInterests managed bean with the final result being a set of values from both lists.

<managed-bean>
…
  <managed-property>
    <property-name>sportsInterests</property-name>
    <list-entries>
      <value>Cycling</value>
      <value>Running</value>
      <value>Swimming</value>
      <value>Kayaking</value>
      <value>#{moreSports[0]}</value>
      <value>#{moreSports[1]}</value>
      <value>#{moreSports[2]}</value>
    </list-entries>
  </managed-property>
</managed-bean>

For a more general example of managed bean interdependency, consider a new custom class of type com.jsfreg.register.Address that contains String properties for street, city and zipCode. It can be registered as an independent managed bean using:

<managed-bean>
  <managed-bean-name>addressBean</managed-bean-name>
  <managed-bean-class>com.jsfreg.register.Address</managed-bean-class>
  <managed-bean-scope>none</managed-bean-scope>
</managed-bean>

Recall that a scope of none means that this bean is not initialized until requested by another managed bean.

Next, you could add two new properties homeAddress and shippingAddress of type com.jsfreg.register.Address to the original UserBean. You can then define these properties by using the following code:

<managed-bean>
  <managed-bean-name>userBean</managed-bean-name>
  <managed-bean-class>com.jsfreg.register.UserBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
  <managed-property>
    <property-name>homeAddress</property-name>
    <value>#{addressBean}</value>
  </managed-property>
  <managed-property>
    <property-name>shippingAddress</property-name>
    <value>#{addressBean}</value>
  </managed-property>
  <managed-property>
    <property-name>firstName</property-name>
  </managed-property>
</managed-bean>

As a request is made to a page with an expression of #{userBean.homeAddress}, a new instance of UserBean is created and stored in the session scope. Its properties homeAddress and shippingAddress will also be initialized as well. Subsequent postback operations could add values to the fields of the respective addresses of type AddressBean of the UserBean, using expressions that reference the address items:

<h:inputText value="#{userBean.homeAddress.street}"/>

The next question regarding managed bean interdependence is whether cyclical dependencies are possible with managed beans. Although some other IoC containers can handle cyclical dependencies, this is not the case for JSF managed beans. If two are made dependent on each other, a runtime error will occur.

Setting Managed Properties Using EL

An important point to note is that in addition to offering the ability to establish inter-bean dependencies using EL, it is also possible to set managed properties to any value accessible via EL. For example, the implicit object param can be used in an EL expression to set a property. This can be a handy trick that allows the application to assign a property based on an incoming Request parameter. As an example, consider if the previous UserBean had a property, userid, also of type String. It could be set as a managed property using a value from the implicit param object.

<managed-property>
  <property-name>userid</property-name>
  <value>#{param.userid}</value>
</managed-property>

In your JSP you could value-bind this property to a UI component:

Userid entered:<h:inputText value="#{UserBean.userid}"/>

To provide a value, of course, you would have to add the userid value as a request parameter:

http://host:port/yourapp/faces/yourpage.jsp?userid=cschalk

You can now see that it is possible to declare the entire initial state of your model tier using the managed bean facility. This makes for a very powerful and flexible system.

Controlling Managed Bean Life Spans

Similar to standard JSP, JavaServer Faces provides a way to define the scope of a managed bean instance by using a scope setting. A scope defines the lifetime of a bean, and is similar to the concept of scope in the Java language. In contrast to JSP, however, there is no “page” scope because managed beans have to exist and be accessible on postback, which is outside the scope of JSP. As you have seen in previous managed bean examples, the <managed-bean-scope> element of a managed bean defines how long the instance of the managed bean will survive. The different managed bean scopes are described in Table 4-5.

EXPERT GROUP INSIGHT Note the conspicuous absence of the page scope, which is present in JSP. This was intentional to avoid introducing any dependency on the JSP specification in the core JSF specification. The main reason for avoiding all such dependencies was to enable alternate page description technologies, aside from JSP, to be used with JSF. This topic is covered in detail in Chapter 12.

When dealing with managed beans’ different scopes, it is important to remember that managed beans can only reference other managed beans whose scope is either none or is greater than or equal to the calling bean’s scope. This is described in Table 4-6.

A final word on scopes in general: It’s best to put your beans in the narrowest scope possible, preferably request. Doing so helps prevent memory leaks by allowing the data to be garbage collected frequently, it encourages keeping your design lightweight because putting lots of data into the request each time is costly, and, most importantly, it cuts down on difficult to debug concurrency bugs that can happen when using session and application.

Image

TABLE 4-5 JSF Managed Bean Scopes

JSF 1.2 TIP Java EE 5 Annotations are for use in managed beans. There are two kinds of annotations you can use in a JSF managed bean: lifecycle annotations, and data access annotations. Let’s discuss the former first.

Any scoped managed bean method annotated with @PostConstruct will be called after the managed bean is instantiated, but before the bean is placed in scope. Such a method must take no arguments, return void, and may not declare a checked exception to be thrown. The method may be public, protected, private, or package private. If the method throws an unchecked exception, the JSF implementation must not put the managed bean into service and no further methods on that managed bean instance will be called. Any scoped managed bean method annotated with @PreDestroy will be called before the bean is removed from the scope or before the scope in which the bean resides is destroyed, whichever comes first. The constraints placed on the method are the same as with @PostConstruct. If the method throws an unchecked exception, the implementation may log it, but the exception will not affect the execution in any way.

The data access annotations are: @Resource, @Resources, @EJB, @EJBs, @WebServiceRef, @WebServiceRefs, @PersistenceContext, @PersistenceContexts, @PersistenceUnit, and @PersistenceUnits. Usage of these annotations are beyond the scope of this book, but the @PersistenceContext annotation is particularly useful in gaining access to the Java Persistence API from your managed beans.

Image

TABLE 4-6 Scope Compatibility

The JSF Expression Language

In the preceding examples (and in earlier chapters) you saw how to access managed bean properties and invoke managed bean custom (action) methods using special expressions with delimiters #{ and }. These expressions follow syntactic rules defined by the Expression Language Specification. Let’s now take a closer look at the expression language in JavaServer Faces.

One thing to understand at the outset is that there are differences between the expression language for JSF 1.1 and the expresssion language for JSF 1.2. In the following discussion, the key differences between the expression language for JSF 1.1 and JSF 1.2 are described.

Important Expression Languages Changes Between JSF 1.1 and JSF 1.2

The most fundamental difference between JavaServer Faces versions 1.1 and 1.2 is the introduction of the Unified EL Specification. With JSF 1.1, a JSF-specific implementation of EL was created and although very similar to other EL implementations, such as those used by JSP 2.0 and the JSP Standard Tag Library (JSTL), it still had significant differences. Because expression languages had become an increasingly popular and well-utilized technology across the Java Web tier, it was decided to generalize the EL concepts introduced specifically by JSF so that they could be used by a wider set of Java Web-tier technologies. This resulted in the creation of the Unified EL.

EXPERT GROUP INSIGHT The Unified EL is now provided by the JSP 2.1 specification, though it is specified in a separate sub-document in that specification. This was done to facilitate eventually separating the Unified EL out into its own JCP specification for use by the entire Java platform. Also, separating the EL from the specific technology hosting it, such as the Java Web tier, means that several important concepts that were formerly in the domain of the EL, such as the notion of scope, are now outside of the EL proper and reside only in JSP or JSF. Even so, the rest of this discusson will treat these concepts as if they are a part of the core EL.

JSF 1.1 developers needn’t worry about having to change the syntax of their expressions to upgrade to 1.2, because the Unified EL accepts syntax compatible with JSF 1.1. For example, the following still holds true:

• JSF 1.2 expressions still use delimiters #{ and }.

• Expressions starting with #{ are still evaluated at runtime, which is referred to as deferred evaluation. Expressions starting with ${ are still evaluated at page compile time and are referred to as immediate evaluation.

JSF 1.2 TIP The JSF 1.1 expression language is upwardly compatible with JSF 1.2.

Examining the Evolution of the EL: Deferred vs. Immediate Expressions

The EL used in JSF 1.0 and 1.1 is an extension of the EL first used in the JSP Standard Tag Library (JSTL), and later in JSP versions 1.2 and 2.0. The main extension brought to the EL by JSF that is not present in previous versions is the concept of deferred expressions. In JSP, any ${} expression that appears in the page is evaluated immediately as the page is rendered. If an expression appears as the value of a JSP tag attribute, such as:

<c:set var="name" value="Falstaff" scope="page" />
<demo:customTag value='${pageScope.name}' />

then the JavaBeans property named value in the CustomTag.java tag handler class must have a type that matches the type to which the expression evaluates. Furthermore, the expression ${pageScope.name} is evaluated immediately when the demo:customTag tag is encountered and the setValue( ) method of the CustomTag.java tag handler receives the evaluated value.

Immediate evaluation is perfectly adequate for JSP, but JSF needed something more. JSF introduced the request processing lifecycle (described in Chapter 3), which governs what happens when the form is submitted (postback). During a postback, the JSP page that rendered the markup that is being posted back is not known and not available to the JSF runtime, therefore any expressions in that page are not available since they were evaluated immediately when the page was rendered.

JSF introduced the deferred expression concept to allow expressions to be useful both during the rendering of the page, and during a postback. This concept allows a deferred expression, such as #{user.name}, to show a value to the user, and also to be the “target” of a value entered by the user. As described earlier, JSF reserves the #{} delimiter to mean “deferred expression” and allows JSP to claim ${} to mean “immediate expression.” The #{} delimiter was chosen because it prevents the JSP runtime from evaluating the expression, allowing the JSF JSP Custom Tag handler to create the expression instance and store it in the component for later evaluation.

Figure 4-2 illustrates the evolution of the EL over time. The Unified EL used in JSF 1.2, JSP 2.1, and JSTL 1.2 adds the concept of deferred expression and allows JSP to be aware of deferred and immediate expressions.

Image

FIGURE 4-2 The evolution of the EL over time

EXPERT GROUP INSIGHT In keeping with the design goal of being extremely extensible, it is possible to customize the semantics of the EL since the beginning of JSF. For more on how to do so, please see Chapter 12.

Unified EL Concepts

The goal of having a Unified EL is to provide an easy and compact way to access application objects from any point in the application. A major force behind the need for a compact language to refer to objects was the increased usage of tag attributes in JSP or, in general, XML. Consider a tag with an attribute:

<MyTag attribute="value" />.

If value had to be derived dynamically at runtime, it could necessitate a long Java statement to obtain the value. Expression language provides a solution to this by:

1. Eliminating the need to always refer to container-managed parent objects (request, session, and application).

2. Shortening the expression by omitting get and set from object properties/methods.

3. Allowing navigation of an arbitrarily complex hierarchy of JavaBeans objects.

Value Expressions

Value expressions (referred to as Value Binding Expressions in JSF 1.1) are by far the most common usage of expressions in JSF applications. They allow for presenting (getting) dynamically evaluated results or setting bean properties at runtime using a compact expression. Value expressions can be used to evaluate a single value such as the value of a property of a managed bean or an expression that evaluates a final value from multiple sources including sources outside of Faces managed beans. Recall an expression used in previous examples:

<h:outputText value="#{userBean.firstName}"/>

The expression #{userBean.firstName} is a shorthand way to call the getfirstName( ) method of the userBean managed bean. In general, value expressions are evaluated behind the scenes by a getValue( ) method from a ValueExpression instance that is provided by the JSF runtime.

What Really Happens When an EL Expression Is Evaluated

As the expression #{userBean.firstName} is evaluated at runtime, the EL system breaks the expression down into two parts. The part before the first dot (or square bracket) is called the base. In this case, the base is userBean. The part after the first dot (or square bracket) is called a property and is recursively broken down into smaller parts; in this case it is just firstName. Generally, the base says where to look for the bean instance and the property parts are interpreted as beans properties to get from the base. The first thing the EL does is check if the value of the base is one of the implicit objects (described shortly). In this case, it is not, so the EL sets about looking for userBean in progressively wider scopes. It does this by first calling getAttribute(“userBean”) on the ServletRequest. Because the userBean managed bean was declared in the session scope, it is not found in the ServletRequest. The EL then calls getAttribute(“userBean”) on the HttpSession. In this case, the bean is found, so it is returned. (If the bean had not been found in the session, getAttribute(“userBean”) would have been called on the ServletContext for this application.) Once the EL has obtained the base it then proceeds to resolve properties against the base. With firstName, the getFirstName( ) method is called on the UserBean instance.

In addition to simply displaying dynamically derived values from value expressions, the output of a value expression can also be used to set an attribute of a UI component. A common usage is to set the rendered attribute to a value expression that evaluates to a boolean value. Consider the example:

<h:outputText rendered="#{userBean.manager}" value="#{Employee.salary}"/>

Notice the rendered attribute is defined with a value expression that derives a boolean value (assuming the manager field is of type boolean) by calling the method isManager( ). This allows the UIOutput component to render conditionally based on whether or not the user is a manager.

Using Value Expressions to Update Model Data

Using expressions to display values in a Web page is nothing new. Indeed, the original EL in early versions of JSTL had this feature. The new feature introduced by JSF is the ability to use an expression to set a value when a form is submitted. This means value expressions can be used for updating Model objects. For example, if an input UI component (implements EditableValueHolder) is value bound to a managed bean property (Model object), upon postback the bean property will take on the updated value applied to the UI component. This occurs during the Update Model Values phase of the JSF request processing life cycle. Recall the input example from earlier in the chapter:

<h:inputText value="#{userBean.firstName}"/>

During a postback, if the value in the input field has changed, the new value will be applied to the managed bean (UserBean). This is handled behind the scenes by the setValue( ) method on the same ValueExpression (ValueBinding) instance calling userBean’s setFirstName( ) method.

Other new features introduced by JSF include the ability to get a type of an EL expression as well as to find out if an EL expression is read-only or read-write.

Value Expression Syntax

So far you have seen only very basic examples of value expressions. Let’s examine some more complex examples.

Recall the usage of a single dot (.) operator in previous examples. With EL it is also possible to use consecutive dot operators to traverse object hierarchies as shown in the expression:

<h:outputText value=="#{userBean.homeAddress.street}"/>

In this case the dot operator successively calls the getter methods, getHomeAddress( ) and getStreet( ), as it traverses down the object hierarchy to retrieve a final value.

To access elements of an array or collection you can use brackets ([ ]) in the expression. Recall the expressions that were used in the managed property list for sportsInterest:

…
  <value>#{moreSports[0]}</value>
  <value>#{moreSports[1]}</value>
  <value>#{moreSports[2]}</value>

This example also shows how JSF EL can be used outside of a JSP or a UI component. In this case, it was used in faces-config.xml.

In general square brackets can be used in both JavaBeans and Maps as well. Bracket syntax is really the core, primitive way to access properties and the dot syntax is provided as an easy-to-use alternative for simple property names.

In addition to user-created application objects, implicit objects are also accessible via value expressions. An implicit object is managed by the container. Table 4-7 lists the implicit objects along with a usage example.

Image

TABLE 4-7 Implicit Objects Available via EL

All of the above properties that are of type Map can be accessed using the #{MapObject[‘key’]} expression form. For example, to display a request parameter, userid, in a JSF page, you can use

<h:outputText value="#{param['userid’]}" />

or

<h:outputText value="#{param.userid}" />

Expression Operators

In addition to the [ ] and . operators used in some previous examples, the EL specification defines several other useful operators. These operators can be categorized into the following types: arithmetic, relational, logical, conditional, and empty. Table 4-8 shows these operators.

Here are some EL operator examples:

<h:outputText rendered=" #{userBean.serviceLevel == 'Premium'}"
value ="Congratulations, Premium members receive a
#{Discounts.basicDiscount * 10}% discount!" />

The discount example renders only for Premium members and provides them with a discount percentage ten times the basic discount value.

To show city temperatures in both Fahrenheit and Celsius, one can use:

<h:outputText value="Temperature for #{cityRegistry.city.name} is:
Fahrenheit: #{cityRegistry.city.fahrenheitTemp} Celsius:
#{(cityRegistry.city.fahrenheitTemp - 32) * 5 / 9}">

Method Expressions

Method expressions are similar to value expressions but instead of being used to retrieve and set managed bean (object) properties, method expressions are used to invoke public, non-static methods of managed beans. Recall the example in Chapter 2 where a method expression was bound to a commandButton:

<h:commandButton value="Confirm" action="#{userBean.addConfirmedUser}" />

Image

TABLE 4-8 EL Operators

When clicked on, the method addConfirmedUser( ) is invoked as a result of the Confirm button being clicked.

Method expressions use a subset syntax of value expressions where only the dot operator or bracket operator([ ]) is used to traverse the object hierarchy to access a public non-static method. The other operators do not apply for method expressions.

Invocation of Methods via Method Expressions Note that the EL does not include a way to pass arguments to methods. This is intentional to keep the EL as simple as possible.

EXPERT GROUP INSIGHT The Expert Group considered adding the ability to pass parameters to MethodExpressions in the EL but this was abandoned because it was felt this would encourage the bad coding practice of putting business logic directly into the page. The designers had learned their lesson from the abuse of Scriptlet technology, and didn’t want to repeat their mistake.

When used from a JSP page, the arguments to the MethodExpression depend on the context in which the expression is used. Table 4-9 provides the method expression details of the standard tags with the ActionSource (ActionSource2) behavioral interface. It lists the arguments and return type to which the method pointed to by the MethodExpression must conform. It also lists the tags and tag attributes for the MethodExpression.

Table 4-10 shows the standard tags/UI components with the EditableValueHolder behavioral interface and their method expression details. The single tag attribute, valueChangeListener, is bound to a value change listener method, which accepts a ValueChangeEvent argument and has a return type of void.

The standard tag f:view with its (JSF 1.2 only) attributes and method expression details are displayed in Table 4-11.

EXPERT GROUP INSIGHT To demonstrate the value of having a diverse community of experts developing the JSF specification, the entire concept of MethodExpressions and making them invokeable in response to a button press on a form came from Expert Group members who are part of the tool development community. This is one example of how the design of JSF is very tool friendly, but it is by no means designed exclusively for tools.

Image

TABLE 4-9 ActionSource (ActionSource2) Standard Tags Method Expression Details

Image

TABLE 4-10 EditableValueHolder Standard Tags Method Expression Details

Note that the action attribute of tags that represent ActionSource components is special in that it can accept a literal string, or a MethodExpression as listed in the table. If given a literal string, the EL creates a special MethodExpression that simply returns the literal string. In this way, you can manually specify a navigation outcome. Navigation is covered in detail in Chapter 5.

Web Application Development Details on Managed Beans

Before concluding this chapter, it is necessary to examine two important higher-level application development concepts with managed beans. The first is how to access/update managed beans programmatically from Java directly. The second is the backing bean concept.

How to Access Managed Beans Programmatically

Although you have seen many examples that access and update managed bean properties, in both pages and in the faces configuration file, there is still one important thing to cover: how to access managed beans programmatically. To understand why this is important, consider the following scenario. Assume that a user has logged into an application. While that user is logged in, his or her personal information is stored in a managed bean with a scope setting of session, so it will remain alive during the life of the session. If a custom method needs to access any user-specific information, such as the user’s userid or first name/last name, this can be done programmatically using the following Java code in JSF 1.1:

Image

TABLE 4-11 The Standard Tag f:view and Its Method Expression Details

FacesContext context = FacesContext.getCurrentInstance();
ValueBinding currentBinding =
context.getApplication().createValueBinding("#{userBean.userid}");
String userid = (String) currentBinding.getValue(context);

To update this value, one can use the following:

currentBinding.setValue(context, "NewUserId");

Note that the entire UserBean instance can be retrieved by using the expression #{userBean} without any properties.

FacesContext context = FacesContext.getCurrentInstance();
ValueBinding currentBinding =
context.getApplication().createValueBinding(#{userBean});
UserBean myUserBean = (UserBean) currentBinding.getValue(context);

A slightly simpler variation is:

FacesContext context = FacesContext.getCurrentInstance();
UserBean myUserBean =
context.getApplication().getVariableResolver().resolveVariable(context, "userBean");

While the preceding Faces 1.1 code also works fine in a JSF 1.2 environment, you will see deprecated messages when you compile it. To avoid these messages, use the following (Faces 1.2) syntax for accessing managed beans programmatically in a 1.2 environment:

ELContext elContext = context.getELContext();
Application application = context.getApplication();
String userid = (String) application.evaluateValueExpressionGet(context,
"#{userBean.userid}",String.class);

To set the get or set the value, use:

ExpressionFactory expressionFactory = application.getExpressionFactory();
ValueExpression ve =.expressionFactory.createValueExpression(elContext,
"#{userBean.userid}",String.class);
userId = (String) ve.getValue(elContext);
ve.setValue(elContext, "newUserId");
Invoking a Method on a Managed Bean Programmatically

In addition to just accessing values of managed bean properties, JSF also provides a way to invoke a method of a managed bean. For example, if you want to execute the method addConfirmedUser( ), which was introduced in the JSFReg application in Chapter 2, you would use the following:

Application application = FacesContext.getCurrentInstance().getApplication();
MethodBinding mb = application.createMethodBinding("#{UserBean.addConfirmedUser}",
null );

try
  {
    mb.invoke(context, null);
  }
catch (EvaluationException e)
  {
    Throwable wrapped = e.getCause();
  }

Notice in the previous code listing that the method addConfirmedUser( ) did not take any arguments so the second argument of the invoke( ) was null. However, if the addConfirmedUser( ) method accepted arguments that included a custom UserInfo object as well as an Id of type String, the Faces 1.1 method binding code would be as follows:

Object result = null;
MethodBinding mb = application.createMethodBinding(
    "#{UserBean.addConfirmedUser }",
    new Class [] { UserInfo.class, String.class} );

try
  {
    result = mb.invoke(context, new Object [] { UserInfo(),"joe.shmoe" });
  }
catch (EvaluationException e)
  {
    Throwable wrapped = e.getCause();
  }

Notice also that it is possible to retrieve the results of a method binding invocation shown here using result to store the return value. Here is how this method invocation is done in Faces 1.2:

…
elContext = context.getElContext();
MethodExpression me =
  expressionFactory.createMethodExpression(elContext,
    "#{UserBean.addConfirmedUser }", Void.TYPE,
    new Class [] { UserInfo.class, String.class});

try
  {
    result = me.invoke(elContext, new Object [] { UserInfo(), "joe.shmoe" });
  }
catch (ELException ele)
  {
    Throwable wrapped = ele.getCause();
  }

Note that any exception thrown by the invoked method is wrapped in an EvaluationException in Faces 1.1 and an ELException in the Faces 1.2 Unified EL. The cause must be extracted from these exceptions to see what really happened in the invoked method.

Further coverage of accessing managed beans programmatically is provided in Chapter 9 where the Virtual Trainer example application is reviewed in detail. Chapter 10 also shows how to create custom components that accept method expressions.

Using Managed Beans as Backing Beans for JSF Pages

Users of Microsoft Visual Basic or ASP.Net are familiar with the notion of having an associated source code file (or class) that provides the “back-end plumbing” that handles events, updates data, and so on for a specific page. This is known as the backing bean concept, and although not specifically required by the Faces specification, it is fully supported and recommended in most cases. In fact, several JSF-enabled integrated development environments (IDEs) enable or, in some cases, force this programming style on the developer. (You will see examples of this in Chapter 17 when we examine JSF development with several JSF-enabled IDEs.)

To implement a backing bean approach in JSF, you can create a Java class for each JSF page and register it as a managed bean. It is recommended that backing beans be declared to be in request scope. The most preferred usage is to have a single backing bean per page although this is not enforced by any specification. A common usage is also to name the class the same name as the page. For example, login.jsp would have an associated backing bean of Login.java. Placing the backing bean classes in a sub-package of “.backing” is also useful. Finally, the backing beans can also be registered in the faces-config.xml with “_Backing” added to their names so you always know which beans are backing beans.

In general the backing bean holds the following artifacts for a page:

• Properties corresponding to input fields on a page, such as string properties for userid and password.

• Action methods and action listeners that correspond to UI components that initiate action events, such as clicking on Register or Next Page buttons.

• Declarations of UI component instances that can be directly bound to the UI components used on the page. (We’ll drill down on this usage in more detail in Chapter 6.)

In short, it is the responsibility of the backing bean to serve as a conduit from the page to server-side application logic. In other words, it serves as the “middle man” between the page and the back-end business logic. A typical set of pages and their corresponding backing beans that link to back-end business logic is shown in Figure 4-3.

To get a better idea of how the backing bean concept works, consider a typical login example. In this example you could have a page (login.jsp), which is built with a collection of UIInput components (input fields) to accept the login credentials. In this example, the backing bean can be a Java class, Login.java, which has a corresponding set of JavaBean properties (of type String) for temporarily storing the user’s login credentials. To handle the user’s button click on a Login button (UICommand), an action method, checkUserCredentials( ), could be invoked. It could then call a back-end business method that performs a database or LDAP lookup of the user to determine whether the credentials are valid. Figure 4-4 illustrates this example.

Image

FIGURE 4-3 The backing bean concept illustrated

Here is a more advanced example of backing bean usage where a page, employees_table.jsp, displays a scrollable table of employee information using a corresponding backing bean, EmployeesTable.java. In this example, the JSP page uses an HtmlDataTable (<h:dataTable/>) component to display a table of employee records. It also uses a custom Scroller UI component that works with methods in the backing bean to handle scrolling events such as next page, previous page, first, and last to navigate through the data being displayed by the table component. The JSP page could also have columns for row-level operations such as Edit and Delete. When the user clicks Edit, he or she would navigate to a different page to edit the row values in a form. Clicking on Delete would simply delete the selected record and remain on the same page. For this example, the backing bean (EmployeesTable.java) would most probably have the following:

• Any Java bean properties that are value bound to components in the page. In this example the <h:dataTable> (HtmlDataTable) component could be value bound to a Java bean property that returns either a List, Result, ResultSet, or an Array. For example:

Image

FIGURE 4-4 The backing bean concept shown in a login example

<h:dataTable value=“#{EmpTable_Backing.empList}” /> This is where the tabular data is initially retrieved; however, to manipulate the data, such as scrolling and so on, the HtmlDataTable component on the page can also be directly bound to a declared instance of UIData (or HtmlDataTable), which has the necessary methods to navigate through the tabular data.

• At least one instance of a UIData (or HtmlDataTable) component that is directly bound to the DataTable on the page such as: <h:dataTable value=“#{TrainingEventRegistry.eventlist}” binding=“#{EmpTable_Backing.tableData}” /> In this example EmpTable_Backing.tableData is of type UIData and is used to perform data navigation operations on the tabular (List) data that was value bound to HtmlDataTable.

• An action listener method for handling table events such as scrolling through data.

Figure 4-5 illustrates our example where we have an HtmlDataTable component that is bound to both a UIData instance as well as value bound to a method that returns a List.

For more detailed UIData and HtmlDataTable examples, Chapter 9, which illustrates the Virtual Trainer example application, includes complete coverage of working with tabular data in Faces applications, including how to perform data navigation (scrolling) as well as inserting, updating, and deleting data associated with HtmlDataTable components.

Before concluding the chapter, here is a final thing to consider when using backing beans. It is possible to have more than one backing bean per page, or have multiple pages bound to properties of a single bean as there is no specified rule on this. This is left to the developer’s discretion, but having numerous dependencies between multiple pages and multiple backing beans can become very hard to manage. However, it’s still technically okay to have separate request-scoped managed beans for sub-sections of your page that get included and reused across multiple pages. Again, these are design considerations where the Faces application architect will have to weigh the benefits of standard OOP reuse mechanisms against raising the overall application architecture complexity.

Image

FIGURE 4-5 An HtmlDataTable bound to a UIData instance and a List