[ Team LiB ] Previous Section Next Section

The jsp:useBean Action

JSP scriptlets, expressions, and declarations provide you with a way to access JavaBeans. Pages that use the actions that define these elements, however, tend to look cluttered. You would be better off accessing JavaBean properties in a JSP using actions that look like a few extra actions in a normal HTML page.

The jsp:useBean action gives you the ability to create JavaBeans, and the jsp:getProperty and jsp:setProperty actions allow you to manipulate bean properties. Let's take a moment to examine each of these.

When you want to use a JavaBean within a JSP, use the jsp:useBean action to either create a new instance of the bean or to use an existing bean. The idea behind the jsp:useBean action and its associates is that you should try to move as much of your application logic as possible out of your JSP so all that remains is code to display the output.

When you encapsulate business objects or business logic into a Java class, you should make that Java class a bean. Many of Sun's Java APIs and tools revolve around the idea that you put your logic into beans and then use tools to help you create applications that use those beans. JSP is one of those tools.

Adding the Bean to the Page

When you add a bean to a JSP, you can either create a new bean or use an existing one. The JSP engine determines whether it needs to create a new bean for you based on the bean's ID.

When you add a bean to a page, you must at least give the bean an ID, which is just a name and the bean's class, like this:


<jsp:useBean id="myBean" class="examples.TestBean"/>

The JSP engine first searches for an existing bean with the same ID (myBean in this case). If it doesn't find an existing bean, the JSP engine creates a new instance of the class you specified. Where the JSP engine looks to find existing beans depends on the bean's scope.

Using the useBean ID to Access a JavaBean Instance

graphics/bytheway_icon.gif

The JSP compiler creates a variable with the same name as the ID specified in the jsp:useBean element. You can also use this ID in any Java code you put in your JSP. For instance, if you instantiated a bean with an ID of myBean, you could write an expression like <%= myBean.getFirstName() %>.


One of the other options you can use in the jsp:useBean element is scope. The scope determines where the JSP engine stores a created bean and also where it looks to see whether a particular bean ID already exists. A bean can have a scope of page, request, session, or application. A bean with a scope of page is visible on the current JSP only and disappears when the page finishes executing or forwards itself to another JSP or to a servlet. If you do not specify a scope for a bean, the default scope is page.

A bean with request scope is visible to other JSPs and servlets and is stored in the request object. You can use the bean's ID to get the bean instance out of the request with the getAttribute method. For example, suppose you set up the following bean in a JSP:


<jsp:useBean id="myBean" scope="request" class="examples.TestBean"/>

Now, suppose you want to include a servlet or forward the request on to a servlet, and the servlet needs to access your bean. The servlet would access the bean this way:


examples.TestBean theBean = request.getAttribute("myBean");

Because the request object disappears when the request completes, it should be obvious that a bean stored in the request is no longer visible.

Beans with session scope are stored in the session object. Suppose you created the following bean:


<jsp:useBean id="mySessionBean" scope="session" class="examples.TestBean"/>

You could access this bean from a servlet this way:


HttpSession session = request.getSession();
Examples.TestBean theBean =
      session.getAttribute("mySessionBean");

Finally, beans with application scope are stored in the application object, which is actually a ServletContext object. Like anything else stored in the application object, a bean with application scope is visible to any other JSP or servlet within the same application.

Servlets Can't Access JSP Page-Scoped Objects

graphics/didyouknow_icon.gif

There is no servlet equivalent for accessing a bean stored with page scope because the page scope implies that the bean is visible only within the page. After you leave the page to go to a servlet, you can't access the bean.


In Case of Trouble

graphics/bytheway_icon.gif

If you are having trouble locating existing bean objects, see the "Q&A" section at the end of this hour.


Getting Bean Properties

So far, you know how to put a bean on a page. Now you need to do something with it. Obviously, you must put data into the bean, get data out of the bean, or both. Use the jsp:getProperty action to get information from a bean. The syntax of jsp:getProperty is simple:


<jsp:getProperty name="beanId" property="propertyName"/>

The jsp:getProperty action automatically inserts the property value into the JSP's output. It works like the <%= tag in that respect. In fact, for a bean stored in the request object, here are two identical ways to display one of the bean's properties:


