站内搜索: 请输入搜索关键词
当前页面: 图书首页 > JavaServer Pages, Second Edition

JavaServer Pages, Second Edition

[ directory ] Previous Section Next Section

3.3 JavaBean Tags

The JavaServer Pages specification provides three basic tags for working with beans: one that finds the bean and makes it available to the rest of the page, one that gets a property from the bean, and one that sets one or more properties. Because of the many ways to use a bean, these tags have a number of variations. These tags and their variations are the basic gateways between the JSP view and the bean model.

Note that these tags are very different from the usual HTML tags. Tags such as <b> and </b> give instructions to the Web browser, saying "present the enclosed text in a bold font." The tags that will shortly be presented give instructions to the JSP engine, telling it how to build the HTML that will eventually be sent to the browser. The browser itself will never see these tags and wouldn't know what to do with them.

In the most basic form, a bean may be made available to a JSP with the following tag:

<jsp:useBean id="bean name"  class="bean class"/>

Here bean name will be the name that is used later to refer to the bean. This name has only two restrictions. First, it must contain only letters, numbers, and the underscore character.[2] The name must also be unique everywhere it is to be used. This means that two beans cannot have the same id, and an id cannot be any of the words request, response, or out, which are reserved by the JSP system.

[2] Technically, it must be a "valid Java identifier," which will make more sense after Chapter 9.

The bean class will be the name of a Java class that defines the bean. Chapter 9 discusses classes in more detail, but for now, a class can be thought of as the collection of Java code that makes up the bean, just as DNA is the code that makes up a lima bean. This bean class must be available to the JSP engine. The JSP specification includes details on how to make classes available to Web applications, which is discussed in Appendix B.

The trailing slash at the end of the tag is important; it signals that there is no corresponding </jsp:useBean> close tag. If this slash is missing, an error will occur at translation time. Examples later in this chapter use a closing tag, but when it is not used, the JSP engine must be told not to expect it.

Errors to Watch For

The most common problem with the jsp:useBean tag is specifying a class that the JSP engine cannot find. When the page is tested, this will be reported as a java.lang.ClassNotFoundException. This error may be caused by a simple misspelling or typo in the name, or it may be because the file that makes up the class is not in the right directory.


3.3.1 Getting a Property

Once a bean has been obtained with jsp:useBean, getting a property is as simple as using the jsp:getProperty tag:

<jsp:getProperty name="bean name" property="property name"/>

Bean name will be the same name that was used in the id field, and property name will be the name of the property to get. Listing 3.1 demonstrates the use of these tags.

Listing 3.1 A JSP that gets properties from a bean
  <jsp:useBean
    id="bean1"
    class="com.awl.jspbook.ch03.Bean1"/>

  <p>Here is some data that came from bean1:</p>

  <ul>

  <li>The name of this bean is:
  <jsp:getProperty name="bean1" property="name"/>

  <li>The 7th prime number is:
  <jsp:getProperty
    name="bean1"
    property="seventhPrimeNumber"/>

  <li>The current time is:
  <jsp:getProperty name="bean1" property="currentTime"/>

  </ul>

The first thing this JSP does is make the bean available to the page. Here, the id has some relationship to the class name, but that need not be the case. It is also not necessary for the jsp:useBean tag to appear right at the top of the page, as long as it appears before any jsp:getProperty tags. However, putting all the jsp:useBean tags together at the top of a page makes it easy to see all the beans that a page is using.

Once the bean has been loaded, the jsp:getProperty tag is used to retrieve data from it. As promised, this hides a number of programming details from the page author. Within the bean, the code that gets the seventh prime number could simply return it from a precomputed list of prime numbers, recompute it each time, or pull it out of a database. In fact, it does the easiest thing and returns the number 17.[3]

[3] If 17 ever ceases to be the seventh prime number, please contact the author, and a replacement bean will be cheerfully provided.

The method the bean uses to get the current date cannot rely on a similar trick, as the date changes every time the page loads. This method must therefore have some code to it, which is shown in Chapter 10.

Finally, note that bean properties can be used anywhere on a page, including within HTML tags, as in:

<td bgcolor="<jsp:getProperty name="bean1"
             property="color"/>">

Here, the color of a table cell is being pulled out of a bean. For this to work, the color property must be presented in one of the acceptable forms for HTML, such as #FF0000 or "red." This is another place where the person coding the page and the person coding the bean must agree.

Errors to Watch For

The only error that can come from the jsp:getProperty tag results from trying to get a property that the bean does not have. This error would be presented on the page as

com.sun.jsp.JspException:
getProperty(id): can't find method to read prop

Most likely, this error will arise because of a typo in the property name, which can simply be corrected. If the JSP does need a property that the bean does not have, the programmer will have to be asked to add it.


3.3.2 Setting Properties

Of the many ways to set a bean's properties, the simplest looks almost exactly like getting a property:

