Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Java@Work | Who Are You, Anyway? (Web Techniques, Feb 2001)


Java@Work | Who Are You, Anyway? (Web Techniques, Feb 2001)

Who Are You, Anyway?

By Al Williams

One hallmark of a great restaurant is that the staff knows your name and remembers you when you visit. How many movies have you seen where someone orders "the usual" and the waiter or bartender knows what to do? Personally, I've only been to a few places that offer that level of service—maybe times have changed, or maybe it's just me.

The best Web sites do the same thing—they remember you. Maybe they know what background color you like, or what sports teams you follow. Some e-commerce sites remember your basic information so you don't have to retype it for each order.

Unfortunately, remembering data about users isn't one of those things that comes easily on the Web. Each Internet transaction is typically an anonymous one-time affair. This has resulted in the emergence of a variety of techniques that let you identify and store data that pertains to a user.

Sessions

The HTTP protocol supports cookies—small bits of data that the server can deposit and retrieve from the user's browser. If the server assigns each browser a unique identifier, the server can identify repeated requests from the same browser. (There are other ways to make this association, but cookies are the cleanest and most common.) Browsers don't have to accept cookies, but because so many sites require them, most users don't completely shut them off.

JavaServer Pages (JSPs), like many similar systems, artificially create the notion of a session. The first time a browser requests a page, the server assigns the browser a unique ID and stores it in a client-side cookie. Subsequent requests contain this cookie and the server knows they originated from the same browser.

Session management is important in many cases. For example, when a customer fills a shopping cart, you'll want to remember the contents of that cart the entire time the customer visits the site. However, session management goes only so far. A browser can arbitrarily erase cookies whenever it wants to do so, and cookies eventually expire. Typically, a session cookie will last around 30 minutes (each page view restarts the clock). It would be unusual to find a session that lasts for days or even hours. Also, cookies belong to a particular browser on a particular computer. Your session at work won't apply to your session at home.

The solution is to store session data in a persistent form, like in a database. Coupled with a way to let users identify themselves, you can recall preferences and other data on a per-user basis, instead of only for the session.

Beans and JSP

JSP has all the pieces you need to handle this situation easily. However, the logic is a bit complex—maybe too confusing to code completely in JSP. Instead, I decided to make a user property database JavaBean that you could easily use from within JSP. The core bean is abstract— specific implementations could store data in a flat file, a property file, an XML file, a database, or any place you want to store the data. The bean lets you easily associate a user name (that's password-protected) with a set of properties.

JSP is a simplified way to create servlets. Most people would agree that creating a JSP script is simpler than writing a servlet from scratch. However, writing too much Java code in a JSP is often bad form. One of JSP's strengths is that it lets HTML authors and designers focus on the page structure and simply sprinkle in Java code where it's required. However, when the code overwhelms the HTML markup, much of this benefit evaporates.

Fortunately, there's a middle ground. You can write a custom JavaBean that you can easily incorporate into the JSP page. Don't worry about the complexity of JavaBeans. You'll find it's easy enough to create beans—they're little more than ordinary Java objects that follow a few naming conventions. In fact, you don't really have to create a JavaBean at all. However, JSP is especially adept at including beans, and the extra trouble to create one is minimal.

What makes a JavaBean? For the purposes of this discussion, a bean is any public Java class that doesn't expose public fields. That doesn't mean the object can't have fields, or even that the object can't share fields with outside programs—in a way. Instead of fields, beans have properties. A property appears to be similar to a field. However, when you change or read a property, you're really calling special functions within the bean to do the work. If you want a property named xyz, you'd provide getXyz and setXyz methods. Many bean-aware programs automatically generate these method calls when you request access to a property. Bean-aware programs understand that this is really a property.

Of course, the get and set methods might simply provide access to a nonpublic field. On the other hand, some properties don't directly correspond to a variable. For example, you might have a field called isServerUp that indicates if another machine is available on the network. The getIsServerUp method might not reflect a variable at all. Instead, it would poll to see if the server was running using a socket. There might not be a setIsServerUp method since that wouldn't make much sense. In that case, the property is read-only.

Is that all there is to JavaBeans? No. However, for adding functions to JSPs, it's all you really need to know.

Design

The base class for the property database is UserDB (see Listing 1). The class provides abstract methods that handle the actual transfer of data. In particular:

  • getProperty—Fetches a property for the current user from the database.

  • writeProperty—Writes a property for the current user (not necessarily saving it).

  • save—Saves the property database to persistent storage.

  • load—Loads the database for a specific user (validating the password).

  • create—Creates a new user.

Although the abstract base class doesn't provide any of these functions, it does provide support for them. In particular, the base class maintains the user name, a directory prefix to identify the location of the data (this isn't necessarily an actual directory name—it could be, for example, a dataset name), an auto- save flag, and a dirty flag. If you set the autosave flag, and the database is dirty (that is, changed), the base class code will automatically issue a save when the session expires.