<jsp:getPropery name="myBean" property="firstName"/>

<%= ((examples.TestBean) request.getAttribute("myBean")).
    getFirstName() %>

As you can see, the jsp:getProperty action takes care of fetching the bean from wherever it is stored, casting it to the appropriate type, and invoking the property's accessor method.

Because the jsp:useBean action also creates a variable with the same name as the bean, you could also use the following expression:


<%= myBean.getFirstName() %>

The main reason you would choose the jsp:getProperty action over the <%= action is that the jsp:getProperty action is language independent. Although the focus of this book is on using Java as the JSP scripting language, the JSP specification allows for other scripting languages, such as JavaScript. Although the expression <%= myBean.getFirstName() %> works for JavaScript, it probably wouldn't work for other scripting languages. If you used Smalltalk as a scripting language, the expression would be something like <%= myBean firstName %>. You can be sure that jsp:getProperty will work no matter which scripting language you are using.

Another reason you would choose to use the former method to access a bean property is because it's similar to the appearance of other tags on the page.

Setting Bean Properties

Obviously, if you can get bean properties from a JSP, you need to set them, too. The jsp:setProperty action enables you to set bean properties and provides some useful shortcuts for copying parameter values into a bean.

The basic syntax for setting a bean property is


<jsp:setProperty name="beanName" property="propertyName"
    value="propertyValue"/>

You can even use the <%= tag inside the jsp:setProperty action this way:


<jsp:setProperty name="myBean" property="name"
    value="<%=myName%>"/>

You can use jsp:setProperty to set the value of string properties and certain data types that can be converted from a string. Table 14.1 lists the data types that are automatically converted and the method used to convert them.

Table 14.1. Automatic Type Conversions Performed by jsp:setProperty

Java Type

Conversion Method

boolean or Boolean

Boolean.valueOf

byte or Byte

Byte.valueOf

char or Character

Character.valueOf

double or Double

Double.valueOf

float or Float

Float.valueOf

int or Integer

Integer.valueOf

long or Long

Long.valueOf

For example, if your bean includes the following set method:


public void setAge(int age)

You can safely set the age this way:


<jsp:setProperty name="myBean" property="age" value="35"/>

The string "35" is automatically converted to an integer when the JSP engine sets the property.

Setting Properties Directly from Parameters

One of the great features of jsp:setProperty is that it recognizes the frequent need to copy values out of form variables and into beans. You can automatically copy a parameter into a bean property this way:


<jsp:setProperty name="myBean" param="paramName"
    property="propertyName"/>

If the property name is the same as the parameter name, you can omit the parameter name:


<jsp:setProperty name="myBean" property="propertyName"/>

The presence or absence of the value keyword in jsp:setProperty determines whether the JSP engine uses a specific value or gets the value from a parameter. You can't have both a value and a param attribute in a single jsp:setProperty.

Null Parameters and jsp:setProperty

graphics/bytheway_icon.gif

If a parameter's value is null or if it's an empty string, the jsp:setProperty method won't attempt to set the value. Although this behavior is normally good, it could trip you up if you expect to be able to clear out an entry by sending a blank value.


If your property is an indexed property (that is, an array of values), jsp:setProperty can handle it as long as it's an array of strings or one of the types previously listed in Table 14.1. To see how this works, imagine you have a class like the one shown in Listing 14.1.

Listing 14.1 Source Code for Group.java
package examples;

public class Group implements java.io.Serializable
{
    protected java.util.Vector members;

    public Group()
    {
        members = new java.util.Vector();
    }

    public String getMember(int which)
    {
        return (String) members.elementAt(which);
    }
    public void setMember(int which, String member)
    {
        members.setElementAt(member, which);
    }

    public String[] getMembers()
    {
// Convert the members vector into an array of strings.
        String[] memberArray = new String[members.size()];
        members.copyInto(memberArray);

        return memberArray;
    }

    public void setMembers(String[] memberArray)
    {
// If there are no members, just clear out the vector.
        if (memberArray == null)
        {
            members.setSize(0);
            return;
        }
// Copy the contents of the member array into the members vector.
        members.setSize(memberArray.length);
        for (int i=0; i < memberArray.length; i++)
        {
            members.setElementAt(memberArray[i], i);
        }
    }
}

