LJ Archive

JavaBeans

Reuven M. Lerner

Issue #86, June 2001

Using beans makes working with JSPs easier for all levels of programmers.

In the previous two installments of “At the Forge”, we began to work with Jakarta-Tomcat, an open-source servlet and Java Server Pages (JSP) engine sponsored by the Apache Software Foundation. As we have seen, it is neither difficult nor time-consuming to create servlets or JSPs. Getting used to the server-side Java paradigm is probably the biggest hurdle to using them.

While servlets offer us the full breadth of power and expressiveness available from within a Java program, they force us to think at a relatively low level. Every time we want to send HTML-formatted text to the user's browser—quite often, normally—we must use the PrintWriter object associated with the HTTP response object:

PrintWriter out = response.getWriter();
out.println("<HTML><Body>This is illegal HTML</Body></HTML>");

JSPs come to the rescue, assuming that everything that is not explicitly marked as an executable code section should be sent verbatim to the user's browser. But this creates a new problem, namely the fact that a JSP wanting to connect to a relational database must add dozens or hundreds of lines of Java code.

The solution is to create bundles of code that reside outside of the JSP, whose methods can be invoked using a syntax that resembles HTML more than it does Java. These bundles of code are known as JavaBeans, and they can make it much easier to work with JSPs, both for experienced programmers who want to work at a higher level, and for inexperienced programmers who want to take advantage of functionality.

This month, we will take a quick tour of JavaBeans. We will write some of our own beans, integrate them into JSPs and discuss some of the problems and pitfalls associated with them.

What Is a Bean?

From the perspective of someone implementing a bean, JavaBeans are nothing more than Java classes that adhere to several conventions. (We will soon discuss just what those conventions are.)

But to someone who writes a JSP, a bean is a special type of container into which we can store and retrieve certain types of information. Each piece of information is known as a property and can be set or retrieved individually. Not all properties can be set and not all of them can be retrieved, but the interface to the bean from a JSP is uniform and easy to understand.

Because beans understand a restricted set of actions, there are special JSP tags that allow us to work with them. Using these tags allows us to reduce the amount of Java code directly placed within our JSPs. Not only does this reduce clutter and make our JSPs more maintainable and readable, but it means that nonprogrammers can take advantage of a bean's power without having to learn to program in Java.

It's not unusual for a JSP to use multiple beans simultaneously, storing and retrieving different properties as necessary. Thus, a JSP for an on-line store's shopping cart might use one bean for the store's inventory, another for the user's shopping cart, and still another to track the user's language, payment and shipping preferences. Each of these beans is implemented by a separate Java class but is manipulated using special JSP tags that hide most of the complexity from the JSP author.

Of course, a bean can be used on multiple web sites (or by multiple portions of a single site). If you develop a useful JavaBean that encapsulates interesting functionality, other users can drop that bean into their Java classpath, taking advantage of the functionality from within their JSPs.

Implementing a Bean

To write a bean, we must write a Java class that implements the java.io.Serializable interface. Simply put, this means that a bean must be able to save to disk and restore itself. If the fields of your class are common Java types, such as integers and strings, then implementing Serializable shouldn't concern you too much.

Listing 1 contains a simple bean implementation. This bean contains a single instance variable (userID) and two methods. The getUserID method returns the current value of userID, while the setUserID method sets the value of that field. Because these methods' return values and parameter lists match the signatures for bean property methods, we can use them from within our JSPs.

Listing 1. SimpleBean.java

On my system, which is running version 3.2 of the Apache project's Jakarta-Tomcat servlets/JSP system, I placed my Java classes under the directory $TOMCAT_HOME/classes ($TOMCAT_HOME is an environment variable that points to the root of the Tomcat installation; on my system, its value is /usr/java/jakarta-tomcat-3.2.1/). If this “classes” directory exists, it is added to the Tomcat CLASSPATH environment variable, making it a convenient place to put new classes.

The class itself is very simple, demonstrating the different types of methods you can create: 1) A bean constructor that takes no arguments and can set one or more fields. In our particular example, the SimpleBean constructor initializes userID to be 0. 2) A get property method that returns a value to the caller. Like the bean constructor, a get property method does not take any arguments. 3) A set property method that takes a single argument (the new value) but does not return any value to its caller.

Keep in mind that beans are classes like most other Java classes, meaning that they must be recompiled before they are reused. Moreover, the Tomcat servlet container does not automatically reload classes that have been compiled. Your best bet is to restart Tomcat each time you recompile a bean class.

Using the Bean

Now that we have created our simple bean class, how do we use it from within a JSP? JSPs recognize three special tags, all of which begin with “jsp:”.

