ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


O'Reilly Book Excerpts: JavaServer Pages

JavaServer Pages: Generating Dynamic Content

Related Reading

Java Server Pages
By Hans Bergsten

by Hans Bergsten

This excerpt is Chapter 5 from Java Server Pages, published in December 2000 by O'Reilly.

JSP is all about generating dynamic content: content that differs based on user input, time of day, the state of an external system, or any other runtime conditions. JSP provides you with lots of tools for generating this content. In this book, you will learn about all of them--standard actions, custom actions, JavaBeans, and scripting elements. Before we do that, however, let's start with a few simple examples to get a feel for how the basic JSP elements work.

In this chapter, we develop a page for displaying the current date and time, and look at the JSP directive element and how to use JavaBeans in a JSP page along the way. Next, we look at how to process user input in your JSP pages and make sure it has the appropriate format. We also look at how you can convert special characters in the output, so they don't confuse the browser.

What Time is It?

Using JSP Directives

Using JavaBeans

Input and Output

Setting JavaBean Properties From User Input

Keep On Doing It 'til You Get It Right

Formatting HTML Output

What Time Is It?

Recall from Chapter 3, JSP Overview, that a JSP page is just a regular HTML page with a few special elements. JSP pages should have the file extension .jsp, which tells the server that the page needs to be processed by the JSP container. Without this clue, the server is unable to distinguish a JSP page from any other type of file and sends it unprocessed to the browser.

When working with JSP pages, you really just need a regular text editor such as Notepad on Windows or Emacs on Unix. Appendix E, JSP Resource Reference, however, lists a number of tools that may make it easier for you, such as syntax-aware editors that color-code JSP and HTML elements. Some Interactive Development Environments (IDEs) include a small web container that allows you to easily execute and debug the page during development. There are also several web page authoring tools--the type of tools often used when developing regular HTML pages--that support JSP. I don't recommend that you use them initially; it's easier to learn how JSP works if you see the raw page elements before you use tools that hide them.

The first example JSP page, named date.jsp, is shown in Example 5-1.

Example 5-1: JSP Page Showing the Current Date and Time (date.jsp)

<%@ page language="java" contentType="text/html" %>
<html>
  <body bgcolor="white">
 
    <jsp:useBean id="clock" class="java.util.Date" />
 
    The current time at the server is:
    <ul>
      <li>Date: <jsp:getProperty name="clock" property="date" />
      <li>Month: <jsp:getProperty name="clock" property="month" />
      <li>Year: <jsp:getProperty name="clock" property="year" />
      <li>Hours: <jsp:getProperty name="clock" property="hours" />
      <li>Minutes: <jsp:getProperty name="clock" property="minutes" />
    </ul>
 
  </body>
</html>

The date.jsp page displays the current date and time. We'll look at all the different pieces soon, but first let's run the example to see how it works. Assuming you have installed all book examples as described in Chapter 4, Setting Up the JSP Environment, first start the Tomcat server and load the http://localhost:8080/ora/ URL in a browser. You can then run Example 5-1 by clicking the "Current Date/Time example" link from the book examples main page, shown in Figure 5-1. You should see a result like the one shown in Figure 5-2.

Figure 5-1. JSP book examples main page

Figure 5-1: JSP book examples main page  

Figure 5-2. Current Date/Time JSP page example

Figure 5-2: Current Date/Time JSP page example  

Notice that the month seems to be off by one and the year is displayed as 100. That's because the java.util.Date class we use here numbers months from 0 to 11, so January is 0, February is 1, and so on, and it reports year as the current year minus 1900. That's just the way this example works. As you will see later, there are much better ways to display dates.

The page shown in Example 5-1 contains both regular HTML elements and JSP elements. The HTML elements are used as-is, defining the layout of the page. If you use the View Source function in your browser, you notice that none of the JSP elements are visible in the page source. That's because the JSP elements are processed by the server when the page is requested, and only the resulting output is sent to the browser. To see the unprocessed JSP page in a separate window, click on the source link for the date.jsp file in the book examples main page. The source link uses a special servlet to send the JSP page as-is to the browser instead of letting the server process it. This makes it easier for you to compare the source page and the processed result.

Let's look at each piece of Example 5-1 in detail.

Using JSP Directives

The first line in Example 5-1 is a JSP directive element. Directives are used to specify attributes of the page itself, primarily those that affect how the page is converted into a Java servlet. There are three JSP directives: page, include, and taglib. In this example, we're using only the page directive. We'll see the others later.