<jsp:setProperty
      name="bean name"
      property= "property name"
      value= "property value"/>

Here, name, as before, is the id from the jsp:useBean tag, and property is the name of the property to set. Value is the new value to assign to the property. The simplest type of value is a string enclosed in quotes, such as "red" or "3".

Listing 3.2 shows a JSP that uses a bean with two properties related to the time. The format property allows the JSP author to specify the format in which the time should be presented, and the currentTime property has the date.

Listing 3.2 A JSP that sets a property
<jsp:useBean
  id="date"
  class="com.awl.jspbook.ch03.DateBean"/>

<ul>

<jsp:setProperty name="date" property="format"
 value="EEEE, MMMM dd yyyy 'at' hh:mm"/>

<li><jsp:getProperty name="date" property="currentTime"/>

<jsp:setProperty name="date" property="format"
 value="hh:mm:ss MM/dd/yy"/>

<li><jsp:getProperty name="date" property="currentTime"/>

<jsp:setProperty name="date" property="format"
 value="yyyyy.MMMMM.dd GGG hh:mm aaa"/>

<li><jsp:getProperty name="date" property="currentTime"/>

</ul>

Recall from Chapter 2 that a JSP is evaluated by the JSP engine from top to bottom. So, the JSP engine will first see the jsp:useBean tag and make the bean available to the page under the name date. Then, this bean's format property will be set. The exact meaning of the value is unimportant, although details are available in the documentation for the java.text.SimpleDateFormat class. The important thing is that when the JSP engine next goes to get the value of the currentTime property from the bean, the bean will use the value of the format property to render it.

When it encounters the next jsp:setProperty tag, the JSP engine will replace the old value of the format property with the new one. This is not a problem; that old value has already served its purpose. When it is next asked for currentTime, the bean will use the new value and will present the current time differently. The bean might also present a slightly different time, as a few milliseconds will have passed since the last jsp:getProperty.

Hard-coded values such as these format specifications are fine for many purposes. But to participate in dynamic pages, beans must be capable of interacting with other dynamic elements.

The Connection Between Forms and Properties

Most interesting dynamic pages are driven at least partially by values that have been provided by users through forms. Because most program logic resides in beans, it seems natural that many JSPs take input values from forms, pass these values into beans via jsp:setProperty tags, and then display other properties representing the result of a computation.

Fortunately, the JSP architects realized how common this situation would be and provided another simple tag to accomplish it. If the form is providing a value called "parameter" and the bean has a property called "parameter", the value can be set with the tag

<jsp:setProperty
      name="bean name"
      property="parameter"/>

In this case, the value is implied and is assumed to come from the form. Sometimes, the name of the form parameter and the name of the property will not match. They can be connected through another variation of the jsp:setProperty tag:

<jsp:setProperty
      name="bean name"
      property="property name"
      param="param name"/>

Here, the JSP will use the form parameter called param name to set the property called property name.

The most powerful version of the jsp:setProperty tag looks through all the parameters provided by the form and all the methods provided by the bean and links them automatically. This version looks as follows:

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

If the form provides values called param1, param2, and so on and if the bean has properties with the same names, everything will match up perfectly. If the form provides some parameters for which there are no matching properties, these parameters will be ignored, and no error will occur. The JSP could proceed to do something else with those parameters, such as pass them on to the bean manually or send them to a different bean with another jsp:setProperty tag. Likewise, if the bean provides properties for which the form does not supply values, these properties will simply not be set. The JSP can call them manually, if needed.

Listing 3.3 shows a page with a simple HTML form. When this form is submitted, the values will be passed to the page in Listing 3.4, which will pass these values to a bean and then use the bean to access the values.

Listing 3.3 A form that sends data to a bean
<form action="form_handler.jsp" method="post">

Enter some text: <input type="text" name="textField"><br>

Now select a color: <select name="color">
<option value="red">red
<option value="green">green
<option value="blue">blue
</select><br>

Do you like cheese?
<input type="radio" name="cheese" value="yes">Yes
<input type="radio" name="cheese" value="no">No<br>

<input
   type="submit"
   name="submit"
   value="Send this info to a bean">
</form>

Absolutely nothing is special about this form; you can hardly even tell that it is a JSP! In particular, note that the page with the form knows nothing about the bean that will be receiving the form values. That is handled entirely by the receiving page, which is shown in Listing 3.4.

Listing 3.4 Processing form inputs with a bean
<jsp:useBean
  id="values"
  class="com.awl.jspbook.ch03.FormBean"/>
<jsp:setProperty name="values" property="*"/>
Here is your text, in the color you chose:
<font color="<jsp:getProperty
               name="values"
               property="color"/>">
<jsp:getProperty name="values" property="textField"/>
</font><br>

When asked whether you like cheese, you said:
<jsp:getProperty name="values" property="cheese"/>

