According to the JavaBeans specification (available at http://java.sun.com/products/javabeans/), a Java Bean is "a reusable software component that can be manipulated in a builder tool." That is a pretty broad definition, and indeed, as you will see in this chapter, beans are used for a wide variety of purposes. At first glance, a bean seems to be similar to an object. However, beans serve a different purpose. Objects are created and manipulated inside a Java program when the program calls constructors and invokes methods. However, beans can be configured and manipulated without programming. NOTE | You may wonder where the term "bean" comes from. Well, Java is a synonym for coffee (at least in the United States), and coffee is made from beans that encapsulate its flavor. You may find the analogy cute or annoying, but the term has stuck. |
The "classic" application for JavaBeans is a user-interface builder. A palette window in the builder tool contains component beans such as text fields, sliders, check boxes, and so on. Instead of writing Swing code, a user-interface designer drags and drops component beans into a form and customizes them, by selecting property values from a dialog (see Figure 2-1). Figure 2-1. Customizing a Bean in a GUI Builder In the context of JavaServer Faces, beans go beyond user interface components. You use beans whenever you need to wire up Java classes with web pages or configuration files. Consider the login application in Chapter 1. A UserBean instance is configured in the faces-config.xml file:
<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> This means: Construct an object of the class com.corejsf.UserBean, give it the name user, and keep it alive for the duration of the session, that is, for all requests that originate from the same client. Once the bean has been defined, it can be accessed by JSF components. For example, this input field reads and updates the password property of the user bean.
<h:inputSecret value="#{user.password}"/> As you can see, the JSF developer does not need to write any code to construct and manipulate the user bean. In a JSF application, beans are commonly used for the following purposes: For user interface components (traditional user interface beans) For tying together the behavior of a web form (called "backing beans") For business objects whose properties are displayed on web pages For services such as external data sources that need to be configured when an application is assembled Because beans are so ubiquitous, we now turn to a review of those parts of the JavaBeans specification that are relevant to JSF programmers. Bean Properties Bean classes need to follow specific programming conventions in order to expose features that tools can use. We discuss these conventions in this section. The most important features of a bean are the properties that it exposes. A property is any attribute of a bean that has For example, the UserBean class of the preceding chapter has a property with name password and type String. The methods getPassword and setPassword access the property value. Some programming languages, in particular Visual Basic and C#, have direct support for properties. However, in Java, a bean is simply a class that follows certain coding conventions. The JavaBeans specification puts a single demand on a bean class: It must have a default constructor, that is, a constructor without parameters. However, in order to define properties, a bean must either use a naming pattern for property getters and setters, or it must define property descriptors. The latter approach is quite tedious and not commonly used, and we will not discuss it here. See Horstmann & Cornell, Core Java vol. 2 ch. 8, Sun Microsystems Press 2003 for more information. Defining properties with naming patterns is straightforward. Consider the following pair of methods:
T getFoo() void setFoo(T newValue) The pair corresponds to a read-write property with type T and name foo. If you only have the first method, then the property is read-only. If you only have the second method, then the property is write-only. The method names and signatures must match the pattern precisely. The method name must start with get or set. A get method must have no parameters. A set method must have one parameter and no return value. A bean class can have other methods, but they do not yield bean properties. Note that the name of the property is the "decapitalized" form of the part of the method name that follows the get or set prefix. For example, getFoo gives rise to a property named foo, with the first letter turned into lower case. However, if the first two letters after the prefix are upper case, then the first letter stays unchanged. For example, the method name getURL defines a property URL, and not uRL. For properties of type boolean, you have a choice of prefixes for the method that reads the property. Both
boolean isConnected() and
boolean getConnected() are valid names for the reader of the connected property. NOTE | The JavaBean specification also defines indexed properties, specified by method sets such as the following:
T[] getFoo() T getFoo(int index) void setFoo(T[] newArray) void setFoo(int index, T newValue)
However, JSF provides no support for accessing the indexed values. |
The JavaBeans specification is silent on the behavior of the getter and setter methods. In many situations, these methods will simply manipulate an instance field. But they may equally well carry out more sophisticated operations, such as database lookups, data conversion, validation, and so on. A bean class may have other methods beyond property getters and setters. Of course, those methods do not give rise to bean properties. Value Binding Expressions Many JSF user interface components have an attribute value that lets you specify either a value or a binding to a value that is obtained from a bean property. For example, you can specify a direct value.
<h:outputText value="Hello, World!"/> Or you can specify a value binding.
<h:outputText value="#{user.name}"/> In most situations, a value binding expression such as #{user.name} describes a property. Note that the binding can be used both for reading and writing when it is used in an input component, such as
<h:inputText value="#{user.name}"/> The property getter is invoked when the component is rendered. The property setter is invoked when the user response is processed. We will discuss the syntax of value binding expressions in detail starting on page 62. NOTE | JSF value binding expressions are different from the JSTL/JSP 2.0 expression language. A JSTL expression always invokes property getters. For that reason, JSF uses the #{...} delimiters instead of the JSTL ${...} syntax. |
|