Using JavaBeans
AJavaBean is a special type of Java class that you can use in several interesting ways to simplify program development. Some beans, such as Swing components, are designed to be visual components that you can use in a GUI editor to quickly build user interfaces. Other beans, known as Enterprise JavaBeans, are designed to run on special EJB servers and can run the data access and business logic for large Web applications.
In this chapter, I look at a more modest type of JavaBean that's designed to simplify the task of building Java Server Pages. In a nutshell, you can use the simple JavaBeans to build Java Server Pages without writing any Java code in the JSP itself. JavaBeans let you access Java classes by using special HTML-like tags in the JSP page.
What Is a JavaBean?
Simply put, a JavaBean is any Java class that conforms to the following rules:
- It must have an empty constructor. That is, a constructor that accepts no parameters. If the class doesn't have any constructors at all, it qualifies because the default constructor has no parameters. But if the class has at least one constructor that accepts one or more parameters, it must also have a constructor that has no parameters to qualify as a JavaBean.
- It must have no public instance variables. All the instance variables defined by the class must be either private or protected.
- It must provide methods named get Property and set Property to get and set the value of any properties the class provides, except for boolean properties that use is Property to get the property value. The term property isn't really an official Java term. In a nutshell (or should that be, in a beanpod?), a property is any value of an object that-can be retrieved by a get method (or an is method if the property is boolean) or set with a set method. For example, if a class has a property named lastName, it should use a method named getLastName to get the last name and setLastName to set the last name. Or, if the class has a boolean property named taxable, the method to set it is called setTaxable, and the method to retrieve it is isTaxable.
Note that a class doesn't have to have any properties to be a JavaBean, but if it does, the properties have to be accessed according to this naming pattern. Also, not all properties must have both a get and a set accessor. A read-only property can have just a get accessor, and a write-only property can have just a set accessor.
REMEMBER The property name is capitalized in the methods that access it, but the property name itself isn't. Thus setAddress sets a property named address, not Address.
That's all there is to it. More advanced beans can also have other characteristics that allow them to have a visual interface so they can be used drag-and-drop style in an IDE. And some beans implement an interface that allows their state to be written to an output stream so they can be re-created later. But those features are optional; any class that meets the three criteria stated here is a bean and can be used as a bean in JSP pages.
You've already seen plenty of classes that have methods with names like getCount and setStatus. These names are part of a design pattern called the Accessor pattern, which is covered in Book III, Chapter 2. Thus you've seen many examples of beans throughout this book, and you've probably written many bean classes yourself already.
REMEMBER |
Any class that conforms to this pattern is a bean. There's no JavaBean class you have to extend, nor is there a Bean interface you have to implement to be a bean. All a class has to do to be a bean is stick to the pattern. |
Looking Over a Sample Bean
Listing 4-1 shows a sample JavaBean class named Triangle that calculates the Pythagorean Theorem, which calculates the long side of a right triangle if you know the length of the two short sides. This class defines three properties: sideA and sideB represent the two short sides of the triangle, and sideC represents the long side. The normal way to use this bean is to first use the setSideA and setSideB methods to set the sideA and sideB properties to the lengths of the short sides, and then use the getSideC method to get the length of the long side.
TECHNICAL STAUFF |
In case you can't remember way back to high school, the long side is equal to the square root of the first short side squared plus the second short side squared. |
Listing 4-1: The Triangle Bean
package calculators; → 1 public class Triangle { private double sideA; → 5 private double sideB; public Triangle() → 8 { this.sideA = 0.0; this.sideB = 0.0; } public String getSideA() → 14 { return Double.toString(this.sideA); } public void setSideA(String value) → 19 { try { this.sideA = Double.parseDouble(value); } catch (Exception e) { this.sideA = 0.0; } } public String getSideB() → 31 { return Double.toString(this.sideB); } public void setSideB(String value) → 36 { try { this.sideB = Double.parseDouble(value); } catch (Exception e) { this.sideB = 0.0; } } public String getSideC() → 48 { if (sideA == 0.0 || sideB == 0.0) return "Please enter both sides."; else { Double sideC; sideC = Math.sqrt( (sideA * sideA) + (sideB * sideB)); return Double.toString(sideC); } } }
The following paragraphs point out the highlights of this bean class:
→ 1 |
As with most servlet classes, this bean is part of a package. In this case, the package is named calculators. (I'm assuming that if you need a bean to calculate the Pythagorean Theorem, you probably want other beans to calculate derivatives, prime numbers, Demlo numbers, and the like. You can put those beans in this package, too.) |
→ 5 |
This class uses a pair of instance variables to keep track of the two short sides. As per the rules for JavaBeans, these instance variables are declared as private. |
→ 8 |
A constructor with no parameters is declared. (Strictly speaking, this constructor doesn't have to be explicitly coded here, because the default constructor does the trick, and the two instance variables are initialized to their default values of zero automatically.) |
→ 14 |
The getSideA method returns the value of the sideA property as a string. |
→ 19 |
The setSideA method lets you set the value of the sideA property with a string. This method uses a try/catch statement to catch the exceptions that are thrown if the string can't be parsed to a double. If the string is invalid, the sideA property is set to zero. |
→ 31 |
The getSideB method returns the value of the sideB property as a string. |
→ 36 |
The setSideB method sets the value of the sideB property from a string. Again, a try/catch statement catches any exceptions and sets the property to zero if the string can't be parsed to a double. |
→ 48 |
The getSideC method calculates the length of the long side, and then returns the result as a string. However, if either of the values is zero, the method assumes that the user hasn't entered any data, so it returns an error message instead. (That's a reasonable assumption, because none of the sides of a triangle can be zero.) Notice that there is no setSideC method. As a result, sideC is a read-only property. |
Tip |
For an interesting anecdote about the Pythagorean Theorem and The Wizard of Oz, refer to Book III, Chapter 2. |
Using Beans with JSP Pages
To work with a bean in a JSP page, you add special tags to the page to create the bean, set its properties, and retrieve its properties. Table 4-1 lists these tags, and the following sections describe the details of using each one.
Tag |
Description |
---|---|
name” class==“package.class” /> |
Establishes a reference to the bean and creates an instance if necessary. The name specified in the id attribute is used by the other tags to refer to the bean. |
name” property=“property” /> |
Retrieves the specified property from the bean identified by the name attribute. |
name” property=“property” value= =“value” /> |
Sets the specified property to the value specified in the value attribute. |
name” property=“property” param=parameter” /> |
Sets the specified property to the value of the parameter specified in the param” attribute. The parameter is usually the name of a form field. |
name” property=”* “/> |
Sets all the properties defined by the bean to corresponding parameter values, provided a parameter with the correct name exists. |
Creating bean instances
To include a bean in a JSP page, you add a special jsp:useBean tag to the page. In its simplest form, this tag looks like this:
name" emphasis">package.Class" />
The id attribute provides the name that you use elsewhere in the JSP to refer to the bean, and the class attribute provides the name of the class, qualified with the package name. For example, here's a jsp:useBean tag to use the Triangle bean:
The jsp:useBean tag creates an instance of the bean by calling the empty constructor if an instance doesn't already exist. However, if the bean already exists, the existing instance is used instead.
Here are a few additional things you should know about the jsp:useBean tag:
- The jsp:useBean tag can appear anywhere in the JSP document, but it must appear before any other tag that refers to the bean.
- This and all bean tags are case-sensitive, so be sure to code them exactly as shown. won't work.
- If Tomcat complains that it can't find your bean when you run the JSP, double-check the package and class name-they're case-sensitive, too-and make sure the bean is stored in a directory under WEB-INFclasses that's named the same as the package. For example, store the Triangle bean's class file in WEB-INFclassescalculators.
- The jsp:useBean element can have a body that contains jsp: setProperty tags that initialize property values. Then the element is formed more like normal HTML, with proper start and end tags. For example:
Don't worry about the details of the jsp:setProperty tags just yet. Instead, just make a note that they're executed only if a new instance of the bean is actually created by the jsp:useBean tag. If an instance of the bean already exists, the jsp:setProperty tags are not executed.
- The jspuseBean tag also has a scope attribute, which I explain later in this chapter, in the section "Scoping Your Beans."
Getting property values
To get the value of a bean's property, you use the jsp:getProperty tag. The form of this tag is straightforward:
For example, here's a tag that gets the sideC property from the Triangle bean created in the previous section:
The name attribute must agree with the value you specify in the id attribute in the jsp:useBean tag that created the bean. And the property attribute is used to determine the name of the getter method-in this case, getSideC.
Tip |
Remember to begin the property name with a lowercase letter. If you specify property=“SideC”, you get an error message from the server when you run the page. |
In most cases, you use jsp:getProperty to insert the value of a property into a page. However, you can also use it to specify the value of an attribute for some other tag in the JSP document. For example:
" >
Here the value of the sideA property is retrieved and used for the value attribute of an input field named sideA. As a result, when this input field is sent to the browser, its initial value is the value from the Triangle bean.
Warning |
Be extra careful to match up the quotation marks and the open and close brackets for the tags. In this example, the entire jsp:getProperty tag is enclosed within the quotation marks that indicate the value of the input field's value attribute. The right bracket that appears at the very end closes the input element itself. |
Setting property values
To set a property value, you can use one of several variations of the jsp:setProperty tag. If you want to set the property to a literal string, you write the tag like this:
Here the name attribute must match up to the id attribute from the jsp:useBean tag that created the bean, the property attribute is used to determine the name of the setter method (in this case, setSideA), and the value attribute provides the value to be set.
Tip |
I put this tag on three lines only because it's too long to fit within the margins of this page on one line. In actual practice, most JSP developers string these tags out on a single line unless they get really long, which doesn't happen often. |
Although this form of the jsp:setProperty tag is useful, the param form is more useful. It lets you set the property to the value entered by the user into a form field or passed to the JSP by way of a query string. For example, if your JSP contains a form that has an input field named FirstSide, you can assign that field's value to the sideA property like this:
Here, if the user enters a value into the FirstSide field, that value is assigned to the bean's sideA property.
In the previous example, I purposely used a name other than sideA for the input field so you wouldn't be confused by the fact that the property and param attributes specify the same value. In actual practice, you usually give the input field the same name as the property it's associated with, like this:
If your input fields have names that are identical to the property names, you can assign all of them to their corresponding properties with one tag, like this:
Here the asterisk (*) in the property attribute indicates that all properties that have names identical to form fields (or query string parameters) are automatically assigned. For forms that have a lot of fields, this form of the jsp:setProperty tag can save you a lot of coding.
A JSP page that uses a bean
So that you can see how these tags work together, Listing 4-2 shows a complete JSP page that uses the bean that was presented in Listing 4-1. This page displays two text input fields and a button. When the user enters the lengths of a triangle's two short sides in the fields and clicks the button, the page displays the sideC property of the bean to show the length of the third side. Figure 4-1 shows how this page appears when it is run.
Figure 4-1: The Triangle. jsp page displayed in a browser.
Listing 4-2: The Triangle.jsp Page
→ 2 /> → 4Right Triangle Calculator
The Right Triangle Calculator
→ 10 Side A: → 12 value="" >
Side B: → 18 value="" >
Side C: → 24 property="sideC" />
→ 27
The following paragraphs explain the key lines in this JSP:
→ 2 |
The jsp:useBean tag creates an instance of the calculators.Triangle bean and names it triangle. |
→ 4 |
The jsp:setProperty tag sets the sideA and sideB properties to the corresponding input fields named sideA and sideB. |
→ 10 |
The form tag creates a form that posts back to the same JSP file using the HTTP POST method. |
→ 12 |
The first of two input text fields. This one is named sideA, and its initial value is set to the value of the bean's sideA property. |
→ 18 |
The second input text field is named sideB. Its initial value is set to the value of the bean's sideB property. |
→ 24 |
This line is where the sideC property is retrieved, thus calculating the length of side C of the triangle based on the length of sides A and B. The result is simply inserted into the document. |
→ 27 |
The Submit button submits the form so the Triangle bean can do its thing. |
Scoping Your Beans
The scope of a JavaBean indicates how long the bean is kept alive. You specify the scope by using the scope attribute on the jsp:useBean tag. The scope attribute can have any of the four values listed in Table 4-2.
Scope |
Explanation |
---|---|
page |
The bean is associated with the current page. Thus, every time the user requests the page, a new bean is created. Then, when the page is sent back to the browser, the bean is destroyed. Thus, each round trip to the server creates a new instance of the bean. |
request |
Similar to page, but the bean is available to other pages that are processed by the same request. This scope is useful for applications that use several different servlets or JSPs for a single request. |
session |
The bean is associated with a user's session. The first time the user requests a page from the application, a bean is created and associated with the user. Then the same bean is used for other subsequent requests by the same user. |
application |
A single copy of the bean is used by all users of the application. |
The default scope is page, which means that the bean is created and destroyed each time the user requests a new page. However, session scope can be very useful for Web applications that need to keep track of information about a user from one page to the next. The best-known example of that is a shopping cart, in which a user can select items he or she wants to purchase. The contents of the shopping cart can be kept in a session bean.
A shopping cart application
Figure 4-2 shows a simple shopping cart application in which the user has the option to purchase three of my recent books by clicking one of the three buttons. When the user clicks a button, an item is added to the shopping cart. If the user has already added the book to the cart, the quantity is increased by one. In the figure, the user has clicked the button for Networking All-in-One Desk Reference For Dummies twice and Networking For Dummies once.
Figure 4-2: A super-simple shopping cart application.
The following paragraphs describe the key techniques that make this shopping cart work:
- The shopping cart itself is a JavaBean that has just two public methods: setBook, which adds a book to the shopping cart, and getList, which returns a string that shows the shopping cart items nicely formatted in an HTML table.
- The shopping cart class contains an inner class that represents a Book object. To keep the application simple, the Book class has the three titles hard-coded into it. In a real shopping cart program, you use a file or database instead of hard-coding these values.
- The list of products that appears at the top of the page is actually three separate forms, one for each product. Each of these forms specifies a parameter passed via a query string to the JSP on the server. The name of this parameter is book, and its value is the code of the book the user ordered. This parameter is bound to the book property of the shopping cart bean, so when the user clicks one of the buttons, the setBook method is called with the value passed via the book parameter. That's how the shopping cart knows which book the user ordered.
- Beneath the list of books, the JSP uses a jsp:getProperty tag to get the list property, which displays the shopping cart.
The shopping cart page
Listing 4-3 shows the JSP for the shopping cart page.
Listing 4-3: BuyMyBook.jsp
→ 2 scope="session"/> → 4Buy My Books!
Which of my books do you want to buy?
→ 10 method="post"> Networking For Dummies
→ 15 method="post"> Networking All-in-One Desk Reference For Dummies
→ 21 method="post"> Word 2003 All-In-One Desk Reference For Dummies
Your cart contains:
→ 28
The following paragraphs describe the JSP's most important lines:
→ 2 |
The jsp:useBean tag loads the books.BookCart JavaBean, specifying that it has session scope. Thus the bean isn't deleted after each page is requested. Instead, the user works with the same bean instance for his or her entire session. |
→ 4 |
The parameter properties are set. The first time the user displays the BuyMyBook.jsp page, there are no parameters, so this method doesn't do anything. But when the user clicks one of the three form buttons, a book parameter is added to the end of the URL that's posted to the server, so the cart's setBook method is called. This causes one copy of the selected book to be added to the cart. |
→ 10 |
This is the form for the first book. Each book has its own form, with a Submit button labeled Buy and a book title. The action attribute specifies that when the Submit button is clicked, the form is posted to BuyMyBook.jsp with the book parameter set to netfd. |
→ 15 |
The second book form. This one specifies netaio as the book parameter value. |
→ 21 |
The form for the third book. This one specifies wordaio as the value of the book parameter. |
→ 28 |
After the forms for each of the books, a jsp:getProperty tag calls the getList method of the bean. This returns a string that contains an HTML table that displays the current contents of the shopping cart. |
The BookCart JavaBean
Now that you've seen the JSP for the shopping cart application, take a look at the Java code for the BookCart bean. It's shown in Listing 4-4.
REMEMBER |
Listing 4-4 contains two classes-a BookCart class and an inner class named Book. So when you compile the code in Listing 4-4, you get two class files-BookCart.class and BookCart$Book.class. To run this application, you have to copy both class files to a Tomcat directory (a WEB-INFclassesooks directory). |
Listing 4-4: The BookCart JavaBean
package books; → 1 import java.util.ArrayList; import java.text.NumberFormat; public class BookCart { private ArrayList cart; → 8 private NumberFormat cf = NumberFormat.getCurrencyInstance(); public BookCart() → 13 { cart = new ArrayList(); } public void setBook(String code) → 18 { boolean found = false; for (Book b : cart) if (b.getCode().equals(code)) { b.addQuantity(1); found = true; } if (!found) cart.add(new Book(code)); } public String getList() → 31 { String list = ""; list +="" + ""; double total = 0.0; for (Book b : cart) { list += "" + "" + "" + "" + ""; total += b.getTotal(); } list +="" + ""; list += "
Title | Qty | Price | Total |
" + b.getTitle() + " | " + b.getQuantity() + " | " + cf.format(b.getPrice()) + " | " + cf.format(b.getTotal()) + " |
Total: | " + cf.format(total) + " |
"; return list; } private class Book → 52 { private String code; → 54 private int quantity; public Book(String code) → 57 { this.code = code; this.quantity = 1; } public String getCode() → 63 { return this.code; } public String getTitle() → 68 { if (code.equals("netfd")) return "Networking For Dummies"; else if (code.equals("netaio")) return "Networking All-in-One Desk " + "Reference For Dummies"; else if (code.equals("wordaio")) return "Word 2003 All-in-One Desk " + "Reference For Dummies"; else return "Unknown book"; } public double getPrice() → 82 { if (code.equals("netfd")) return 24.99; else if (code.equals("netaio")) return 34.99; else if (code.equals("wordaio")) return 29.99; else return 0.0; } public int getQuantity() → 94 { return this.quantity; } public void addQuantity(int qty) → 99 { this.quantity += qty; } public double getTotal() → 104 { return this.quantity * this.getPrice(); } } }
The following paragraphs describe the bean's high points:
and tags mark the start and end of each row, and the tags mark the start and end of each cell within the row. The table includes one row for each book in the cart. Each row contains cells for the title, quantity, price, and total. If you compare the code in this method with the actual table shown in Figure 4-2, you can get an idea of the HTML that's actually created by this method.
Notice also that the loop that builds each table row keeps a running total for the entire shopping cart, which is displayed in a separate row at the bottom of the table. Also, a row of headings is displayed at the start of the table.
→ 1 |
The BookCart class lives in the books package. |
→ 8 |
The shopping cart itself is kept inside the BookCart bean as a private array list of Book items. |
→ 13 |
To be a JavaBean, you need a no-parameter constructor. This one simply initializes the cart array list. |
→ 18 |
The setBook method is called to add a book to the shopping cart. The book's code is passed as a parameter. This method first looks at all the books in the array list to see if the user has already added a book with this code. If so, that book's addQuantity method is called to increase the order quantity for that book by 1. If not, a new book with the specified code is created and added to the cart. |
→ 31 |
This method builds a string that contains all the books in the cart presented as an HTML table. If you're not familiar with HTML tables, all you really need to know is that the |
and | |
→ 52 |
The Book class is defined as an inner class so it can represent books in the array list. |
→ 54 |
The Book class only stores two items of information for each book: the book code and the quantity, which represents the number of books ordered by the user. The other values are calculated by the methods that return them. |
→ 57 |
The constructor accepts a book code and initializes the instance fields. Notice that the quantity is initialized to 1. |
→ 63 |
The getCode method simply returns the code variable. |
→ 68 |
The getTitle method returns one of three book titles depending on the code. If the code is not one of the three pre-defined codes, Unknown book is returned. |
→ 82 |
Likewise, the getPrice method returns one of three prices depending on the code. If the code is not one of the three allowable codes, the book is free! |
→ 94 |
The getQuantity method just returns the quantity variable. |
→ 99 |
The addQuantity method adds a value to the quantity variable. |
→ 104 |
The getTotal method calculates the total by multiplying the price by the quantity. |