|
Simplify JSP Applications with JavaBeans, Part 1
by Richard Shaler
[The code for this article is available for download.]
Separate business logic from presentation. Application developers hear this over and over. You may
understand the concept, but how do you apply this design approach to a Java Web application that uses
Java ServerPages technology? Although JSP technology does facilitate dynamic Web application
development, it doesn't necessarily promote the separation of business logic from presentation. However,
incorporating JavaBeans into your JSP application can help you meet this worthy design approach.
This article will teach you, at a basic level, how to modify a simple, monolithic JSP application into one
that separates the presentation and business logic portions into discrete, reusable, easy-to-manage
components. I'll present two versions (a before and after) of a sample application and describe the
transformation of one to the other. I'll take the JSP of the "before" application and transform it into three
components: a simpler JSP, a servlet, and a JavaBean.
As you read this material it will be helpful for you to examine the source code for each version of the
application. The code is available for download, and I encourage you to reference it as you read. For
background material, read my previous articles on JSP technology.
The Sample Application
The application I use for illustration is rather simple; it displays the customer last name of a particular
customer number. The application presents an input form to allow a user to key in a customer number. You
can see in the image below where I'm submitting customer number 583990.
When the user submits the customer number, the application displays a simple HTML form where the
customer number and last name are displayed in an HTML table:
The application retrieves the customer's last name from the QCUSTCDT table (found in the QIWS library
of most iSeries systems) via JDBC.
Both versions of the application do the same thing, although, internally, they accomplish it differently.
You'll need the following to run the sample applications:
- An iSeries system with access to the AS/400 Java Toolbox JAR file (jt400.jar), which is usually
available in your Client Access installation (just scan your system for "jt400.jar")
- A PC connected to the iSeries via TCP/IP
- A PC or iSeries system with Tomcat (available for free from Apache Software Foundation) installed and running.
I used Tomcat on a PC to test for this article. To learn about installing Tomcat on a PC, see "JavaServer Pages 101" and
Tomcat's native documentation. To learn about
installing Tomcat on the iSeries, see "Installing and Configuring
Tomcat on iSeries."
The Non-JavaBean Version
To understand the first, or "before," version of the application from a component level, examine the
following illustration:
Other than a simple HTML input form, the application uses a single JSP member. In the illustration I refer
to this JSP as "Output Form++," because it does more than just create output; it also controls the flow of the
application processes and contains some business logic (simple retrieval of information). These processes
can be grouped into three code categories: controller, business, and presentation. These categories are
important concepts in the Model-View-Controller component architecture. MVC architecture is material
for another article, but I mention it here because the objective of separating business logic from
presentation is closely related to meeting the goals of the MVC architecture.
The source members of the "before" version are CustNoInput1.html and CustomerLastNameOutput1.jsp.
This version of the application requires no manual compiling, as Tomcat parses the JSP and compiles the
necessary Java servlet the first time it is invoked. You'll find instructions for installing this application later,
in the "Installing the Sample Application" section.
The JavaBean Version
Now examine the second, or "after," version of the application from the component level, in the
following illustration:
As you can see, the application now has four components instead of two. I've taken the three categories of
code (controller, business, and presentation) that were in the single JSP of the "before" version, and placed
them into three different Java components. The controller code is now in a servlet, the business code is now
in a JavaBean, and the presentation code is all that remains in the JSP.
A servlet is a Java program that runs on the server and typically controls an application's flow (similar to an
iSeries CL driver program). But what is a JavaBean?
A JavaBean implies a plug-and-play type of component. Any application should be able to easily exploit a
JavaBean, similar to any CD player being able to play a CD. In other words, a JavaBean should be a
component that can be easily used by any application that requires its information or function.
Here, the JavaBean component contains the logic to retrieve a customer's last name, and nothing else. It
doesn't display the information; it simply retrieves it and retains it for any other component of this
application to access. Other applications can use different instances of the same JavaBean to access other
customer last names.
The source members of the "after" version are CustNoInput2.html, CustomerLastNameControllerServlet.java,
CustomerLastNameBean.java, CustomerLastNameOutput2.jsp, and jdbc.properties.
The CustomerLastNameControllerServlet.java and CustomerLastNameBean.java source files must be
compiled. You'll find instructions for installing this application in the "Installing the Sample Application"
section.
The Transformation
Modify the HTML Input Form
I made one simple change to the input form to call the servlet (CustomerLastNameControllerServlet.java)
instead of the monolithic JSP (CustomeLastNameOutput1.jsp). This servlet call is done through the HTML
FORM tag, with the method and action attribute:
<FORM method="Post"
action="/custlastname/servlet/CustomerLastNameControllerServlet">
Notice the path value /custlastname/servlet. The first path element is the application name; the second
element (servlet) is a special logical name that tells the Tomcat server that the resource is a servlet. This
causes the server to look for the servlet in the \webapps\custlastname\WEB-INF\classes
directory, which is where the compiled version of the CustomerLastNameControllerServlet.java file will be
placed when you install and compile the application.
Create Controller Servlet
The component CustomerLastNameControllerServlet controls the flow of the application components. For
example, it makes the connection to the iSeries via JDBC, instantiates (or materializes) the customer last
name JavaBean (CustomerLastNameBean), and then passes control to the presentation JSP
(CustomerLastNameOutput2.jsp). For space considerations, I can't go into too much detail about servlets,
but I'll explain some of the more important features used by the servlet.
Servlets have access to a special method by the name of init. If used, init will only execute the first time the
servlet is called by a user. The init function is used in the sample servlet to make the connection to the
iSeries system.
Two other special methods are used in servlets: doGet and doPost. One of these two methods is called
automatically when an HTML form is submitted, depending on how the HTML form is coded. The sample
application HTML input form uses the HTML FORM tag's Post method; therefore, doPost is automatically
called. If you examine the servlet code, you will see the doPost method calls the doGet method, which
actually performs the work. (This coding technique allows me to treat an HTML Get or Post request with
essentially the same code.)
Within the doGet method, you can see the servlet code that creates a JavaBean instance:
CustomerLastNameBean cust = new CustomerLastNameBean(con, nbr);
Notice that the parameter list passed to CustomerLastNameBean contains the connection object created
earlier by the init method of the servlet. The parameter list also contains the customer number retrieved
from the HTML input form through the getParameter method of the req (HTTP request) object:
BigDecimal nbr = new BigDecimal(req.getParameter("custno"));
The last thing the servlet does is to pass control to the JSP used to display the output to the browser
(CustomerLastNameOutput2.jsp):
getServletConfig().getServletContext().
getRequestDispatcher("/CustomerLastNameOutput2.jsp").
forward(req, resp);
However, one important thing has to be done before the control is passed to the JSP. You must set a request
object (in this case req) attribute called CustomerLastNameBean to the customer object (cust). This allows
the JSP to access the methods and properties of the Bean when it receives control.
req.setAttribute("CustomerLastNameBean", cust);
The next component that needs to be created is the JavaBean. But, before I address the JavaBean, it will be
helpful to explain a little about Java packages.
A Word About Java Packages
JavaBeans are normally made part of a package. Basically, Java packages allow you to group related Java
components into a single compressed file (usually named with a .jar extension) that is much easier to
manage, install, and administer than numerous independent components. Applications will often contain
dozens, or even hundreds, of Java components, including JavaBeans. During development or before a
package is created, these Java components must reside in directory structures that agree with the package
name structure. Package names usually follow the URL of a company in reverse order. In the sample
application, for example, the package name structure I created is com.itechtutor (the fictitious company
URL is itechtutor.com), and it is specified in the JavaBean source code as follows:
package com.itechtutor;
Unless a package is created and your application can access the package, you must create a directory with
the same structure as the package name. On a Windows system you can simply substitute a backslash (\) for
each period, and you've created the literal path that must exist to contain the JavaBean. On iSeries, Unix, or
Linux systems, substitute a slash (/). Because I did not create a package for the sample application during
development or in the download files, a directory structure of com\itechtutor or com/itechtutor must exist in
the application directory under Tomcat webapp\\WEB-INF\classes directory. See the
directory image in the "Installing the Sample Application" section below to see the relative position of the
com\itechtutor directory.
Create JavaBean
This component contains the application's business logic. I pulled the retrieval logic (the SQL select
statement, and so forth) out of the "before" version JSP (CustLastNameOutput1.jsp) and placed it in the
JavaBean (CustLastNameBean.java). Of course, the JavaBean source code has some other code, too. For
example, it contains some constructor methods (methods called automatically when a JavaBean is created),
and it contains a getLastName method, which allows an application component to access the customer last
name value from the JavaBean.
The next several paragraphs describe some of the basic things that cause a Java component to be considered
a JavaBean.
JavaBeans usually end with the word Bean, which identifies them as a JavaBean.
As mentioned previously, a JavaBean promotes the idea of plug-and-play. An application that uses a
JavaBean should be able to exploit it without too much knowledge of the Bean. A JavaBean user (other
components of the application) should be able to determine certain things about the Bean. For example, the
properties of JavaBeans are accessed with special "getter" methods and updated with special "setter"
methods. The method names for the getter and setter methods are always the property name prefixed with
"get" or "set." A JavaBean property called lastname would have a getLastName and setLastName method
defined. The conforming getter and setter method names allow a Bean user to easily determine the
attributes (properties and methods) of the Bean (a process known as introspection).
JavaBeans have at least one constructor method defined with no parameters. This allows a Java component
to instantiate a JavaBean without needing to know its constructor parameter list (signature). Ideally, a
JavaBean would only have the one constructor method with no parameters, but you can create additional
constructors with different parameter lists (a technique known as overloading). The sample JavaBean used
here uses the constructor overload technique to have two things passed to it: the connection obtained by the
servlet and the customer number.
Now take a look at the partial source code in CustLastNameBean.java:
public CustomerLastNameBean () {}
public CustomerLastNameBean (Connection con, BigDecimal nbr) {
this.custNo = nbr;
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT CUSNUM, LSTNAM " +
"FROM qcustcdt " +
"WHERE CUSNUM = " +
nbr);
if (rs.next()) {
this.lstNam = rs.getString("LSTNAM");
}
rs.close();
stmt.close();
} catch (SQLException e) {
System.out.println("SQL error : " + e);
}
}
You can see there are two CustomerLastNameBean constructor methods. It is the second constructor that is
called when the servlet program (CustomerLastNameControllerServlet.java) instantiates the Bean.
Lastly, the JSP (CustomerLastNameOutput2.jsp) must be linked to the JavaBean it is to use
(CustomerLastNameBean). This is done through the use of the JSP <jsp:useBean> action tag:
<jsp:useBean id="CustomerLastNameBean" scope="request"
class="com.itechtutor.CustomerLastNameBean" />
The "id" is used to reference the Bean within the JSP, and the "class" attribute is used to specify the literal
Bean name (in this case fully qualified).
Installing the Sample Application
Complete instructions for installing the sample applications ("before" and "after") are included in a text file
called CustomerLastNameInstallNotes.txt, which is part of the
download package. The directory structure illustrated below, containing the application I set up
(custlastname) to test this article, will help you to understand the structure of an installed Tomcat
(4.x) application:
Notice the selected custlastname directory, under the webapps directory. All the sample application
components ("before" and "after" versions) are contained within and below the custlastname directory. In
the real world you probably wouldn't stuff the code for two applications into the same application directory,
but it was easier to do so here.
The download package contains the file makecustlastname.bat, which will make compiling the
application easier. (See the CustomerLastNameInstallNotes.txt file to find out where to place the
makecustlastname.bat file before you execute it.)
You may discover that the installation process is tedious. Fortunately, there is a way to simplify the
installation of Java applications on Web servers such as Tomcat, and that is WAR files. However, a
discussion of WAR files is beyond the scope of this article. Look for a future article on the subject of WAR
files.
Try This Bean
By dividing the monolithic JSP of the "before" application into three components (JSP, servlet, and
JavaBean), I was able to simplify the presentation logic while isolating the business and controller logic
into a separate components. This componentizing of an application contributes to easier maintenance and
promotes reusability. (Keep in mind the applications presented here are elementary and actually quite
crude, but they serve well as examples.) Again, I encourage you to examine the source code to gain a better
understanding of how to create a JSP that uses a JavaBean. In my next article I'll teach you how to refine
and improve communication among the JSP and JavaBean components by modifying the components of
the application presented here.
Editor's Note: The file CustomerLastNameInstallNotes.txt, contained in the download package for this article, has been
edited since its original publication to include a step in the installation instructions. The first step
listed under the "Installation" section in the file now reads as follows:
1. Update your CLASSPATH environment variable on your PC by adding a path to the servlet.jar package (i.e., c:\Apache Tomcat 4.0\common\lib\servlet.jar).
Guild Companies regrets the error. [Correction made 5/1/02]
|