The JSP shown in Listing 14.2 copies any member parameters it receives into the Group object and then displays the contents of the object. Notice how easy it is to copy the values into the bean compared to how difficult it is to get the values out. The jsp:getProperty action doesn't handle indexed properties well, so stick to single-value properties when using that action.

Listing 14.2 Source Code for ShowGroup.jsp
<html>
<body>

<%-- Create the bean --%>
<jsp:useBean id="group" class="examples.Group"/>

<%-- Copy any member parameters into the bean --%>
<jsp:setProperty name="group" property="members" param="member"/>

<P>
Group members:<br>

<%-- Display the contents of the bean --%>
<%
    examples.Group theGroup = (examples.Group) pageContext.
        getAttribute("group");

    String[] members = theGroup.getMembers();

    for (int i=0; i < members.length; i++)
    {
        out.println(members[i]+"<BR>");
    }
%>
</body>
</html>

Figure 14.1 shows the ShowGroup JSP in action, using values passed directly into the URL. (Look at the address line.)

Figure 14.1. You can set multivalued properties easily with jsp:setProperty.

graphics/14fig01.gif

In addition to the convenience of setting multiple values, the jsp:setProperty action can also scan for matches between property names and parameter names. All you need to do is specify * for the parameter name:


<jsp:setProperty name="myBean" property="*"/>

Listing 14.3 shows a simple test bean with a few properties.

Listing 14.3 Source Code for TestBean.java
package examples;

public class TestBean implements java.io.Serializable
{
    protected String firstName;
    protected String lastName;
    protected int age;

    public TestBean() { }

    public String getFirstName() { return firstName; }
    public void setFirstName(String aFirstName)
        { firstName = aFirstName; }

    public String getLastName() { return lastName; }
    public void setLastName(String aLastName)
        { lastName = aLastName; }

    public int getAge() { return age; }
    public void setAge(int anAge) { age = anAge; }
}

Listing 14.4 shows a JSP that inserts values into a TestBean object and then displays the values again. One of the striking things about this JSP is that it does a fairly good bit of work but doesn't contain any explicit Java code.

Listing 14.4 Source Code for ShowTestBean.jsp
<html>
<body>

<%-- Create an instance of the bean --%>
<jsp:useBean id="myBean" class="examples.TestBean"/>

<%-- Copy the parameters into the bean --%>
<jsp:setProperty name="myBean" property="*"/>

The bean values are:<br>
First Name: <jsp:getProperty name="myBean" property="firstName"/><br>
Last Name: <jsp:getProperty name="myBean" property="lastName"/><br>
Age: <jsp:getProperty name="myBean" property="age"/><br>

</body>
</html>

Figure 14.2 shows the output of ShowTestBean.jsp with parameters passed in directly in the URL.

Figure 14.2. The jsp: setProperty action makes it easy to set several bean properties from request parameters.

graphics/14fig02.gif

In Case of Trouble

graphics/bytheway_icon.gif

If you are having trouble accessing bean properties, see the "Q&A" section at the end of this hour.


Initializing a New Bean

Frequently, you'll want to set only certain properties on a bean the first time it is created, but after that, you want to leave those properties alone. Rather than putting a /> at the end of jsp:useBean, you can use a closing </jsp:useBean> action and put your initialization tags between the opening and closing tags for jsp:useBean. In other words, any code, HTML, or JSP actions that are between the jsp:useBean and </jsp:useBean> are executed only if the bean is created. If the bean already exists, any content between the opening and closing actions is skipped.

Listing 14.5 shows a variant of the JSP in Listing 14.4. This variant JSP changes the scope of the bean from page (the default) to session and executes some code when the bean is created.

Listing 14.5 Source Code for TestInit.jsp
<html>
<body>

<%-- Create an instance of the bean --%>
<jsp:useBean id="myBean" class="examples.TestBean" scope="session">
    I initialized the bean.<BR>
    <jsp:setProperty name="myBean" property="firstName"
        value="blah"/>
    <% out.println("I ran some Java code during the init, too<P>"); %>
</jsp:useBean>

<%-- Copy the parameters into the bean --%>
<jsp:setProperty name="myBean" property="*"/>