The first line of this example summons a bean into existence and calls it values. The second line then passes all the values from the form into this bean by setting properties. This works only because the bean was built to work with this form and so has properties called text, color, and cheese. These properties are then pulled out of the bean in a few ways. The text and cheese values are simply displayed, but the color property is used within a font tag in order to set a color.

The bean in this example is acting like a simple glass box; values are put in with the jsp:setProperty tag and can then be viewed with the jsp:getProperty tag. However, once a bean has been given values, it can do much more than simply hold them and give them back.

The next example, Listing 3.5, illustrates this. This JSP uses a bean that acts like a simple calculator; it has two properties, called value1 and value2, which may be set from a form. The bean also has a third property, sum, which it computes by adding value1 and value2.

Listing 3.5 A bean calculator
<jsp:useBean
  id="calc"
  class="com.awl.jspbook.ch03.CalcBean"/>

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

The sum of your two numbers is
<jsp:getProperty name="calc" property="sum"/>

There you have it: a calculator in just four lines of code! The form that calls this page is very simple and so is not shown here, although it may be found on the CD-ROM accompanying this book. As in Listing 3.4, the form knows nothing about the bean but simply provides two text boxes named value1 and value2, and the bean takes care of the rest.

Having conveyed how well beans and forms work together, it's time for a little fine print. For this cooperation to work, it must be an echo of cooperation between the person writing the bean and the person writing the form. They must agree on the names of the form variables, which ones will be multivalued, and so on. This should not be any burden to either person, as the bean interface makes both their jobs easier.

It is important to note that each time a user visits the calculator page, the jsp:useBean tag will create a brand new instance of the CalcBean. This is a good thing, as it means that if several users access the same page at the same time, they will each get a copy of the bean, with different values for all the properties. This ensures that if one person tries to use the calculator from Listing 3.5 to compute 100 + 156 at the same time that another user is computing 62 + 34, they will get 256 and 96, respectively.

This may not seem like a big deal; in fact, many people would probably not even have thought that this would be an issue. However, in some Web application frameworks, developers must give a great deal of thought to how their systems will behave if many users access the site simultaneously. Fortunately, using beans and JSPs means that developers can write their pages as if only one user will be using them at a time, and they will automatically work properly even when there are many simultaneous users.

Errors to Watch For

Attempting to set a property that bean does not possess will result in the following error:

com.sun.jsp.JspException:
  setProperty(id): Can't Find the method for setting prop

As in attempting to get a nonexistent property, this error may be a misspelling, or the bean developer must add the needed property. Note that this error will not be generated when setting a bean's properties from a form. If the form names and properties do not match up, the mismatched values will simply be ignored. This can be worse, as it means that a page may not work without an obvious error message to explain why.


Form Values

Unfortunately, simple things are seldom perfect; a bug is lurking in the simple calculator of Listing 3.5. If a user enters on the form a value that is not a number, such as A, the page will return a cryptic error message. The bean programmer could avoid this by constructing the bean in such a way that it would simply ignore bad inputs. This would hardly be an improvement, though, as the page would return an incorrect answer instead of an error. At least with the error message, the user knows that something is awry.

What is needed here is a means for the bean to tell the page whether the inputs were valid and for the page to display different text in either case. This is possible, but such interaction between a model and a view is best mediated by a controller, so this will be deferred until Chapter 12.

It would also be possible to use some JavaScript within the page to ensure that the values are legal. This could be done by adding to the form an onSubmit value, which would check that the values look like numbers and would pop up an error dialogue if they do not. The advantage to this approach is that the feedback is presented to the user immediately, without having to pass all the data to the server. This also means one less condition the server needs to check and one less submission it needs to process. For very popular applications, reducing the strain on the server in such a way can make a noticeable difference in overall system performance.

Unfortunately, using JavaScript has lots of downsides. First, getting the same JavaScript to work on multiple different browsers can be surprisingly difficult. Browsers' incompatibilities and fragility are especially evident when JavaScript is involved. Many Web programmers decide to target only one browser, making their site unavailable to a portion of their potential audience. Alternatively, it is possible to write many different versions of the JavaScript code and have the server include the appropriate version based on which browser is being used. JSPs can make it relatively painless to detect the browser being used and include appropriate JavaScript; this will also be demonstrated in Chapter 4. Even using JSPs, all that JavaScript code will still need to be tested and maintained.

In addition to the compatibility issues, some users choose to turn off JavaScript, and some browsers, such as those included in many mobile phones, don't support JavaScript at all. This means that it will be necessary to write the code to handle the form validation on the server anyway.

Finally, it is generally good practice to have all related code in one place. Because the form will ultimately be processed on the server, it makes aesthetic sense to keep the validation code there as well. This way, if and when the business logic changes, it will not be necessary to hunt down the JavaScript code that checks values and the completely separate Java code that uses these values.

    [ directory ] Previous Section Next Section