Before we continue, a word of warning: the special tags that allow us to work with JavaBeans from within a JSP are written in XML rather than HTML. While HTML is a loosely defined specification that does not always require us to close a tag, XML is much stricter. Every opening <tag> must be closed by a matching </tag>. Without a closing </tag>, the XML parser will exit with an error. A tag can close itself by placing a slash at the end of the tag, as in <tag/>.

This means that within an HTML-generating JSP using JavaBeans, you will have to keep track of two slightly different syntaxes. After a while, you will find that moving between these two syntaxes is almost second nature. Moreover, the JSP parser produces error messages that make it relatively easy to determine when you have forgotten to place a trailing slash on a JavaBean tag. However, this mix of syntaxes can be maddening at the beginning, and you can expect to go through some hardship in learning to understand it.

To use a JavaBean class, we use the special <jsp:useBean/> tag. This tag tells the JSP to find and load a particular bean and to create an instance of the bean within our JSP. The <jsp:useBean/> tag also lets us give our bean instance a name that we will use later on. Here is an example of how to load our SimpleBean class from within a JSP:

<jsp:useBean id="simple"
 class="il.co.lerner.SimpleBean"/>

As you can see, the tag ends with a slash (/), following the XML syntax. There are actually cases in which you might prefer to separate the <jsp:useBean/> tag into an opening <jsp:useBean> and closing </jsp:useBean>; whatever is between those two tags is only performed when the bean is first loaded into memory. However, the simpler form is not uncommon.

The <jsp:useBean/> tag takes two mandatory parameters. The class parameter names the package and class in which our bean sits. The id parameter gives our bean a unique name within the JSP. As with variable names, it is a good idea to choose clear identifiers for working with beans. The more obvious the name, the easier it will be to debug our JSP later on.

We can set and retrieve property values within our bean instance with the <jsp:setProperty/> and <jsp:getProperty/> tags. Both of these tags take a name parameter whose value should be identical to the id that we gave our bean earlier on (I am sure there is a good reason why we use an id attribute in <jsp:useBean/> and a name attribute in <jsp:setProperty/>, but I find it to be confusing). We can thus retrieve the value of the userID property with the following tag:

<jsp:getProperty name="simple" property="userID"/>

This retrieves the userID property from the simple bean and places it inside of the JSP. Note that this does not simply retrieve the value, it also makes it visible to the user. Also notice that the capitalization of our property name has been altered slightly. In order to access the getUserID method within our bean, we use <jsp:getProperty/> for the property userID. Don't be fooled into thinking the property names are case-insensitive, however; this transformation takes place simply to keep things readable.

To modify the value of a property, we use the <jsp:setProperty/> tag. This tag does not return any results, but it does take a value attribute whose value is then handed to the appropriate method in the bean class:

<jsp:setProperty name="simple" property="userID"
 value="300"/>

Listing 2 contains a complete JSP that demonstrates how we can use our SimpleBean class from within a JSP. It displays the default value of the userID property, then sets that property to a new value and displays the new value.

Listing 2. use-simple.jsp

Parameters and Properties

It is certainly common for properties to be stored in a bean's instance variables, as in our SimpleBean class. In such cases, invoking <jsp:setProperty/> effectively sets the value of the field, and invoking <jsp:getProperty/> retrieves its current value. Of course, there is no reason why properties must reflect fields. Properties can easily be stored to and retrieved from a relational database. When you retrieve a property, it is possible the returned value is being calculated in real time rather than being returned from an instance variable.

Consider, for example, how we might create a bean that performs simple mathematical operations. We can set two read/write properties (call them arg1 and arg2) and then a number of read-only properties we can use to perform calculations on these arguments. Listing 3 (available at ftp.linuxjournal.com/pub/lj/listings/issue86) contains a simple bean, Calculate.java, which demonstrates how we can accomplish this.

Because there is no setSum property, the JSP engine will not allow us to invoke <jsp:setProperty/> on the sum property. However, it will allow us to set arg1 and arg2 and to retrieve each of the individual properties we might want.

Now that we have a working bean, we can use it from within a JSP. Listing 4 contains the listing for calculator.jsp, which performs some basic calculations using the JavaBean we just created.

Listing 4. calculator.jsp

The first and most interesting part of calculator.jsp is the way in which it sets the properties:

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

Normally, we can take one of the parameters passed via GET or POST and assign its value to a particular property using the following notation:

<jsp:setProperty name="calculator"
 parameter="foo" property="arg1"/>
In other words, the above tag will take the foo parameter and use its value when invoking setArg1 on the calculator bean. But when we use an asterisk, as in Listing 4, we indicate to the JSP engine that we want to take each of the parameters we received and assign each of the values to the properties of the same name. Thus, the arg1 parameter will be passed to the arg1 property and so forth.

