AhmadLang / Java, How To Program, 2004
.pdf
[Page 1265 (continued)]
26.8. Multitier Applications: Using JDBC from a Servlet
Servlets can communicate with databases via JDBC (Chapter 25). Many of today's applications are three-tier distributed applications, consisting of a user interface, business logic and a database. The user interface in such an application is often created using HTML or XHTML (as shown in this chapter). HTML and XHTML are preferred in systems where portability is a concern. Using the networking provided by the browser, the user interface can communicate with the middle-tier business logic. The middle tier can then access the database to manipulate the data. The three tiers can reside on separate computers that are connected to a network.
In multitier architectures, Web servers often are used in the middle tier. Server-side components, such as servlets, execute in an application server alongside the Web server. These components provide the business logic that manipulates data from databases and communicates with client Web browsers.
Servlets, through JDBC, can interact with popular database systems. Developers use SQL for queries, and JDBC drivers handle the specifics of interacting with each database system.
The SurveyServlet in Fig. 26.21 and the Survey.html document in Fig. 26.22 implement portions of a three-tier distributed application. The middle tier is Survey-Servlet, which handles requests from the client browser and provides access to the third tiera MySQL database accessed via JDBC. The servlet in this example allows users to vote for their favorite animals. When the servlet receives a post request from the Web browser, the servlet uses JDBC to update the total number of votes for that animal in the database and returns a dynamically generated XHTML document containing the survey results to the client.
[Page 1266]
Figure 26.21. Multitier Web-based survey using XHTML, servlets and JDBC.
(This item is displayed on pages 1266 - 1268 in the print version)
1 |
// |
Fig. |
26.21: |
SurveyServlet.java |
2 |
// |
A Web-based |
survey that uses JDBC from a servlet. |
|
3 |
package |
com.deitel.jhtp6.servlets; |
||
4 |
|
|
|
|
5import java.io.PrintWriter;
6import java.io.IOException;
7import java.sql.Connection;
8import java.sql.DriverManager;
9import java.sql.Statement;
10import java.sql.ResultSet;
11import java.sql.SQLException;
12import javax.servlet.ServletConfig;
13import javax.servlet.ServletException;
14import javax.servlet.UnavailableException;
15import javax.servlet.http.HttpServlet;
16import javax.servlet.http.HttpServletRequest;
17import javax.servlet.http.HttpServletResponse;
19public class SurveyServlet extends HttpServlet
20{
21private Connection connection;
22private Statement statement;
24// set up database connection and create SQL statement
25public void init( ServletConfig config ) throws ServletException
26{
27// attempt database connection and create Statements
28try
29{
30Class.forName( config.getInitParameter( "databaseDriver" ) );
31connection = DriverManager.getConnection(
32 |
config.getInitParameter( "databaseName" ) ); |
||
33 |
config.getInitParameter( |
"username" |
), |
34 |
config.getInitParameter( |
"password" |
) ); |
35 |
|
|
|
36// create Statement to query database
37statement = connection.createStatement();
38} // end try
39// for any exception throw an UnavailableException to
40// indicate that the servlet is not currently available
41catch ( Exception exception )
42{
43exception.printStackTrace();
44throw new UnavailableException(exception.getMessage());
45} // end catch
46} // end method init
47
48// process survey response
49protected void doPost( HttpServletRequest request,
50HttpServletResponse response )
51throws ServletException, IOException
52{
53// set up response to client
54response.setContentType( "text/html" );
55PrintWriter out = response.getWriter();
56
57// start XHTML document
58out.println( "<?xml version = \"1.0\"?>" );
60out.printf( "%s%s%s" , "<!DOCTYPE html PUBLIC" ,
61" \"-//W3C//DTD XHTML 1.0 Strict//EN\"",
62" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" );
64out.println(
65"<html xmlns = \"http://www.w3.org/1999/xhtml\">" );
67// head section of document
68out.println( "<head>" ) ;
70// read current survey response
71int value =
72Integer.parseInt( request.getParameter( "animal" ) );
73String sql;
74
75// attempt to process a vote and display current results
76try
77{
78// update total for current survey response
79sql = "UPDATE surveyresults SET votes = votes + 1 " +
80 |
"WHERE id = " + value; |
|
81 |
statement.executeUpdate( sql |
); |
82 |
|
|
83// get total of all survey responses
84sql = "SELECT sum( votes ) FROM surveyresults" ;
85ResultSet totalRS = statement.executeQuery( sql );
86totalRS.next(); // position to first record
87int total = totalRS.getInt( 1 );
88
89// get results
90sql = "SELECT surveyoption, votes, id FROM surveyresults " +
91 |
"ORDER BY id"; |
92ResultSet resultsRS = statement.executeQuery( sql );
93out.println( "<title>Thank you!</title>" ) ;
94out.println( "</head>" );
95
96out.println( "<body>" );
97out.println( "<p>Thank you for participating." );
98out.println( "<br />Results:</p><pre>" );
99
100// process results
101int votes;
102
103while ( resultsRS.next() )
104{
105 |
out.print( |
resultsRS.getString( 1 ) ); |
106 |
out.print( |
": " ); |
107 |
votes = resultsRS.getInt( 2 ); |
108 |
out.printf( "%.2f", ( double ) votes / total * 100 ); |
109 |
out.print( "% responses: " ); |
110 |
out.println( votes ); |
111 |
} // end while |
112 |
|
113 |
resultsRS.close(); |
114 |
|
115out.print( "Total responses: " );
116out.print( total );
117
118// end XHTML document
119out.println( "</pre></body></html>" );
120out.close();
121} // end try
122// if database exception occurs, return error page
123catch ( SQLException sqlException )
124{
125sqlException.printStackTrace();
126out.println( "<title>Error</title>" );
127out.println( "</head>" );
128out.println( "<body><p>Database error occurred. " );
129out.println( "Try again later.</p></body></html>" );
130out.close();
131} // end catch
132} // end method doPost
133
134// close SQL statements and database when servlet terminates
135public void destroy()
136{
137// attempt to close statements and database connection
138try
139{
140statement.close();
141connection.close();
142} // end try
143// handle database exceptions by returning error to client
144catch ( SQLException sqlException )
145{
146sqlException.printStackTrace();
147} // end catch
148} // end method destroy
149} // end class SurveyServlet
Figure 26.22. Survey.html document that allows users to submit survey responses to SurveyServlet.
|
(This item is displayed on pages 1270 - 1271 in the print version) |
1 |
<?xml version = "1.0" ?> |
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
3 |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
4 |
|
5 |
<!-- Fig. 26.22: Survey.html --> |
6 |
|
7<html xmlns = "http://www.w3.org/1999/xhtml">
8<head>
9<title>Survey</title>
10</head>
11
12<body>
13<form method = "post" action = "/jhtp6/animalsurvey">
14<p>What is your favorite pet?</p>
15<p>
16<input type = "radio" name = "animal"
17value = "1" />Dog<br />
18<input type = "radio" name = "animal"
19value = "2" />Cat<br />
20<input type = "radio" name = "animal"
21value = "3" />Bird<br />
22<input type = "radio" name = "animal"
23value = "4" />Snake<br />
24<input type = "radio" name = "animal"
25value = "5" checked = "checked" /> None
26</p>
27<p><input type = "submit" value = "Submit" /></p>
28</form>
29</body>
30</html>
[View full size image]
Servlets are initialized by method init, which we override in SurveyServlet (lines 2546). Method init is called exactly once in a servlet's life cycle, before any client requests are accepted. The method takes ServletConfig argument and throws a Servlet-Exception. The argument provides the servlet with information about its initialization parameters (i.e., parameters not associated with a request, but passed to the servlet for initializing the servlet). These parameters are specified in the web.xml deployment descriptor file as part of a servlet element. Each parameter appears in an init-param element of the following form:
<init-param>
<param-name>parameter name</param-name> <param-value>parameter value </param-value>
</init-param>
Servlets can obtain initialization parameter values by invoking ServletConfig method getInitParameter, which receives a string representing the param-name of the parameter and returns the param-value as a string.
In this example, the servlet's init method (lines 2546) performs the connection to the MySQL database. Line 30 loads the driver (com.mysql.jdbc.Driver, which is specified in the initialization parameter "databaseDriver"). Lines 3134 attempt to open a connection to the animalsurvey database. The database name, username and password are specified in the initialization parameters "databaseName", "username" and "password", respectively. The database contains one table (surveyresults) that consists of three fieldsa unique integer to identify each record (id), a string representing the survey option (surveyoption) and an integer representing the number of votes for a survey option (votes). [Note: The examples folder for this chapter contains the SQL script animalsurvey.sql with which you can create the animalsurvey database for this example. For information on executing the SQL script, please refer to Chapter 25.]
When a user submits a survey response, method doPost (lines 49132) handles the request. Lines 7172 obtain the survey response, then lines 76121 attempt to process it. Lines 7980 specify an update statement to increment the votes value for the record with the specified ID and update the database. Lines 8587 execute the query specified in line 84 to retrieve the total number of votes received using SQL's built-in sum function to total all the votes in the surveyresults table. Then lines 92120 execute the query specified in lines 9091 to obtain the data in the table and process the ResultSet to create the survey summary for the client. When the servlet container terminates the servlet, method destroy (lines 135148) closes the Statement, then closes the database connection. Figure 26.22 shows survey.html, which invokes SurveyServlet through alias animalsurvey when the user submits the form.
We use our jhtp6 context root to demonstrate the servlet of Fig. 26.21. Place Survey.html in the servlets directory created previously. Place SurveyServlet.class (with the complete package structure) in the classes subdirectory of WEB-INF in the jhtp6 context root. Then, edit the web.xml deployment descriptor in the WEB-INF directory to include the information specified in Fig. 26.23. This program cannot execute in Tomcat unless the Web application has access to the JAR file that contains the MySQL database driver and its supporting classes. This JAR file (mysql-connector-java-3.0.14-production- bin.jar) can be found in your MySQL Connector's installation directory. Place a copy of this file in the WEB-INF subdirectory lib to make its contents available to the Web application. Please refer to Chapter 25 for more information on how to configure MySQL.
[Page 1270]
Figure 26.23. Deployment descriptor information for servlet
SurveyServlet.
(This item is displayed on page 1272 in the print version)
Descriptor element |
Value |
|
|
servlet element |
|
servlet-name |
animalsurvey |
description |
Connecting to a database from a servlet. |
servlet-class |
com.deitel.jhtp6.servlets.SurveyServlet |
init-param |
|
|
|
param-name |
databaseDriver |
param-value |
com.mysql.jdbc.Driver |
init-param |
|
param-name |
databaseName |
param-value |
jdbc:mysql://localhost/animalsurvey |
init-param |
|
param-name |
username |
param-value |
jhtp6 |
init-param |
|
param-name |
password |
param-value |
jhtp6 |
servlet-mapping element |
|
servlet-name |
animalsurvey |
url-pattern |
/animalsurvey |
|
|
After copying these files, type the following URL in your Web browser:
http://localhost:8080/jhtp6/servlets/Survey.html
Select an animal and press the Submit button to invoke the servlet. [ Note: The MySQL database server should be running when the servlet is invoked.]
[Page 1270 (continued)]
26.9. Welcome Files
Web application developers can specify an ordered list of welcome files to be loaded when the request URL is not mapped to a servlet. These files are typically HTML or JSP documents. Welcome files are defined using the welcome-file-list element in the deployment descriptor. Element welcome- file-list contains one or more welcome-file elements. Each welcome-file element specifies the partial URL of a welcome file without a leading or trailing /. For example, the following welcome-file- list element indicates that index.html and index.htm are the welcome files.
<welcome-file-list>
<welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file>
</welcome-file-list>
[Page 1271]
To specify the welcome files for the jhtp6 context root, insert the preceding welcomefile-list element after the last servlet-mapping element in the web.xml deployment descriptor. When the URL http://localhost:8080/jhtp6/ is requested, the Web server appends each welcome file in the order specified in the deployment descriptor to the request URL, such as
[Page 1272]
http://localhost:8080/jhtp6/index.html
http://localhost:8080/jhtp6/index.htm
and checks whether the resource is valid. The servlet container sends the request to the first matching welcome file. For example, if index.html exists in the jhtp6 directory, the servlet container sends the request to the http://localhost:8080/jhtp6/index.html. If no matching welcome file is found, the servlet container returns a response indicating that the resource is not available.
Figure 26.24 is the index.html that provides links (lines 1524) to test all the examples demonstrated in this chapter. Copy this file to C:\jakarta-tomcat-5.0.25\webapps\jhtp6 and restart the Tomcat server. To test the welcome file, type the following URL in your Web browser:
Figure 26.24. Welcome file index.html.
|
(This item is displayed on page 1273 in the print version) |
1 |
<?xml version = "1.0" ?> |
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
3 |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
4 |
|
5 |
<!-- Fig. 26.24: index.html --> |
6 |
|
7<html xmlns = "http://www.w3.org/1999/xhtml">
8<head>
9<title>Welcome File</title>
10</head>
11
12<body>
13<p>Click a link to test each example demonstrated in this chapter</p>
14<p>
15<a href = "/jhtp6/servlets/WelcomeServlet.html">
16WelcomeServlet</a><br />
17<a href = "/jhtp6/servlets/WelcomeServlet2.html">
18WelcomeServlet2</a><br />
19<a href = "/jhtp6/servlets/WelcomeServlet3.html">
20WelcomeServlet3</a><br />
21<a href = "/jhtp6/servlets/RedirectServlet.html">
22RedirectServlet</a><br />
23<a href = "/jhtp6/servlets/Survey.html">
24SurveyServlet</a><br />
25</p>
26</body>
27</html>
[View full size image]
http://localhost:8080/jhtp6/
The index.html page is loaded. Click a link to test the corresponding servlet example.
[Page 1274]
26.10. Wrap-Up
This chapter continued our networking discussions by presenting servlets that enhance the functionality of Web servers. You learned the architecture and life cycle of servlets. You learned how to respond to HTTP requests by using an HttpServlet. You also learned how to redirect requests to a static or dynamic Web resource. You executed the sample servlets with the Apache Tomcat server. You then built a multitier Web application that uses JDBC to access and manipulate a database from a servlet. In the next chapter, we introduce JavaServer Pagesan extension of servlet technology. We demonstrate several JSP componentsimplicit objects, scripting elements, standard actions and directives. We also discuss how to use CachedRowSets to access a MySQL database from a JavaBean object, then access the JavaBean object from a JSP page.