To detect session expiration, the base class has to implement the simple two-method HttpSessionBindingListener interface. This interface lets you detect when a session begins and ends.

In general, a session begins when the user first views a page. It expires after a certain amount of time elapses with no activity from the user, or when your script explicitly invalidates the session. You can release an active session with the following code:

request.getSession(). invalidate();

Because the abstract base class fully implements HttpSessionBindingListener, there's no need for the derived classes to know anything about session management. All the work occurs behind the scenes.

Implementation

One possible database for user information is a collection of ordinary Java property files. I've used property files in a few projects lately, and they offer an easy-to-understand, simplified database for Java programs. Of course, for industrial-strength Web sites, you'd want to use a better database, but property files are easy to use for a modest site and they keep the example code simple. The base class has no prejudice—you can easily derive a new class to use the database of your choice.

The property file implementation appears in Listing 2. You'll see that the only methods of substance are create, load, save, getProperty, and writeProperty. As you'd expect, these map to various methods of a protected instance of the Properties object. Each user has his or her own property file stored in the directory specified. The password appears unencrypted in the property file, so the directory shouldn't be accessible via the Web server.

By default, the autosave feature is off, so you'll have to explicitly call save when you want to update the underlying property file. You can also turn on automatic saving so that the file updates when the session ends.

The hardest part of building the bean is making the JSP container recognize it. You want to put your beans in a directory along the server's class path. Exactly where to put your class files depends on what container you're using—and your particular setup.

Using the beans requires a few pages, no matter what. First, you need a login page that accepts the user's ID and password. Next, you probably want a page that lets you create a new ID. It's also handy to have a page that forces an end to the user's session. This effectively logs the user out of the system.

The key to making this system viable is to create the database bean with session scope. When you include a bean in a JSP page, you can specify the scope and name that you want it to have. Each time you include the bean, the JSP container first checks to see if the bean already exists in that scope. If it does, you simply get that instance of the bean. If it doesn't, the container creates a new bean for you.

Beans with session scope persist until the session is over. That means if you create a database bean with session scope, every page the user visits will use the same bean. That lets you initialize the bean on the login page without having to reinitialize it on every successive page. Because each user has a separate session, you don't have any privacy problems with one user accessing a different user's settings. Of course, this simple system is far from secure. You'll want to avoid storing sensitive information—like credit card numbers, for example—in a plain-text property file.

Here's the JSP tag that creates (or finds) the bean:

<jsp:useBean id="upd" class="UserDBProp" scope="session"/>

The bean's name in this case is upd. In a way, this is similar to writing:

UserDBProp upd = new UserDBProp();

The big difference, however, is that if upd already exists with session scope, you'll simply retrieve the existing instance of the class.

You can also use special tags to access the properties of the bean (although you can refer to them in ordinary JSP scriptlets, as well). For example, here's a tag that sets the dir property:

<jsp:setProperty name="upd" property="dir" value="c:/tmp"/>

Don't forget that this results in the actual bean receiving a call to setDir. This tag doesn't directly attempt to access a field named dir, even though that seems to be the case.

You can find an example login script in Listing 3. The form submits data back to itself. If it detects data entry, it attempts to load the user's properties. If this fails (that is, load returns false), then the same form will appear with an additional error message in red. If the load is successful, the script redirects to the home page automatically (see Listing 4).

Creating a new user is practically the same operation (see Listing 5). The only difference is that in this case, the user must not already exist, and upon success, the script creates the property file and redirects the user back to the login page.

Enhancements

Of course, one obvious enhancement you could make to this system is to use a true database like MySQL or Access to store the data. Improved data security would also be nice. Another useful feature would be to remember the user's ID and password in a cookie for future logins, or to offer a way for the user to retrieve a lost password via email.

You could even use this system to implement a rudimentary security system. Each page could include a JSP file that checked to see if the user's login was accepted. If not, it could redirect the user to the login page. This would make it nearly impossible to view a page without entering your password. A variation on this theme is to assign users a security clearance that controls what they can see. Certain pages might not be accessible unless your clearance is over, say, 100.

Even if you don't want to remember your users, I hope you'll remember this: It's easy to add sophisticated features to JSP by using simple beans. Not only will you be able to teach your Web pages some new tricks, but your JSP pages won't be cluttered with abstruse Java code.

(Get the source code for this article here.)


Al is a consultant who lives near Houston, TX. You can find him on the Web at www.al-williams.com.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.