JSP pages typically start with a page directive that specifies the scripting language and the content type for the page:

<%@ page language="java" contentType="text/html" %>

A JSP directive element starts with a directive-start identifier (<%@) followed by the directive name (e.g., page) and directive attributes, and ends with %>. A directive contains one or more attribute name/value pairs (e.g., language="java"). Note that JSP element and attribute names are case-sensitive, and in most cases the same is true for attribute values. For instance, the language attribute value must be java, not Java. All attribute values must also be enclosed in single or double quotes.

The page directive has many possible attributes. In Example 5-1, two of them are used: language and contentType.

The language attribute specifies the scripting language used in the page. The JSP reference implementation (the Tomcat server) supports only Java as a scripting language.[1] java is also the default value for the language attribute, but for clarity you may still want to specify it. Other JSP implementations support other languages besides Java, and hence allow other values for the language attribute. For instance, both JRun (http://www.allaire.com/) and Resin (http://www.caucho.com/) support JavaScript in addition to Java.

The contentType attribute specifies the type of content the page produces. The most common values are text/html for HTML content and text/plain for preformatted, plain text. But you can also specify other types, such as text/xml for browsers that support XML or text/vnd.wap.wml for devices like cellular phones and PDAs that have built-in Wireless Markup Language (WML) browsers. If the content generated by the page includes characters requiring a charset other than ISO-8859-1 (commonly known as Latin-1), you need to specify that charset with the contentType attribute. We'll look at the details of charsets in Chapter 11, Internationalization.

Using Template Text

Besides JSP elements, notice that the page shown in Example 5-1 contains mostly regular HTML:

...
<html>
  <body bgcolor="white">
 
...
 
    The current time at the server is:
    <ul>
      <li>Date: ...
      <li>Month: ...
      <li>Year: ...
      <li>Hours: ...
      <li>Minutes: ...
    </ul>
 
  </body>
</html>

In JSP parlance, this is called template text. Everything that's not a JSP element, such as a directive, action, or scripting element, is template text. Template text is sent to the browser as-is. This means you can use JSP to generate any type of text-based output, such as XML, WML, or even plain text. The JSP container doesn't care what the template text is.

Using JavaBeans

There is also some dynamic content in this example. Step back a moment and think about the type of dynamic content you see on the Web every day. Common examples might be a list of web sites matching a search criteria on a search engine site, the content of a shopping cart on an e-commerce site, a personalized news page, or messages on a bulletin board. Dynamic content is content generated by some server process, for instance the result of a database query. Before it is sent to the browser, the dynamic content needs to be combined with regular HTML elements into a page with the right layout, navigation bars, the company logo, and so forth. In a JSP page, the regular HTML is the template text described earlier. The result of the server processing--the dynamic content--is commonly represented by a JavaBeans component.

A JavaBeans component, or just a bean for short, is a Java class that follows certain coding conventions, so it can be used by tools as a component in a larger application. In this chapter, we discuss only how to use a bean, not how to develop one. (If you're a programmer and not already familiar with JavaBeans, you may want to skip ahead to Chapter 15, Developing JavaBeans for JSP, to learn about these coding conventions.) A bean is often used in JSP as the container for the dynamic content to be displayed by a web page. Typically, a bean represents something specific, such as a person, a product, or a shopping order. A bean is always created by a server process and given to the JSP page. The page then uses JSP elements to insert the bean's data into the HTML template text.

The type of element used to access a bean in a page is called a JSP action element. JSP action elements are executed when a JSP page is requested (this is called the request processing phase, as you may recall from Chapter 3). In other words, JSP actions represent dynamic actions that take place at runtime, as opposed to JSP directives, which are used only during the translation phase (when the JSP page is turned into Java servlet code). JSP defines a number of standard actions and also specifies how you can develop custom actions. For both standard and custom action elements, use the following notation:

<action_name attr1="value1" attr2="value2">
  action_body
</action_name>

Action elements, or tags as they are sometimes called,[2] are grouped into libraries (known as tag libraries). The action name is composed of two parts: a library prefix and the name of the action within the library, separated by a colon (i.e., jsp:useBean). All actions in the JSP standard library use the prefix jsp, while custom actions can use any prefix except jsp, jspx, java, javax, servlet, sun, or sunw. You specify input to the action through attribute/value pairs in the opening tag. The attribute names are case-sensitive, and the values must be enclosed in single or double quotes. For some actions, you can also enter data that the action should process in the action's body. It can be any text value, such as a SQL statement, or even other nested JSP action elements. You will see examples of action elements with a body later.

Before you use a bean in a page, you must tell the JSP container which type of bean it is and associate it with a name. The first JSP action in Example 5-1, <jsp:useBean>, is used for this purpose:

<jsp:useBean id="clock" class="java.util.Date" />

The id attribute is used to give the bean a unique name. It must be a name that is a valid Java variable name: it must start with a letter and cannot contain special characters such as dots, plus signs, etc. The class attribute contains the fully qualified name of the bean's Java class. Here, the name clock is associated with an instance of the class java.util.Date. Note that we don't specify a body for this action. When you omit the body, you must end the opening tag with />, as in this example. In this case, when the JSP container encounters this directive, there is no bean currently available with the name clock, so the <jsp:useBean> action creates a bean as an instance of the specified class and makes it available to other actions in the same page. In Chapter 8, Sharing Data Between JSP Pages, Requests, and Users, you will see how <jsp:useBean> can also be used to locate a bean that has already been created.

Incidentally, the <jsp:useBean> action supports three additional attributes: scope, type, and beanName. The scope attribute is described in detail in Chapter 8, and the other two attributes are covered in Appendix A, JSP Elements Syntax Reference. We don't need to worry about those attributes here.

Accessing JavaBean Properties

The bean's data is represented by its properties. If you're a page author charged with developing a JSP page to display the content represented by a bean, you first need to know the names of all the bean's properties. This information should be available from the Java programmers on the team or from a third-party source. In this example, we use a standard Java class named java.util.Date as a bean with properties representing date and time information. Table 5-1 describes the properties used in this example. (If you're not a programmer, don't worry about the Java Type and Access columns at this point.)

Table 5-1: Properties for java.util.Date

Property Name

Java Type

Access

Description

date

int

read

The day of the month as a number between 1 and 31

hours

int

read

The hour as a number between 0 (midnight) and 23

minutes

int

read

The number of minutes past the hour as a number between 0 and 59

month

int

read

The month as a number from 0 to 11

year

int

read

The current year minus 1900

Once you have created a bean and given it a name, you can retrieve the values of the bean's properties in the response page with another JSP standard action, <jsp:getProperty>. This action obtains the current value of a bean property and inserts it directly into the response body.

To include the current date property value in the page, use the following tag:

<jsp:getProperty name="clock" property="date" />

The name attribute, set to clock, refers to the specific bean instance we defined with the <jsp:useBean> action previously. This action locates the bean and asks it for the value of the property specified by the property attribute. As documented in Table 5-1, the date property contains the day of the month as a number between 1 and 31. In Example 5-1, multiple <jsp:getProperty> actions are used to generate a list of all the clock bean's property values. The result is the page shown in Figure 5-2.

Input and Output

User input is a necessity in modern web pages. Most dynamic web sites generate pages based on user input. Unfortunately, users seldom enter information in exactly the format you need, so before you can use such input, you probably want to validate it.

And it's not only the input format that's important. Web browsers are also picky about the format of the HTML you send them. For instance, when you generate an HTML form with values taken from a database, a name such as O'Reilly can cause problems. The single quote character after the O can fool the browser into believing that it's at the end of the string, so you end up with just an O in your form.

Using JavaBeans to Process Input

As we saw earlier, a bean is often used as a container for data, created by some server process, and used in a JSP page that displays the data. But a bean can also be used to capture user input. The captured data can then be processed by the bean itself or used as input to some other server component (e.g., a component that stores the data in a database or picks an appropriate banner ad to display). The nice thing about using a bean this way is that all information is in one bundle. Say you have a bean that can contain information about a person, and it captures the name, birth date, and email address as entered by the person on a web form. You can then pass this bean to another component, providing all the information about the user in one shot. Now, if you want to add more information about the user, you just add properties to the bean, instead of having to add parameters all over the place in your code. Another benefit of using a bean to capture user input is that the bean can encapsulate all the rules about its properties. Thus, a bean representing a person can make sure the birthDate property is set to a valid date.

Using a bean to capture and validate user input is one aspect of building a web application that's easy to maintain and extend as requirements change. But it's not the only option. If you're a page author and intend to use JSP to develop sites using components from third parties, you may wonder how you can capture and validate input without access to a Java programmer who can develop the beans. Don't worry; we'll see another alternative in Chapter 9, Database Access.

Processing and validating input can also be performed by a servlet instead of a JSP page. If you're a programmer, you'll find examples of this approach in Chapter 14, Combining Servlets and JSP. In this part of the book, however, we use JSP pages for all aspects of the applications so we can focus on JSP features. And one JSP feature makes it very easy to capture user input, so let's see how it's done.

Setting JavaBeans properties from user input

In this next example, we capture information about web site users. It could be the frontend to a newsletter subscription site, for instance. In order to send the users information that might interest them, we register the birth date, sex, and lucky number, along with the full name and email address, for each person that signs up for the service.

To capture and validate the user input, the example uses a bean named com.ora.jsp.beans.userinfo.UserInfoBean, with the properties described in Table 5-2. If you're a programmer, you may want to skip ahead to peek at the source code for this bean class in Chapter 15.

Table 5-2: Properties fcom.ora.jsp.beans.userinfo.UserInfoBean

Property Name

Java Type

Access

Description

userName

String

read/write

The user's full name

birthDate

String

read/write

The user's birth date in the format yyyy-mm-dd (e.g., 2000-07-07)

emailAddr

String

read/write

The user's email address in the format name@company.com

sex

String

read/write

The user's sex (male or female)

luckyNumber

String

read/write

The user's lucky number (between 1 and 100)

valid

boolean

read

true if the current values of all properties are valid, false otherwise

As shown in the Access column, all properties except valid are read/write properties. This means that, in addition to using the bean's properties to generate output (like in Example 5-1), the property values can be set based on user input.

The HTML form shown in Example 5-2 allows the user to enter information corresponding to the bean properties.

Example 5-2: An HTML Form that Sends User Input to a JSP Page (userinfo.html)

<html>
  <head>
    <title>User Info Entry Form</title>
  </head>
  <body bgcolor="white">
    <form action="userinfo1.jsp" method="post">
      <table>
        <tr>
          <td>Name:</td>
          <td><input type="text" name="userName" >
          </td>
        </tr>
        <tr>
          <td>Birth Date:</td>
          <td><input type="text" name="birthDate" >
          </td>
          <td>(Use format yyyy-mm-dd)</td>
        </tr>
        <tr>
          <td>Email Address:</td>
          <td><input type="text" name="emailAddr" >
          </td>
          <td>(Use format name@company.com)</td>
        </tr>
        <tr>
          <td>Sex:</td>
          <td><input type="text" name="sex" >
          </td>
          <td>(Male or female)</td>
        </tr>
        <tr>
          <td>Lucky number:</td>
          <td><input type="text" name="luckyNumber" >
          </td>
          <td>(A number between 1 and 100)</td>
        </tr>
        <tr>
          <td colspan=2><input type="submit"></td>
        </tr>
      </table>
    </form>
  </body>
</html>

This is a regular HTML page that presents a form with a number of fields, as shown in Figure 5-3. There are a few things worth mentioning here. First, notice that each input field has a name attribute with a value that corresponds to a UserInfoBean property name. Matching the names lets us take advantage of a nice JSP feature that sets property values automatically, as you'll see shortly. Also note that the action attribute of the form specifies that a JSP page, userinfo1.jsp, is invoked when the user clicks the Submit button. Figure 5-3 shows what the form looks like in a browser.

Figure 5-3. User input form

Figure 5-3: User input form  

Example 5-3 shows the JSP page that is invoked when the user submits the form.

Example 5-3: A JSP Page that Validates User Input with a Bean (userinfo1.jsp)

<%@ page language="java" contentType="text/html" %>
<html>
  <body bgcolor="white">
    <jsp:useBean 
      id="userInfo"
      class="com.ora.jsp.beans.userinfo.UserInfoBean">
      <jsp:setProperty name="userInfo" property="*" />
    </jsp:useBean>
 
    The following information was saved:
    <ul>
      <li>User Name: <jsp:getProperty
                       name="userInfo" property="userName" />
      <li>Birth Date: <jsp:getProperty
                        name="userInfo" property="birthDate" />
      <li>Email Address: <jsp:getProperty
                           name="userInfo" property="emailAddr" />
      <li>Sex: <jsp:getProperty
                 name="userInfo" property="sex" />
      <li>Lucky number: <jsp:getProperty
                          name="userInfo" property="luckyNumber" />
    </ul>
    The user input is valid: <jsp:getProperty
                               name="userInfo" property="valid" />
  </body>
</html>

Almost at the top of Example 5-3, you see that a <jsp:useBean> action is used to associate a name with the bean:

<jsp:useBean 
  id="userInfo"
  class="com.ora.jsp.beans.userinfo.UserInfoBean">
  <jsp:setProperty name="userInfo" property="*" />
</jsp:useBean>

The <jsp:useBean> action looks similar to the one in Example 5-1. The id attribute specifies the name for the bean, and the class attribute specifies the full name of the bean class. But here we also use a <jsp:setProperty> action as the body of the <jsp:useBean> action. You must therefore use the complete closing tag (</jsp:useBean>) to tell the JSP container where the action ends, instead of the shorthand notation used in Example 5-1. The body of the <jsp:useBean> action is executed only when a new bean is created. In this example, that's always the case, but as you will learn in Chapter 8, there are cases in which the bean already exists and the action is needed only to associate it with a name.

Now let's take a closer look at the <jsp:setProperty> action. As the name implies, this action is used to set the bean's property values. Like the <jsp:getProperty> action, it has a name attribute that must match the id attribute of a <jsp:useBean> action, and a property attribute that specifies which property to set.

When a form is submitted, the form field values are sent as request parameters with the same names as the form field elements. In Example 5-3, note that an asterisk (*) is used as the property attribute value of the <jsp:setProperty> action. This means that all bean properties with names that match request parameters sent to the page are set automatically. That's why it's important that the form element names match the bean property names, as they do here. Automatically setting all matching properties is a great feature; if you define more properties for your bean, you can set them simply by adding new matching fields in the form that invokes the JSP page.

Besides the property attribute, the <jsp:setProperty> action has two more optional attributes: param and value. If for some reason you can't use the same name for the parameters and the property names, you can use the param attribute to set a bean property to the value of any request parameter:

<jsp:setProperty
  name="userInfo"
  property="userName"
  param="someOtherParam"
/>

Here, the userName property is set to the value of a request parameter named someOtherParam.

You can also explicitly set a bean property to a value that is not sent as a request parameter with the value attribute:

<jsp:setProperty
  name="userInfo"
  property="luckyNumber"
  value="13"
/>

Here, the luckyNumber property is set to the value 13. You typically use the value attribute only when you set the bean properties based on something other than user input, for instance values collected from a database.

Validating user input

Never trust your users, at least not when it comes to entering information in the format you need. Often, you need to make sure the input is valid before you continue to process a request. A date, for instance, can be written in many different formats. If you don't live in the United States, you probably have had to fill out both an I-94 and a customs declaration form to be admitted by an immigration officer. You may have noticed that on one of the forms you need to write your birth date as yyyy/mm/dd and on the other you write it as mm/dd/yyyy. I always get it wrong.

Four of the UserInfoBean's properties require a special format: birthDate, emailAddr, sex, and luckyNumber. A good place to make sure the input is valid is in the bean itself, which is exactly what the UserInfoBean does. With this bean, if you try to set any of the above properties to a value that isn't valid, the bean will leave the property unset. In addition, the bean has a true/false (Boolean) property named valid. This property has the value false unless all other properties have been set to valid values.

Let's see this in action. Example 5-3 displays the property values using the <jsp:getProperty> action:

<li>User Name: <jsp:getProperty
                name="userInfo" property="userName" />

Since a property is set only if the value is valid, no values are shown for improperly specified properties. Try it. Click on the "User Info 1 example" link under the Chapter 5 header in the book examples main page shown in Figure 5-1. Enter both valid and invalid values in the form and look at the result produced by the userinfo1.jsp page when you click Submit. A sample result is shown in Figure 5-4.

Figure 5-4. Output from userinfo1.jsp

Figure 5-4: Output from userinfo1.jsp  

Note that the Birth Date information is missing (at my age, you're not so eager to reveal your birth date), so the input is marked as invalid.

Keep On Doing It 'til You Get It Right

Okay, now you know how to set bean properties and you're aware that beans often validate their values. It would be nice if this technique could be used to display the same form over and over until all required input is correct. You can do that with just a few changes, as shown in Example 5-4, the userinfo2.jsp page.

Example 5-4: A JSP Page that Validates and Redisplays Until Correct (userinfo2.jsp)

<%@ page language="java" contentType="text/html" %>
<html>
  <head>
    <title>User Info Entry Form</title>
  </head>
  <body bgcolor="white">
    <jsp:useBean
      id="userInfo"
      class="com.ora.jsp.beans.userinfo.UserInfoBean">
      <jsp:setProperty name="userInfo" property="*" />
    </jsp:useBean>
 
    <%-- Output list of values with invalid format, if any --%>
    <font color="red">
      <jsp:getProperty name="userInfo" property="propertyStatusMsg" />
    </font>
 
    <%-- Output form with submitted valid values --%>
    <form action="userinfo2.jsp" method="post">
      <table>
        <tr>
          <td>Name:</td>
          <td><input type="text" name="userName" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="userName"
                   />">
          </td>
        </tr>
        <tr>
          <td>Birth Date:</td>
          <td><input type="text" name="birthDate" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="birthDate"
                   />">
          </td>
          <td>(Use format yyyy-mm-dd)</td>
        </tr>
        <tr>
          <td>Email Address:</td>
          <td><input type="text" name="emailAddr" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="emailAddr"
                   />">
          </td>
          <td>(Use format name@company.com)</td>
        </tr>
        <tr>
          <td>Sex:</td>
          <td><input type="text" name="sex" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="sex"
                   />">
          </td>
          <td>(Male or female)</td>
        </tr>
        <tr>
          <td>Lucky number:</td>
          <td><input type="text" name="luckyNumber" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="luckyNumber"
                   />">
          </td>
          <td>(A number between 1 and 100)</td>
        </tr>
        <tr>
          <td colspan=2><input type="submit"></td>
        </tr>
      </table>
    </form>
  </body>
</html>

Instead of using a static HTML page for the input form and a separate JSP page with the validation code, in this example we have combined them into a single JSP page. This page generates the form and provides an appropriate message based on whether or not the input is valid. The page also fills in the form with the valid values that have already been specified (if any) so the user needs to enter values only for missing or incorrect input.

Let's look at Example 5-4 from the top. The first thing to note is that the page generates a message using the UserInfoBean property named propertyStatusMsg. Here is the corresponding snippet:

<%-- Output list of values with invalid format, if any --%>
<font color="red">
  <jsp:getProperty name="userInfo" property="propertyStatusMsg" />
</font>

The first line here is a JSP comment. Text between <%-- and --%> in a JSP page is treated as a comment and never appears in the result sent to the browser. For complex pages, it's always a good idea to include comments to explain things that are not obvious.

The propertyStatusMsg property can have three different values. If none of the properties have been set, the value is "Please enter values in all fields". If at least one value is missing or invalid, the message states "The following values are missing or invalid" and provides a list of the relevant properties. Finally, if all the values are valid, the propertyStatusMsg is "Thanks for telling us about yourself!"

Next we generate the form, filled out with all valid values. Here's the beginning of the form and the code for the userName property:

<%-- Output form with submitted valid values --%>
<form action="userinfo2.jsp" method="post">
  <table>
    <tr>
      <td>Name:</td>
      <td><input type="text" name="userName" 
        value="<jsp:getProperty
                 name="userInfo"
                 property="userName"
               />">
      </td>
    </tr>

Most of this is plain HTML, which is treated as template text and passed on untouched to the browser. But note the use of a <jsp:getProperty> action as the HTML <input> element's value attribute. This is how the userName field in the form is filled in with the current value of the userName bean property. Also note how the form's action attribute points back to the JSP page itself.

Try this out by clicking on the "User Info 2 example" link on the book examples page. Enter both valid and invalid values in the form and look at the results. In Chapter 8, we'll expand on this example and look at how you can move on to another page when all input is valid.

One item may look a bit strange to you: an element (<jsp:getProperty>) is used as the value of another element's attribute (the <input> tag's value attribute). While this is not valid HTML syntax, it is valid JSP syntax. Remember that everything not recognized as a JSP element is treated as template text. Whether the template text is HTML, XML, WML, or just plain text doesn't matter. As far as the JSP container is concerned, the previous code is as valid as:

any old template text <jsp:getProperty
                         name="userInfo"
                         property="userName" /> more text

When the JSP page is processed, the action element is replaced with the value of the bean's property. The resulting HTML sent to the browser is therefore valid.

Formatting HTML Output

If you enter a value containing double quotes in the Name field of the userinfo2.jsp page, it doesn't work right. For example, try "Prince, "the artist"" and you'll see what I mean. Only "Prince," appears in the Name field, and the Birth Date field is not shown at all. What's going on here?

A look at the HTML code generated by the JSP page using your browser's View Source function reveals what's wrong:

<table>
  <tr>
    <td>Name:</td>
    <td><input type="text" name="userName" 
      value="Prince, "the artist"">
    </td>
  </tr>

In the JSP file, double quotes are used to enclose the value of the <input> element's value attribute, so when the value itself includes a double quote, the browser gets confused. The first double quote in the value is interpreted as the end of the value. That's why you see only "Prince," in the field. Even worse, the rest of the value interferes with the interpretation of the rest of the form, causing the next input field to be ignored in most browsers.

One solution to this problem would be to use single quotes around the values instead, since HTML accepts either single quotes or double quotes. But then you would have the same problem if the user enters a value that includes a single quote. Fortunately, there's a better way.

What's needed is special treatment of all characters that can cause HTML interpretation problems when we generate HTML from dynamic strings. One way to handle this is to let the bean take care of the special treatment. The UserInfoBean can do this through another set of properties: userNameFormatted, birthDateFormatted, emailAddrFormatted, sexFormatted, and luckyNumberFormatted.

These are read-only properties that simply represent formatted versions of the corresponding real property values. The bean is designed so that when you use these property names, all troublesome characters in the real property values--such as single quotes, double quotes, less-than symbols, greater-than symbols, and ampersands--are converted to their corresponding HTML character entities (i.e., &#39;, &#34;, &lt;, &gt;, and &amp;). The browser handles the converted values with no problem. If you're curious about the Java code for the formatted properties, it's described in Chapter 15. Example 5-5 shows a JSP page that uses the new properties.

Example 5-5: A JSP Page with Validation and Formatting Using a Bean (userinfo3.jsp)

<%@ page language="java" contentType="text/html" %>
<html>
  <head>
    <title>User Info Entry Form</title>
  </head>
  <body bgcolor="white">
    <jsp:useBean
      id="userInfo"
      class="com.ora.jsp.beans.userinfo.UserInfoBean">
      <jsp:setProperty name="userInfo" property="*" />
    </jsp:useBean>
 
    <%-- Output list of values with invalid format, if any --%>
    <font color="red">
      <jsp:getProperty name="userInfo" property="propertyStatusMsg" />
    </font>
 
    <%-- Output form with submitted valid values --%>
    <form action="userinfo2.jsp" method="post">
      <table>
        <tr>
          <td>Name:</td>
          <td><input type="text" name="userName" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="userNameFormatted"
                   />">
          </td>
        </tr>
        <tr>
          <td>Birth Date:</td>
          <td><input type="text" name="birthDate" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="birthDateFormatted"
                   />">
          </td>
          <td>(Use format yyyy-mm-dd)</td>
        </tr>
        <tr>
          <td>Email Address:</td>
          <td><input type="text" name="emailAddr" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="emailAddrFormatted"
                   />">
          </td>
          <td>(Use format name@company.com)</td>
        </tr>
        <tr>
          <td>Sex:</td>
          <td><input type="text" name="sex" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="sexFormatted"
                   />">
          </td>
          <td>(Male or female)</td>
        </tr>
        <tr>
          <td>Lucky number:</td>
          <td><input type="text" name="luckyNumber" 
            value="<jsp:getProperty
                     name="userInfo"
                     property="luckyNumberFormatted"
                   />">
          </td>
          <td>(A number between 1 and 100)</td>
        </tr>
        <tr>
          <td colspan=2><input type="submit"></td>
        </tr>
      </table>
    </form>
  </body>
</html>

Related Reading

JavaServer PagesJavaServer Pages
By Hans Bergsten
Table of Contents
Index
Sample Chapter
Full Description
Read Online -- Safari

It's not always a good idea to have a bean handle this type of formatting, though. A bean is easier to reuse if it doesn't contain logic that is specific for one type of use, such as generating strings suitable for HTML. When we look at scripting elements and custom actions, we will revisit the subject of HTML formatting and look at other solutions to this problem.

Try the final version of this example by clicking on the "User Info 3 example" link. Now everything works fine, even if you happen to be Prince, "the artist."


1. In fact, Java is the only scripting language formally supported in the JSP specification, but the specification leaves room for other languages to be supported.

2. An element is actually represented by a start tag and an end tag, but the term "tag" is often used to refer to what's formally known as an element.

Copyright © 2009 O'Reilly Media, Inc.