Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
In this article, I will examine the handling of a user registration form using JSP. One of the basic programming tenets of JSP is to delegate as much processing as possible to JavaBean components. My JSP form-handling implementation will demonstrate some interesting features. It will not only provide basic data validation for the registration information input by a user, but will also exhibit stateful behavior. This lets you pre-fill the form's input elements with validated data as the user loops through the submission cycle and finally enters the correct data for all of the input elements. So, without further ado, let's dive into the example.
Take a look at Listing 1, which presents the user with a simple registration form, displayed in Figure 1.
<html>
<body>
<form action="/examples/jsp/forms/process.jsp" method=post>
<center>
<table cellpadding=4 cellspacing=2 border=0>
<th bgcolor="#CCCCFF" colspan=2>
<font size=5>USER REGISTRATION</font>
<br>
<font size=1><sup>*</sup> Required Fields</font>
</th>
<tr bgcolor="#c8d8f8">
<td valign=top>
<b>First Name<sup>*</sup></b>
<br>
<input type="text" name="firstName" value="" size=15 maxlength=20></td>
<td valign=top>
<b>Last Name<sup>*</sup></b>
<br>
<input type="text" name="lastName" value="" size=15 maxlength=20></td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
<b>E-Mail<sup>*</sup></b>
<br>
<input type="text" name="email" value="" size=25 maxlength=125>
<br></td>
<td valign=top>
<b>Zip Code<sup>*</sup></b>
<br>
<input type="text" name="zip" value="" size=5 maxlength=5></td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
<b>User Name<sup>*</sup></b>
<br>
<input type="text" name="userName" size=10 value="" maxlength=10>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top>
<b>Password<sup>*</sup></b>
<br>
<input type="password" name="password1" size=10 value=""
maxlength=10></td>
<td valign=top>
<b>Confirm Password<sup>*</sup></b>
<br>
<input type="password" name="password2" size=10 value=""
maxlength=10></td>
<br>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
<b>What music are you interested in?</b>
<br>
<input type="checkbox" name="faveMusic"
value="Rock">Rock
<input type="checkbox" name="faveMusic" value="Pop">Pop
<input type="checkbox" name="faveMusic" value="Bluegrass">Bluegrass<br>
<input type="checkbox" name="faveMusic" value="Blues">Blues
<input type="checkbox" name="faveMusic" value="Jazz">Jazz
<input type="checkbox" name="faveMusic" value="Country">Country<br>
</td>
</tr>
<tr bgcolor="#c8d8f8">
<td valign=top colspan=2>
<b>Would you like to receive e-mail notifications on our special
sales?</b>
<br>
<input type="radio" name="notify" value="Yes" checked>Yes
<input type="radio" name="notify" value="No" > No
<br><br></td>
</tr>
<tr bgcolor="#c8d8f8">
<td align=center colspan=2>
<input type="submit" value="Submit"> <input type="reset"
value="Reset">
</td>
</tr>
</table>
</center>
</form>
</body>
</html>