On my system, where I have installed calculator.jsp under the examples/jsp URL, I can assign arg1 the value 5 and arg2 the value 20 with the following URL: http://localhost/examples/jsp/calculator.jsp?arg1=5&arg2=20.

Of course, this is not a foolproof system. I can cause a runtime exception by passing the following URL: http://localhost/examples/jsp/calculator.jsp?arg1=5&arg2=20.0.

The JSP engine tries to assign 20.0 (a float value) to arg2 (an int), which fails.

We can surround our <jsp:setProperty/> and <jsp:getProperty/> tags with scriptlet tags, using the standard Java try-and-catch mechanism to attempt to avoid runtime errors. For example, the following code ensures we will never have to deal with division-by-zero exceptions when using getQuotient:

<P>Quotient:
    <% try { %>
        <jsp:getProperty name="calculator"
        property="quotient"/>
    <% } catch (Exception e) { %>
        <B>Error! division by zero</B>
    <% } %>
</P>

At the same time, this sort of code introduces more Java into the JSP, precisely the reason why we began to use beans. Whether the nonprogrammers on your staff will be able to handle this sort of code depends very much on your environment, as well as the sorts of beans you have created.

Bean Scopes

As we have discussed in previous months, the servlet container loads only a single copy of every servlet into memory at a given time. It can get away with this because Java is multithreaded, allowing a particular servlet to be executing simultaneously for several HTTP requests. Since JSPs are actually servlets in disguise, they are also subject to issues of multithreading.

This raises the question of what happens to our JavaBeans: how many times are they loaded; what is their scope? If a JSP sets a property that happens to modify a class' fields, does this affect all of the other instances of the same bean?

The answer is: It depends. There are four different types of bean scopes, and the type of scope that you choose will profoundly affect the way your bean is used. Application scope means a single copy of the bean for all JSPs is running within the servlet container. Session scope is for a single user, from the time they enter the site to the time they exit. If a user opens two browser windows onto your system, they will have identical sessions. Request scope extends through the end of an HTTP request. This is useful if you want to set a bean's properties in one JSP, use the <jsp:forward/> tag to perform an internal redirect to a second JSP and then continue to use that same bean from the second JSP. Page scope is for a single JSP page. When the page exits, so does the scope.

By default, beans are placed in the session scope. You can change this by adding a scope parameter to the <jsp:useBean/>:

<jsp:useBean id="simple" scope="application"
 class="il.co.lerner.SimpleBean"/>

Once we have done the above, properties set by one JSP will be visible to other JSPs. Of course, because beans in the application and server scopes might be executed by more than one JSP simultaneously, they must be threadsafe. Consider the scopes in which your beans are meant to be used, and make them threadsafe as necessary. If a bean is not threadsafe, be sure to indicate as much in its documentation so that others will not mistakenly use it in the wrong way.

Web Log

Last month, we continued our simple investigations of web logs with a JSP that directly accessed a relational database to get the latest contents of a web log. While such a JSP is certainly legal, it looks awkward, is difficult to debug and fails to separate code from logic as elegantly as we might have hoped.

By putting the database logic into a JavaBean, we can achieve several of our goals: the code is reusable, available even to nonprogrammers and allows us to change the source of information or the application logic without rewriting our JSP. Listing 5 (available at ftp.linuxjournal.com/pub/lj/listings/issue86) contains the source code for our bean, which I have made threadsafe (using the “synchronized” keyword within the getBlog method) so we can create a single instance of application scope. This JavaBean connects to the web log database and retrieves the latest information. Listing 6 contains a small JSP that uses this JavaBean to display the web log.

Listing 6. viewblog.jsp

There really isn't anything special about the bean in Listing 5, but it does bring together a number of things that we have been discussing in the last few months. We now have a way for nonprogrammers to access information in our web log without having to write a single line of code on their own! Using a few simple JSP tags, we can place our current blog contents in an HTML page quickly and easily.

Conclusion

JavaBeans are a wonderful way in which to reduce the amount of code we put in our JSPs, while making it easier to use. However, complex JSPs will still contain some code, such as when they have to iterate through loops or work with complex data.

Next month, we will see how we can write our own tags similar to the jsp: tags we saw this month, using JSP's custom actions facility. Therefore, we can create our own new tags, associating them with any code we wish. In this way, JSPs allow us to create our own new formatting language, as well as use the tags that have been provided.

Resources

Reuven M. Lerner owns and manages a small consulting firm specializing in web and internet technologies. As you read this, he should be (finally) finishing Core Perl, to be published by Prentice-Hall later this year. You can reach him at reuven@lerner.co.il, or at the ATF home page, http://www.lerner.co.il/atf/.

LJ Archive