The bean values are:<br>
First Name: <jsp:getProperty name="myBean" property="firstName"/><br>
Last Name: <jsp:getProperty name="myBean" property="lastName"/><br>
Age: <jsp:getProperty name="myBean" property="age"/><br>

</body>
</html>

Figure 14.3 shows the output from the TestInit.jsp page when it is run for the first time from a browser.

Figure 14.3. You can place initialization code between jsp:useBean and </jsp:useBean>.

graphics/14fig03.gif

Figure 14.4 shows the output from the TestInit.jsp page when you click the Refresh button on the browser after seeing the output from Figure 14.3. The initialization code isn't executed because the bean already exists and is stored in the session object.

Figure 14.4. Initialization code isn't executed if a bean already exists.

graphics/14fig04.gif

The Type of an Existing Bean

When you need to refer to a bean using a superclass or interface, you can use the type attribute in the jsp:useBean action. For example, suppose you create a Nameable interface like the one shown in Listing 14.6, with a getFirstName and a getLastName.

Listing 14.6 Source Code for Nameable.java
package examples;

public interface Nameable
{
    public String getFirstName();
    public String getLastName();
}

Objects that implement this interface have first and last names, but may have other attributes that are different. You want to write a JSP that prints out the first name and the last name stored in a bean, but you don't care about the actual class of the bean. All you really care about is that it implements the Nameable interface. By specifying type=examples.Nameable, you can use any bean that implements Nameable. Listing 14.7 shows an example.

Listing 14.7 Source Code for ShowNameable.jsp
<html>
<body>

<%-- Locate an instance of the bean and use it as an implementation of Nameable--%>
<jsp:useBean id="myBean" type="examples.Nameable" scope="session"/>

The bean values are:<br>
First Name: <jsp:getProperty name="myBean" property="firstName"/><br>
Last Name: <jsp:getProperty name="myBean" property="lastName"/><br>

</body>
</html>

This example will find the object whose id is myBean in the session scope and use it as an implementation of the Nameable interface. You can test ShowNameable.jsp with TestNameable.jsp from Listing 14.8.

Listing 14.8 Source Code for TestNameable.jsp
<html>
<body>

<%-- Create an instance of the bean --%>
<jsp:useBean id="myBean" class="examples.TestBean2" scope="session"/>

<%-- Copy the parameters into the bean --%>
<jsp:setProperty name="myBean" property="*"/>

<jsp:forward page="/ShowNameable.jsp"/>

</body>
</html>

Notice that Listing 14.7 creates an instance of TestBean2 using the class attribute, whereas Listing 14.6 declares that the type of the object named myBean is Nameable. The effect is to cast the type of TestBean2 to a Nameable. Of course, TestBean must be an implementation of Nameable, or the container will throw an exception. Similarly, if you're trying to use a class as if it were another type, you can only use the class as if it were one of its ancestors.

Classes and Ancestry

graphics/bytheway_icon.gif

Classes group attributes and behavior. Often, there's value in creating a class that encapsulates common behavior and attributes, and in creating specialized classes that derive from it. The derived class is a subclass of the first, which is known as a superclass, parent, or ancestor class. In Java, the latter class extends the former.


Digging a Little Deeper

graphics/didyouknow_icon.gif

Of course, you won't be able to see the results by looking at the page produced by ShowNameable.jsp. It will look the same as if myBean was used directly. To see the effect of using the type attribute, take a moment to look at the code produced by Tomcat. You'll see that the object identified by the id attribute is cast to the type given by the type attribute.


By using both the class and type attributes in a <jsp:useBean> element, you can create a class of one type and use it as another type all in one place. Listing 14.9 shows you how to do this.

Listing 14.9 An Example of How to Use Class and Type id in <jsp:useBean>
<jsp:useBean id="myBean" type="examples.Nameable"
     class="examples.TestBean2" scope="session"/>

If you need to create a bean, you must supply a classname. If you try to use the type attribute without a class attribute and the bean does not exist, the bean is null. In other words, the JSP won't try to create a bean.

In Case of Trouble

graphics/bytheway_icon.gif

If you make changes to a bean and they don't appear to have any effect, see the "Q&A" section at the end of this hour.


    [ Team LiB ] Previous Section Next Section