Figure 1. The user registration form
There should be nothing unusual about the form shown in Listing 1. It contains all of the commonly used input elements, including text-entry fields, checkboxes, and radio buttons. However, notice the action clause of the form:
<form action="/examples/jsp/forms/process.jsp" method=post>
Although typically you may have specified a servlet or Perl script, note that a JSP is perfectly capable of processing data posted from an HTML form. This should not surprise you, since after all, what is JSP? It is nothing but a high-level abstraction of servlets. Thus, in most cases it is entirely feasible to write a JSP equivalent to a servlet.
Still, you should always remember that JSP technology was created for an entirely different purpose than serving as an alternate (some would say easier!) mechanism for creating servlets. JSP is all about facilitating the separation of presentation from dynamic content. Although you can embed any amount of Java code within a JSP page, your best bet is to encapsulate the processing logic within reusable JavaBean components. Nevertheless, in my opinion, it should also be perfectly appropriate to develop controller JSP pages. These pages would still delegate the bulk of the processing to component beans, but they would also contain some conditional logic to respond to a user's actions. But these controller pages would never contain presentation logic to display UI elements. This task would always be externalized into separate JSPs, which will be invoked as needed by the controller.
Take a look at Listing 2, which demonstrates a JSP serving as a controller.
<%@ page import="java.util.*" %>
<%!
ResourceBundle bundle =null;
public void jspInit() {
bundle = ResourceBundle.getBundle("forms");
}
%>
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request">
<jsp:setProperty name="formHandler" property="*"/>
</jsp:useBean>
<%
if (formHandler.validate()) {
%>
<jsp:forward page="<%=bundle.getString(\"process.success\")%>"/>
<%
} else {
%>
<jsp:forward page="<%=bundle.getString(\"process.retry\")%>"/>
<%
}
%>
Because we are delegating the bulk of the processing to JavaBeans, the first thing the controller has to do is instantiate
the bean component. This is done with the <jsp:useBean> tag as follows:
<jsp:useBean id="formHandler" class="foo.FormBean" scope="request">
<jsp:setProperty name="formHandler" property="*"/>
</jsp:useBean>
The <jsp:useBean> tag first looks for the bean instance with the specified name, and instantiates a new one only if it cannot find the bean
instance within the specified scope. Here, the scope attribute specifies the lifetime of the bean. Newly instantiated beans
have page scope by default, if nothing is specified. Observe that in this case, I specify that the bean have request scope
before a response is sent back to the client, since more than one JSP is involved in processing the client request.
You may be wondering about the <jsp:setProperty> within the body of the <jsp:useBean> tag. Any scriptlet or <jsp:setProperty> tags present within the body of a <jsp:useBean> tag are executed only when the bean is instantiated, and are used to initialize the bean's properties. Of course, in this
case I could have placed the <jsp:setProperty> tag on the outside of the <jsp:useBean>'s body. The difference between the two is that the contents of the body are not executed if the bean is retrieved from the
specified scope -- which is moot in this case since the bean is instantiated each time the controller is invoked.
When developing beans for processing form data, you can follow a common design pattern by matching the names of the bean properties
with the names of the form input elements. You would also need to define the corresponding getter/setter methods for each
property within the bean. For example, within the FormBean bean (shown in Listing 3), I define the property firstName, as well as the accessor methods getFirstName() and setFirstName(), corresponding to the form input element named firstName. The advantage in this is that you can now direct the JSP engine to parse all the incoming values from the HTML form elements
that are part of the request object, then assign them to their corresponding bean properties with a single statement, like
this:
<jsp:setProperty name="formHandler" property="*"/>
This runtime magic is possible through a process called introspection, which lets a class expose its properties on request. The introspection is managed by the JSP engine, and implemented via the Java reflection mechanism. This feature alone can be a lifesaver when processing complex forms containing a significant number of input elements.
package foo;
import java.util.*;
public class FormBean {
private String firstName;
private String lastName;
private String email;
private String userName;
private String password1;
private String password2;
private String zip;
private String[] faveMusic;
private String notify;
private Hashtable errors;
public boolean validate() {
boolean allOk=true;
if (firstName.equals("")) {
errors.put("firstName","Please enter your first name");
firstName="";
allOk=false;
}
if (lastName.equals("")) {
errors.put("lastName","Please enter your last name");
lastName="";
allOk=false;
}
if (email.equals("") || (email.indexOf('@') == -1)) {
errors.put("email","Please enter a valid email address");
email="";
allOk=false;
}
if (userName.equals("")) {
errors.put("userName","Please enter a username");
userName="";
allOk=false;
}
if (password1.equals("") ) {
errors.put("password1","Please enter a valid password");
password1="";
allOk=false;
}
if (!password1.equals("") && (password2.equals("") ||
!password1.equals(password2))) {
errors.put("password2","Please confirm your password");
password2="";
allOk=false;
}
if (zip.equals("") || zip.length() !=5 ) {
errors.put("zip","Please enter a valid zip code");
zip="";
allOk=false;
} else {
try {
int x = Integer.parseInt(zip);
} catch (NumberFormatException e) {
errors.put("zip","Please enter a valid zip code");
zip="";
allOk=false;
}
}
return allOk;
}
public String getErrorMsg(String s) {
String errorMsg =(String)errors.get(s.trim());
return (errorMsg == null) ? "":errorMsg;
}
public FormBean() {
firstName="";
lastName="";
email="";
userName="";
password1="";
password2="";
zip="";
faveMusic = new String[] { "1" };
notify="";
errors = new Hashtable();
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getUserName() {
return userName;
}
public String getPassword1() {
return password1;
}
public String getPassword2() {
return password2;
}
public String getZip() {
return zip;
}
public String getNotify() {
return notify;
}
public String[] getFaveMusic() {
return faveMusic;
}
public String isCbSelected(String s) {
boolean found=false;
if (!faveMusic[0].equals("1")) {
for (int i = 0; i < faveMusic.length; i++) {
if (faveMusic[i].equals(s)) {
found=true;
break;
}
}
if (found) return "checked";
}
return "";
}
public String isRbSelected(String s) {
return (notify.equals(s))? "checked" : "";
}
public void setFirstName(String fname) {
firstName =fname;
}
public void setLastName(String lname) {
lastName =lname;
}
public void setEmail(String eml) {
email=eml;
}
public void setUserName(String u) {
userName=u;
}
public void setPassword1(String p1) {
password1=p1;
}
public void setPassword2(String p2) {
password2=p2;
}
public void setZip(String z) {
zip=z;
}
public void setFaveMusic(String[] music) {
faveMusic=music;
}
public void setErrors(String key, String msg) {
errors.put(key,msg);
}
public void setNotify(String n) {
notify=n;
}
}
It is not mandatory that the bean property names always match those of the form input elements, since you can always perform the mapping yourself, like this:
<jsp:setProperty name="formHandler" param="formElementName"
property="beanPropName"/>
While you can easily map form input types like text-entry fields and radio buttons to a scalar bean property type like String, you have to use an indexed property type like String[] for handling checkboxes. Nevertheless, as long as you provide a suitable setter method you can still have the JSP engine
assign values even for non-scalar types by automatically parsing the corresponding form element values from the request object.
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq