3. Introduction to Java Servlets and JSP Pages
This chapter contains various examples of servlets and JSP pages. They have been tested with the Tomcat server, which runs on port 8080. By following the links on the home page, you can access examples of servlets and JSP pages. Most of the examples below are taken from Tomcat’s examples. To test them, simply start Tomcat, enter the URL http://localhost:8080 in a browser, and follow the servlet link.
![]() | ![]() |
3.1. Java Servlets
3.1.1. Sending HTML Content to a Web Client
Let’s examine the Hello World example above. The servlet is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello World!</h1>");
out.println("</body>");
out.println("</html>");
}
}
When this servlet is executed, the following is displayed:

Note the following points:
- You must import special classes for servlets:
import javax.servlet.*;
import javax.servlet.http.*;
The javax.servlet library is not always included by default with the JDK. In this case, you can download it directly from the Sun website.
- A servlet extends the HttpServlet class
public class HelloWorld extends HttpServlet {
- A GET request made to the servlet is handled by the doGet method
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
- Similarly, a POST request made to the servlet is handled by the doPost method
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
- The HttpServletRequest request object is the object that gives us access to the request made by the web client. The servlet's response will be sent via the HttpServletResponse response object
- The response object allows us to set the HTTP headers that will be sent to the client. For example, the Content-Type: text/html header is set here by:
- To send the response to the client, the servlet uses an output stream provided by the response object:
- Once this output stream is obtained, the HTML code is written to it and thus sent to the client:
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello World!</h1>");
out.println("</body>");
out.println("</html>");
3.1.2. Retrieving parameters sent by a web client
The following example shows how a servlet can retrieve parameters sent by the web client. An input form:

The response sent by the servlet:

The servlet's source code is as follows:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class myRequestParamExample extends HttpServlet {
String title="Retrieving form parameters";
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>" + title + "</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h3>" + title + "</h3>");
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
if (firstName != null || lastName != null) {
out.println("firstname= " + firstName + "<br>");
out.println("lastname= " + lastName);
} else {
out.println("no parameters");
}
out.println("<P>");
out.print("<form action=\"RequestParamExample\" method=\"POST\">");
out.println("firstname= <input type=text size=20 name=firstname>");
out.println("<br>");
out.println("lastname= <input type=text size=20 name=lastname>");
out.println("<br>");
out.println("<input type=submit>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
Note the following changes compared to the previous example:
- The parameters sent by the browser are retrieved as follows:
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
The method request.getParameter("parameterName") returns a null pointer if the parameter "parameterName" is not among the parameters sent by the web client.
- The form specifies that the browser must send the parameters using the POST method
- The received parameters will be processed by the servlet’s doPost method. Here, this method simply calls the doGet method. Thus, this servlet processes the form values regardless of whether they are sent via GET or POST.
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
3.1.3. Retrieving HTTP headers sent by a web client
The following servlet demonstrates how to retrieve the HTTP headers sent by the web client:

The source code for the servlet is as follows:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestHeaderExample extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = request.getHeader(name);
out.println(name + " = " + value);
}
}
}
Points to note:
- It is the `request` object and its `getHeaderNames` method that give us access to the HTTP headers sent by the browser in the form of an enumeration:
- The request.getHeader("header") method allows you to retrieve a specific HTTP header. The example above provides a few of them. Keep in mind that the headers shown here are sent by the browser. The server also has its own HTTP headers, which sometimes mirror those of the browser. The HTTP headers sent by the browser are intended to inform the server about the browser’s capabilities.
Header | Meaning |
Browser identity | |
MIME types accepted by the browser. For example, image/gif means that the browser can handle images in GIF format | |
in the format host:port. Indicates which machine and port the browser wants to contact. | |
encoding format accepted by the browser for documents sent by the server. Thus, if a server has a document in a normal, uncompressed form and another in gzip format, and the browser has indicated that it can handle the gzip format, then the server can send the document in gzip format to save bandwidth. | |
Languages accepted by the browser. If a server has the same document in multiple languages, it will send the version in a language accepted by the browser. | |
The URL requested by the browser | |
The connection mode requested by the browser. Keep-alive means that the server should not close the connection after serving the requested page to the browser. If the browser discovers that the received page contains links to images, for example, it can make new requests to the server to retrieve them without needing to establish a new connection. The browser will then take the initiative to close the connection once it has received all the elements of the page. |
3.1.4. Retrieving Environment Information
The following servlet demonstrates how to access the servlet’s runtime environment information. Some of this information is sent as HTTP headers by the browser and can therefore be retrieved using the previous method.

The servlet code is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestInfo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>Request Information Example</title>");
out.println("</head>");
out.println("<body>");
out.println("<h3>Request Information Example</h3>");
out.println("Method: " + request.getMethod());
out.println("Request URI: " + request.getRequestURI());
out.println("Protocol: " + request.getProtocol());
out.println("PathInfo: " + request.getPathInfo());
out.println("Remote Address: " + request.getRemoteAddr());
out.println("</body>");
out.println("</html>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
The information is obtained here using various methods:
out.println("Method: " + request.getMethod());
out.println("Request URI: " + request.getRequestURI());
out.println("Protocol: " + request.getProtocol());
out.println("PathInfo: " + request.getPathInfo());
out.println("Remote Address: " + request.getRemoteAddr());
Here is a list of some of the available methods and their meanings:
method | meaning |
the name of the web server | |
the web server's working port | |
the GET or POST method used by the browser to make its request | |
the name of the client machine from which the browser made its request | |
the IP address of that same machine | |
the content type sent by the browser (HTTP Content-Type header) | |
the number of characters sent by the browser (HTTP Content-Length header) | |
the version of the HTTP protocol requested by the browser | |
The URI requested by the browser. Corresponds to the part of the URL following the host:port identifier in http://hote:port/URI |
3.1.5. Create a servlet with JBuilder, deploy it with Tomcat
We will now describe how to create and run a Java servlet. We will use two tools: JBuilder to compile the servlet and Tomcat to run it. Tomcat alone might suffice. However, it offers limited debugging capabilities. We will revisit the example developed previously that displays the parameters received by the server. The servlet first sends the following input form:

The response sent by the servlet:

The source code for the servlet is as follows:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class myRequestParamExample extends HttpServlet {
String title="Retrieving form parameters";
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>" + title + "</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h3>" + title + "</h3>");
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
if (firstName != null || lastName != null) {
out.println("firstname= " + firstName + "<br>");
out.println("lastname= " + lastName);
} else {
out.println("No parameters");
}
out.println("<P>");
out.print("<form action=\"RequestParamExample\" method=\"POST\">");
out.println("firstname= <input type=text size=20 name=firstname>");
out.println("<br>");
out.println("lastname= <input type=text size=20 name=lastname>");
out.println("<br>");
out.println("<input type=submit>");
out.println("</form>");
out.println("</body>");
out.println("</html>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
- Create a project named myRequestParamExample using JBuilder and include the previous myRequestParamExample.java program in it.
- During compilation, you may encounter the following issue: your JBuilder may not have the javax.servlet library required to compile servlets. In this case, you need to configure JBuilder to use additional class libraries. The procedure is described in the appendices of this document for JBuilder 7. We have partially reproduced it here:
- Enable the Tools/Configure JDKs option

In the JDK Settings section above, the Name field normally displays JDK 1.3.1. If you have a newer JDK, use the Change button to specify its installation directory. Above, we have specified the directory E:\Program Files\jdk14 where a JDK 1.4 was installed. From now on, JBuilder will use this JDK for its compilations and executions. In the (Class, Source, Documentation) section, you’ll see a list of all the class libraries that JBuilder will scan—in this case, the classes from JDK 1.4. The classes included in this JDK are not sufficient for Java web development. To add additional class libraries, use the Add button and select the extra .jar files you want to use. .jar files are class libraries. Tomcat 4.x includes all the class libraries necessary for web development. They are located in <tomcat>\common\lib, where <tomcat> is the Tomcat installation directory:

Using the Add button, we will add these libraries, one by one, to the list of libraries scanned by JBuilder:

From now on, you can compile Java programs compliant with the J2EE standard, including Java servlets. JBuilder is used only for compilation; execution is subsequently handled by Tomcat.
- Now you can compile the myRequestParamExample.java program and generate the myRequestParamExample.class servlet. Where should this servlet be placed? If the initial Tomcat configuration has not been changed, the servlet .class files must be placed in <tomcat>\webapps\examples\WEB-INF\classes (Tomcat 4.x).
- Verify that Tomcat is running and use a browser to request the URL http://localhost:8080/examples/servlet/myRequestParamExample:

3.1.6. Examples
For the following examples, we used the method described above:
- compiling the servlet's XX.java source file with JBuilder
- deploying the servlet XX.class to <tomcat>\webapps\examples\WEB-INF\classes
- With Tomcat running, enter the URL http://localhost:8080/examples/servlet/XX in a browser
3.1.6.1. Dynamic Form Generation - 1
We will use as an example the generation of a form with only one control: a list. The content of this list is dynamically constructed using values taken from an array. In reality, these values are often retrieved from a database. The form is as follows:

If you click Submit on the example above, you get the following response:

Note that the URL returning the response is the same as the one displaying the form. Here, we have a servlet that processes the response to the form it sent. This is a common scenario. The HTML code for the form is as follows:
<html>
<head><title>Form Generation</title></head>
<body>
<h3>Choose a number</h3><hr>
<form method="POST">
<select name="cmbValues" size="1">
<option>zero</option>
<option>one</option>
<option>two</option>
<option>three</option>
<option>four</option>
<option>five</option>
<option>six</option>
<option>seven</option>
<option>eight</option>
<option>nine</option>
</select>
<input type="submit" value="Submit">
</form>
</body>
</html>
Note that the values sent by the form are sent using the POST method. The HTML code of the response:
<html>
<head><title>Here is my response</title></head>
<body>
You chose the number<h2>nine</h2>
</body>
</html>
The servlet code that generates this form and this response is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class gener1 extends HttpServlet{
// instance variables
private String title = "Generating a form";
private final String[] values = {"zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine"};
private final String HTML1 =
"<html>" +
"<head>" +
"<title>Form Generation</title>" +
"</head>" +
"<body>" +
"<h3>Choose a number</h3>"+
"<hr>" +
"<form method=\"POST\">";
private final String HTML2="<input type=\"submit\" value=\"Submit\">";
private final String HTML3="</form>\n</body>\n</html>";
// GET
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// Tell the client the type of document being sent
response.setContentType("text/html");
// send the form
PrintWriter out = response.getWriter();
// start
out.println(HTML1);
// dropdown
out.println("<select name=\"cmbValeurs\" size=\"1\">");
for (int i=0; i < values.length; i++) {
out.println("<option>" + values[i] + "</option>");
}//for
out.println("</select>");
// end of form
out.println(HTML2 + HTML3);
}//GET
// POST
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// retrieve the user's selection
String choice = request.getParameter("cmbValues");
if (choice == null) doGet(request, response);
// prepare the response
String response = "<html><head><title>Here is my response</title></head>";
response+="<body>You have chosen the number <h2>"+choice+"</h2></body></html>";
// tell the client the type of document being sent
response.setContentType("text/html");
// send the form
PrintWriter out = response.getWriter();
out.println(response);
}//POST
}//class
The doGet method is used to generate the form. There is a dynamic part, which is the content of the list, sourced here from an array. The doPost method is used to generate the response. Here, the only dynamic part is the value of the user’s selection in the form’s list. This value is obtained via request.getParameter("cmbValeurs"), where cmbValeurs is the HTML name of the list:
Finally, note the following points:
- The browser sends the form values to the servlet that generated the form because the <form> tag has no <action> attribute. In this case, the browser sends the data entered in the form to the URL that provided it.
- The <form> tag specifies that the form data must be sent using the POST method. This is why these values are retrieved by the servlet’s doPost method.
3.1.6.2. Dynamic Form Generation - 2
We’ll revisit the previous example and modify it as follows. The form remains the same:

But the response is different:

In the response, the form is returned, with the number chosen by the user indicated below it. Furthermore, this number is the one that appears as selected when the list is displayed. The user can then choose another number:

then click Submit. They receive the following response:

The code for the servlet named gener2.java is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class gener2 extends HttpServlet{
// instance variables
private String title = "Generating a form";
private final String[] values = {"zero", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine"};
private final String HTML1 =
"<html>" +
"<head>" +
"<title>Form Generation</title>"+
"</head>" +
"<body>" +
"<h3>Choose a number</h3>"+
"<hr>" +
"<form method=\"POST\">";
private final String HTML2="<input type=\"submit\" value=\"Submit\"></form>\n";
private final String HTML3="</body>\n</html>";
// GET
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// retrieve the user's selection, if any
String choice = request.getParameter("cmbValeurs");
if (choice == null) choice = "";
// tell the client the type of document being sent
response.setContentType("text/html");
// send the form
PrintWriter out = response.getWriter();
// start
out.println(HTML1);
// dropdown
out.println("<select name=\"cmbValeurs\" size=\"1\">");
String selected = "";
for (int i=0; i < values.length; i++) {
if(values[i].equals(choice)) selected="selected"; else selected="";
out.println("<option "+selected+">"+values[i]+"</option>");
}//for
out.println("</select>");
// form continuation
out.println(HTML2);
if(!choice.equals("")){
// display the user's choice
out.println("<hr>You chose the number <h2>"+choice+"</h2>");
}//if
// end of form
out.println(HTML3);
}//GET
// POST
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// redirect to GET
doGet(request, response);
}//POST
}//class
The doGet method does everything: it builds the form that it sends to the client and processes the values that the client returns. The following points are worth noting:
- We check if the cmbValeurs parameter has a value.
- If so, when building the list content, each item is compared to the user’s selection to set the selected attribute on the user’s chosen item: <option selected>item</option>. Additionally, the selected value is displayed below the form.
3.1.6.3. Dynamic Form Generation - 3
We’re tackling the same problem as before, but this time the values are retrieved from a database. In our example, this is a MySQL database:
- the database is named dbValues
- its owner is admDbValeurs with the password mdpDbValeurs
- the database has a single table named tvaleurs
- this table has only one integer field called value
E:\Program Files\EasyPHP\mysql\bin>mysql --database=dbValeurs --user=admDbValeurs --password=mdpDbVa
leurs
mysql> show tables;
+---------------------+
| Tables_in_dbValues |
+---------------------+
| tvaleurs |
+---------------------+
1 row in set (0.00 sec)
mysql> describe tvaleurs;
+--------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| value | int(11) | | | 0 | |
+--------+---------+------+-----+---------+-------+
mysql> select * from tvaleurs;
+--------+
| value |
+--------+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 6 |
| 5 |
| 7 |
| 8 |
| 9 |
+--------+
10 rows in set (0.00 sec)
The MySQL database dbValeurs has been made accessible via an ODBC driver for MySQL. Its DSN (Data Source Name) is odbc-valeurs. The servlet code is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.*;
public class gener3 extends HttpServlet {
// page title
private final String title = "Generating a form";
// database of list values
private final String DSNValues = "odbc-values";
private final String admDbValues = "admDbValues";
private final String mdpDbValues="mdpDbValues";
// list values
private String[] values = null;
// error message
private String errorMessage = null;
// HTML code
private final String HTML1 =
"<html>" +
"<head>" +
"<title>Form generation</title>"+
"</head>" +
"<body>" +
"<h3>Choose a number</h3>"+
"<hr>" +
"<form method=\"POST\">";
private final String HTML2="<input type=\"submit\" value=\"Submit\"></form>\n";
private final String HTML3="</body>\n</html>";
// GET
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// Tell the client the type of document being sent
response.setContentType("text/html");
// output stream
PrintWriter out = response.getWriter();
// Did the servlet initialization succeed?
if (errorMessage != null) {
// An error occurred—generate an error page
out.println("<html><head><title>"+title+"</title></head>");
out.println("<body><h3>Application unavailable ("+errorMessage+
")</h3></body></html>");
return;
}//if
// retrieve the user's selection, if any
String choice = request.getParameter("cmbValues");
if(choice == null) choice = "";
// submit the form
// start
out.println(HTML1);
// combo
out.println("<select name=\"cmbValues\" size=\"1\">");
String selected="";
for (int i=0;i<values.length;i++){
if(values[i].equals(choice)) selected="selected"; else selected="";
out.println("<option "+selected+">"+values[i]+"</option>");
}//for
out.println("</select>");
// form continuation
out.println(HTML2);
if(!choice.equals("")){
// display the user's choice
out.println("<hr>You have chosen the number <h2>"+choice+"</h2>");
}//if
// end of form
out.println(HTML3);
}//GET
// POST
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// redirect to GET
doGet(request, response);
}//POST
// Initialize the servlet
public void init(){
// populates the array of values from an ODBC database
// with DSN name: DSNvalues
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try{
// Connect to the ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
connection = DriverManager.getConnection("jdbc:odbc:" + DSNValues, admDbValues, mdpDbValues);
// Statement object
st = connection.createStatement();
// execute SELECT query to retrieve the values
rs = st.executeQuery("select value from Tvalues");
// The values are retrieved and placed in a dynamic array
ArrayList lstValues = new ArrayList();
while(rs.next()){
// store the value in the list
lstValues.add(rs.getString("value"));
}//while
// convert list to array
values = new String[lstValues.size()];
for (int i=0; i<lstValues.size(); i++) {
values[i] = (String) lstValues.get(i);
}
} catch (Exception ex) {
// problem
errorMessage = ex.getMessage();
}finally{
try{rs.close();}catch(Exception ex){}
try{st.close();}catch(Exception ex){}
try{connection.close();}catch(Exception ex){}
}//try
}//init
}//class
The key points to note are as follows:
- A servlet can be initialized by a method whose signature must be public void init(). This method is executed only when the servlet is initially loaded
- Once loaded, a servlet remains in memory at all times. This means that after serving a client, it is not unloaded. It thus responds more quickly to client requests.
- In our servlet, a list of values must be retrieved from a database. Since this list does not change over time, the init method is the ideal time to retrieve it. The database is thus accessed only once by the servlet, when it is initially loaded, rather than with every client request.
- Database access may fail. Our servlet’s init method sets an error message, msgErreur, in case of failure. This message is checked in the doGet method, and if an error occurred, doGet generates a page indicating it.
- The implementation of the init method uses standard database access with ODBC-JDBC drivers. If necessary, the reader is encouraged to review the methods for accessing JDBC databases.
When the servlet is executed and the MySQL server has not been started, the following error page appears:

If you now start the MySQL server, you will see the page:

If you select the number 6 and click "Submit":

3.1.6.4. Retrieving values from a form
We’ll revisit an example we’ve already seen, that of the following web form:

The HTML code for the balises2.htm form is as follows:
<html>
<head>
<title>tags</title>
<script language="JavaScript">
function clear(){
alert("You clicked the Clear button");
}//clear
</script>
</head>
<body background="/images/standard.jpg">
...
<form method="POST" action="http://localhost:8080/examples/servlet/parameters">
<table border="0">
<tr>
<td>Are you married?</td>
<td>
<input type="radio" value="Yes" name="R1">Yes
<input type="radio" name="R1" value="no" checked>No
</td>
</tr>
<tr>
<td>Checkboxes</td>
<td>
<input type="checkbox" name="C1" value="one">1
<input type="checkbox" name="C2" value="two" checked>2
<input type="checkbox" name="C3" value="three">3
</td>
</tr>
<tr>
<td>Input field</td>
<td>
<input type="text" name="txtSaisie" size="20" value="a few words">
</td>
</tr>
<tr>
<td>Password</td>
<td>
<input type="password" name="txtMdp" size="20" value="aPassword">
</td>
</tr>
<tr>
<td>Input field</td>
<td>
<textarea rows="2" name="areaSaisie" cols="20">
line1
line2
line3
</textarea>
</td>
</tr>
<tr>
<td>combo</td>
<td>
<select size="1" name="cmbValues">
<option>choice1</option>
<option selected>choice2</option>
<option>option3</option>
</select>
</td>
</tr>
<tr>
<td>single-select list</td>
<td>
<select size="3" name="lst1">
<option selected>list1</option>
<option>list2</option>
<option>list3</option>
<option>list4</option>
<option>list5</option>
</select>
</td>
</tr>
<tr>
<td>multiple-choice list</td>
<td>
<select size="3" name="lst2" multiple>
<option selected>list1</option>
<option>list2</option>
<option selected>list3</option>
<option>list4</option>
<option>list5</option>
</select>
</td>
</tr>
<tr>
<td>button</td>
<td>
<input type="button" value="Clear" name="cmdClear" onclick="clear()">
</td>
</tr>
<tr>
<td>send</td>
<td>
<input type="submit" value="Send" name="cmdSend">
</td>
</tr>
<tr>
<td>Reset</td>
<td>
<input type="reset" value="Reset" name="cmdReset">
</td>
</tr>
</table>
<input type="hidden" name="secret" value="aValue">
</form>
</body>
</html>
The <form> tag in the form has been defined as follows:
The browser will "post" the form values to the URL http://localhost:8080/examples/servlet/parameters, which is the URL of a servlet managed by Tomcat and which displays the values from the previous form. If we call the parameters servlet directly, we get the following results:

If the form balises2.htm entered is this one:

and you click the Submit button, the parameters servlet is called with parameters this time. It then returns the following response:

This response clearly contains the values entered in the form. The servlet code is as follows:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class parameters extends HttpServlet{
// instance variables
String title="Retrieving form parameters";
private String getParameter(HttpServletRequest request, String control){
// returns the value of request.getParameter(control) or "" if it does not exist
String value = request.getParameter(control);
if (value == null) return ""; else return value;
}//getParameter
// GET
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
// Start by retrieving the form parameters
String R1 = getParameter(request, "R1");
String C1 = getParameter(request, "C1");
String C2 = getParameter(request, "C2");
String C3 = getParameter(request, "C3");
String txtInput = getParameter(request, "txtInput");
String txtPassword = getParameter(request, "txtPassword");
String inputArea = getParameter(request, "inputArea");
String[] lines = inputArea.split("\\r\\n");
String cmbValues = getParameter(request, "cmbValues");
String lst1 = getParameter(request, "lst1");
String[] lst2 = request.getParameterValues("lst2");
String secret = getParameter(request, "secret");
// Set the document content
response.setContentType("text/html");
// send the document
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>" + title + "</title>");
out.println("</head>");
out.println("<body bgcolor=\"white\">");
out.println("<h3>" + title + "</h3>");
out.println("<hr>");
out.println("<table border=\"1\">");
out.println("<tr><td>R1</td><td>"+R1+"</td></tr>");
out.println("<tr><td>C1</td><td>"+C1+"</td></tr>");
out.println("<tr><td>C2</td><td>"+C2+"</td></tr>");
out.println("<tr><td>C3</td><td>"+C3+"</td></tr>");
out.println("<tr><td>txtInput</td><td>"+txtInput+"</td></tr>");
out.println("<tr><td>txtPassword</td><td>"+txtPassword+"</td></tr>");
for(int i=0;i<lines.length;i++)
out.println("<tr><td>areaSaisie["+i+"]</td><td>"+lignes[i]+"</td></tr>");
out.println("<tr><td>cmbValues</td><td>"+cmbValues+"</td></tr>");
out.println("<tr><td>lst1</td><td>"+lst1+"</td></tr>");
if(lst2==null)
out.println("<tr><td>lst2</td><td></td></tr>");
else
for(int i=0;i<lst2.length;i++)
out.println("<tr><td>lst2</td><td>"+lst2[i]+"</td></tr>");
out.println("<tr><td>secret</td><td>"+secret+"</td></tr>");
out.println("</body>");
out.println("</html>");
}
// POST
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
// redirects to GET
doGet(request, response);
}
}
This code uses the techniques presented earlier in another example. Note the following two points:
- The lst2 control is a multi-select list, so multiple items can be selected. This is the case in our example, where the items list1 and list3 have been selected. The values of lst2 were sent by the browser to the server in the form lst2=liste1&lst2=liste3. The Java servlet can retrieve these values in an array using the getParameterValues method: here, request.getParameterValues("lst2") returns an array of two strings ["liste1", "liste3"].
- The areaSaisie control is a multi-line input field. request.getParameter("areaSaisie") returns the field’s content as a single string. If you want to extract the individual lines within it, you can use the split method of the String class. The following code
String areaSaisie = getParameter(request, "areaSaisie");
String[] lines = areaSaisie.split("\\r\\n");
retrieves the lines from the input field. These lines are terminated by the characters \r\n (0D0A).
To perform the tests, we have:
- built and compiled the servlet parameters using JBuilder, as explained earlier
- placed the generated class in <tomcat>\webapps\examples\WEB-INF\classes, where <tomcat> is the Tomcat installation directory.
- requested the URL http://localhost:81/html/balises2.htm, the code for which was presented above
- filled out the form and clicked the Submit button.
3.1.6.5. Retrieving HTTP headers from a web client
We’ll use the same example as before, but in response to the web client that sent the form values, we’ll send back the HTTP headers it sent at the same time. We’ll make a single change to our form:
The form values will be sent using the GET method to a Java servlet named headers located in <tomcat>\webapps\examples\WEB-INF\classes. The headers servlet was built and compiled with JBuilder:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class headers extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
// Set the document type
response.setContentType("text/html");
// get a write stream
PrintWriter out = response.getWriter();
// display list of HTTP headers
Enumeration e = request.getHeaderNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = request.getHeader(name);
out.println("<b>" + name + "</b> = " + value + "<br>");
}
}//GET
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
//GET
doGet(request, response);
}//POST
}
We request the URL http://localhost:81/html/balises2.htm and click Submit without modifying the form. We get the following response:

Note the parameterized URL in the browser's Address bar, which shows the method (GET) used to transmit the parameters. We'll use the same example but change the method for sending the parameters (POST):
We get the following new response:

Note the HTTP headers content-type and content-length, which are characteristic of a POST request. Additionally, note that the form values no longer appear in the browser's Address field.
3.2. JSP Pages
JSP (Java Server Pages) are another way to write web server applications. In fact, these JSP pages are translated into servlets before being executed, so we are essentially dealing with servlet technology. JSP pages allow for a clearer highlighting of the structure of the generated HTML pages. Below are some examples, some of which can be accessed by following the JSP link on the Tomcat homepage:
![]() | ![]() |
3.2.1. Retrieving Environment Information
Here we revisit an example previously covered with a servlet: displaying a servlet’s environment variables. This is the “snoop” example from the JSP examples:

The source code for the JSP page is located in <tomcat>\jakarta-tomcat\examples\jsp\snp\snoop.jsp (Tomcat 3.x) or <tomcat>\examples\jsp\snp\snoop.jsp (Tomcat 4.x)
<html>
<!--
Copyright (c) 1999 The Apache Software Foundation. All rights
reserved.
-->
<body bgcolor="white">
<h1> Request Information </h1>
<font size="4">
JSP Request Method: <%= request.getMethod() %>
<br>
Request URI: <%= request.getRequestURI() %>
<br>
Request Protocol: <%= request.getProtocol() %>
<br>
Servlet path: <%= request.getServletPath() %>
<br>
Path info: <%= request.getPathInfo() %>
<br>
Translated path: <%= request.getPathTranslated() %>
<br>
Query string: <%= request.getQueryString() %>
<br>
Content length: <%= request.getContentLength() %>
<br>
Content type: <%= request.getContentType() %>
<br>
Server name: <%= request.getServerName() %>
<br>
Server port: <%= request.getServerPort() %>
<br>
Remote user: <%= request.getRemoteUser() %>
<br>
Remote address: <%= request.getRemoteAddr() %>
<br>
Remote host: <%= request.getRemoteHost() %>
<br>
Authorization scheme: <%= request.getAuthType() %>
<hr>
The browser you are using is <%= request.getHeader("User-Agent") %>
<hr>
</font>
</body>
</html>
Note the following points:
- This code closely resembles HTML. However, it contains <%= expression %> tags that are specific to the JSP language. The JSP compiler replaces the entire tag in the HTML text with the value of expression.
- This example uses methods of the Java `request` object, which is the `request` object already encountered in the study of servlets. It is therefore an `HttpServletRequest` object. Thus, the tag `<%= request.getRemoteHost() %>` will be replaced in the HTML code by the name of the web client machine that made the request.
- You can achieve the same result with a servlet, but here the structure of the web page is more obvious.
3.2.2. Retrieving parameters sent by the web client
Here we revisit the example we previously studied with a servlet. A form is presented to the browser:

In response to the request above, the browser receives the following page:

The code for the JSP page is as follows:
<%
// local variables for the main procedure
String title="Retrieving form parameters";
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
%>
<!-- HTML code -->
<html>
<head>
<title><%= title %></title>
</head>
<body bgcolor="white">
<h3><%= title %></h3>
<%
if (firstName != null || lastName != null) {
out.println("firstname= " + firstName + "<br>");
out.println("lastname= " + lastName);
} else {
out.println("no parameters");
}
%>
<P>
<form method="POST">
firstname= <input type="text" size="20" name="firstname">
<br>
lastname= <input type="text" size="20" name="lastname">
<br>
<input type="submit">
</form>
</body>
</html>
- While we see the <%= expression %> tag again, as in the previous example, a new tag appears: <% Java instructions; %>. The <% tag introduces Java code. This code ends when it encounters the closing code tag %>.
- The entire preceding code (HTML + JSP) will be converted into a Java servlet. It will be enclosed within a single method, known as the main method of the JSP page. This is why the Java variables declared at the beginning of the JSP page are accessible in the other portions of JSP code interspersed throughout the HTML: these variables and code segments will be part of the same Java method. However, if our JSP code were to contain methods, the variables `title`, `firstname`, and `lastname` would not be accessible within them due to method scoping. We would need to make them global variables or pass them as parameters to the methods. We will return to this later.
- To include dynamic parts in the HTML code, two methods are possible: <%= expression %> or out.println(expression). The out object is an output stream similar to the one of the same name encountered in the servlet examples, but not of the same type: it is a JspWriter object, not a PrintWriter. It allows writing to the HTML stream using the print and println methods.
- The JSP page better reflects the structure of the generated HTML page than the equivalent servlet.
3.2.3. JSP Tags
Here is a list of tags you might encounter in a JSP page and their meanings.
tag | Meaning |
HTML comment. Sent to the client. | |
JSP comment. Not sent to the client. | |
Declares global variables and methods. The variables will be available in all methods | |
The value of the expression will be inserted into the HTML page in place of the tag | |
contains Java code that will be part of the main method of the JSP page | |
sets attributes for the JSP page. For example: import="java.util.*,java.sql.*" to specify the libraries required by the JSP page extends="aParentClass" to have the JSP page inherit from another class |
3.2.4. JSP Implicit Objects
In the previous examples, we encountered two undeclared objects: request and out. These are two of the objects that are automatically defined in the servlet into which the JSP page is converted. They are called implicit or predefined objects. There are others, but these are the most commonly used along with the response object:
object | meaning |
the object through which you can access the web client’s request (getParameter, getParameterNames, getParameterValues) | |
The object used to construct the web server's response to the client. Allows you to set the HTTP headers to be sent to the web client. | |
the output stream that allows us to send HTML code to the client (print, println) |
3.2.5. Converting a JSP page into a servlet
Let’s revisit the JSP code from myRequestParamExample.jsp:
<%
// local variables for the main procedure
String title="Retrieving form parameters";
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
%>
<!-- HTML code -->
<html>
<head>
<title><%= title %></title>
</head>
<body bgcolor="white">
<h3><%= title %></h3>
<%
if (firstName != null || lastName != null) {
out.println("firstname= " + firstName + "<br>");
out.println("lastname= " + lastName);
} else {
out.println("no parameters");
}
%>
<P>
<form method="POST">
firstname= <input type="text" size="20" name="firstname">
<br>
lastname= <input type="text" size="20" name="lastname">
<br>
<input type="submit">
</form>
</body>
</html>
When the browser requests this JSP page from the Tomcat server, the server will convert it into a servlet. If the requested URL is
http://localhost:8080/examples/jsp/perso/intro/myRequestParamExample.jsp, Tomcat 4.x will place the generated servlet in the directory <tomcat>\work\localhost\examples\jsp\perso\intro:

This name reflects the JSP page’s URL, http://localhost:8080/examples/jsp/perso/intro/myRequestParamExample.jsp. As shown above, we can access the Java code of the servlet generated for the JSP page. In our example, it is as follows:
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;
public class myRequestParamExample$jsp extends HttpJspBase {
static {
}
public myRequestParamExample$jsp( ) {
}
private static boolean _jspx_inited = false;
public final void _jspx_init() throws org.apache.jasper.runtime.JspException {
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
try {
if (_jspx_inited == false) {
synchronized (this) {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
}
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=ISO-8859-1");
pageContext = _jspxFactory.getPageContext(this, request, response,
"", true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
// local variables for the main procedure
String title = "Retrieving form parameters";
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
out.write("\r\n\r\n<!-- HTML code -->\r\n<html>\r\n <head>\r\n <title>");
out.print( title );
out.write("</title>\r\n </head>\r\n <body bgcolor=\"white\">\r\n <h3>");
out.print( title );
out.write("</h3>\r\n ");
if (firstName != null || lastName != null) {
out.println("firstname= " + firstName + "<br>");
out.println("lastname= " + lastName);
} else {
out.println("no parameters");
}
out.write("\r\n <P>\r\n <form method=\"POST\">\r\n firstname= <input type=\"text\" size=\"20\" name=\"firstname\">\r\n <br>\r\n lastname= <input type=\"text\" size=\"20\" name=\"lastname\">\r\n <br>\r\n <input type=\"submit\">\r\n </form>\r\n </body>\r\n</html>\r\n");
} catch (Throwable t) {
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
}
}
}
The generated code is quite complex. We will focus only on the following points:
- The servlet's main method is as follows:
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
This method is called when the servlet starts. We can see that it takes two parameters: the client’s request and a response object to generate its response to the web client.
- In the main method, a JspWriter object named out is declared and then initialized. This object is used to send HTML code to the client via the out.print("HTML code") statement.
- The Java code
<%
// local variables in the main procedure
String title="Retrieving form parameters";
String firstName = request.getParameter("firstname");
String lastName = request.getParameter("lastname");
%>
has been included in its entirety in the servlet's main _jspService method. The same applies to any code located within the <%… %> tags
- The HTML code of the JSP page is output using the out.print("codeHTML") or out.write(...) statements. For example
out.write("</title>\r\n </head>\r\n <body bgcolor=\"white\">\r\n <h3>");
- In this example, there are no methods other than the main _jspService method.
3.2.6. Methods and global variables of a JSP page
Consider the following JSP page:
<%!
// the previous tag starts the global variables and methods section
// this section will be included unchanged in the servlet
// a global variable
String firstName="unknown";
// a method
private String getDog(){
return "Milou";
}//hisDog
// another method
private void displayFriend(JspWriter out) throws Exception{
out.println("<p>His friend's name is Haddock</p>");
}//displayFriend
// end of the global part of the servlet
%>
<%
// the preceding tag indicates that the following code will be saved
// in the servlet's main method
// variable local to the main method
String name="tintin";
%>
<%-- HTML code --%>
<html>
<head>
<title>JSP Page</title>
</head>
<body>
<center>
<h2>JSP Page</h2>
<p>Their name is <%= name %></p>
<p>His first name is <%= firstName %></p>
<p>His dog's name is <%= sonChien() %></p>
<%
// his friend's name
displayFriend(out);
%>
</center>
</body>
</html>
This JSP page generates the following web page:

Let’s take a look at how the four lines above are generated:
<p>His name is <%= name %></p>
<p>His first name is <%= firstName %></p>
<p>His dog's name is <%= sonChien() %></p>
<%
// the name of his friend
displayFriend(out);
%>
The lines above are within a <%..%> tag and will therefore be part of the main _jspService method of the servlet that will be generated. How do they access the variables lastName, firstName, and the methods hisDog and displayFriend?
is a local variable of the main method of the JSP page and is therefore known within it | |
is a global variable of the JSP page and is therefore known within the main method | |
is a public method of the JSP page and is therefore accessible from the main method | |
is a public method of the JSP page and is therefore accessible from the main method. Note that the out object is passed as a parameter to the method. This is mandatory here. In fact, the out object is declared and initialized in the servlet’s main method and is not a global variable. |
Let’s now look at the code for the Java servlet generated from this JSP page, once the unnecessary code has been removed:
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;
public class tintin$jsp extends HttpJspBase {
// The previous tag marks the start of the global variables and methods section
// this section will be included unchanged in the servlet
// a global variable
String firstName="unknown";
// a method
private String getDog(){
return "Milou";
}//hisDog
// another method
private void displayFriend(JspWriter out) throws Exception{
out.println("<p>His friend's name is Haddock</p>");
}//displayFriend
// end of the servlet's global section
static {
}
public tintin$jsp() {
}
private static boolean _jspx_inited = false;
public final void _jspx_init() throws org.apache.jasper.runtime.JspException {
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
try {
if (_jspx_inited == false) {
synchronized (this) {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
}
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=ISO-8859-1");
pageContext = _jspxFactory.getPageContext(this, request, response,
"", true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
out.write(" \r\n\r\n");
// The preceding tag indicates that the following code will be saved
// in the servlet's main method
// local variable in the main method
String name="tintin";
out.write("\r\n\r\n\r\n");
out.write("\r\n<html>\r\n <head>\r\n <title>JSP Page</title>\r\n </head>\r\n <body>\r\n <center>\r\n <h2>JSP Page</h2>\r\n <p>Her name is ");
out.print( lastName );
out.write("</p>\r\n <p>His first name is ");
out.print( first_name );
out.write("</p>\r\n <p>His dog's name is ");
out.print( hisDog() );
out.write("</p>\r\n ");
// his friend's name
displayFriend(out);
out.write("\r\n </center>\r\n </body>\r\n</html>\r\n");
} catch (Throwable t) {
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
}
}
}
As shown above, the Java code that was located between the JSP tags <%! .. %> has been included in its entirety and is not part of the servlet’s main method, _jspService. The variables declared in this section are instance variables and are therefore global to the methods; this is also where methods other than _jspService can be defined.
// this section will be included unchanged in the servlet
// a global variable
String firstName="unknown";
// a method
private String getDog(){
return "Milou";
}//hisDog
// another method
private void displayFriend(JspWriter out) throws Exception{
out.println("<p>His friend's name is Haddock</p>");
}//displayFriend
// end of the servlet's global section
3.2.7. Deploying and Debugging JSP Pages on the Tomcat Server
When you want to build a JSP page and use it with the Tomcat server, the question arises of where to place the page in the server directory structure. There are different ways to do this, which we’ll come back to later. For now, the simplest approach is to place the JSP page in a folder within the directory tree <tomcat>\webapps\examples\jsp (Tomcat 4.x), where <tomcat> is the Tomcat installation directory. Thus, the URL in the previous example was http://localhost:8080/examples/jsp/perso/tintin/tintin.jsp. This means that the tintin.jsp page was located in the <tomcat>\webapps\examples\jsp\perso\tintin folder.
A JSP page is translated into a Java source file, which is then compiled by Tomcat when the JSP page’s URL is requested by a browser. Compilation errors may occur. Tomcat 4.x reports them in its response to the browser. It specifically indicates which lines of the .java file contain errors. Errors can have various causes:
- the JSP code on the page is incorrect (e.g., errors in the JSP tags used)
- the Java code included in the JSP page is incorrect
The first cause can be eliminated by checking the page’s JSP code. The second can be eliminated by checking the Java code. This can be done by directly compiling the .java file generated for the JSP page using a tool such as JBuilder, which offers more advanced debugging capabilities than Tomcat.
3.2.8. Examples
We’ll revisit the example we covered earlier involving a servlet where a user selects a number from a list, and the server tells the user which number they selected while returning the same list with the user’s chosen element highlighted:

To build this page, we retrieved the servlet code and modified it as follows:
- we kept the Java code that did not generate HTML code as-is
- The Java code that generated HTML code was converted into a mix of HTML and JSP code
This results in the following JSP page:
<%@ page import="java.sql.*, java.util.*" %>
<%!
// global application variables
// page title
private final String title="Generating a form";
// database for list values
private final String DSNValues = "odbc-values";
private final String admDbValues = "admDbValues";
private final String mdpDbValues="mdpDbValues";
// list values
private String[] values = null;
// error message
private String errorMessage = null;
// Initialization of the JSP page - executed only once
public void jspInit(){
// populates the values array from an ODBC database
// with DSN name: DSNvalues
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try{
// Connect to the ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
connection = DriverManager.getConnection("jdbc:odbc:" + DSNValues, admDbValues, mdpDbValues);
// Statement object
st = connection.createStatement();
// execute SELECT query to retrieve the values
rs = st.executeQuery("select value from Tvalues");
// The values are retrieved and placed in a dynamic array
ArrayList lstValues = new ArrayList();
while(rs.next()){
// the value is added to the list
lstValues.add(rs.getString("value"));
}//while
// convert list to array
values = new String[lstValues.size()];
for (int i = 0; i < lstValues.size(); i++) {
values[i] = (String) lstValues.get(i);
}
} catch (Exception ex) {
// problem
errorMessage = ex.getMessage();
}finally{
try{rs.close();}catch(Exception ex){}
try{st.close();}catch(Exception ex){}
try{connection.close();}catch(Exception ex){}
}//try
}//init
%>
<%
// _jspService code executed on every client request
// Was there an error during the initialization of the JSP page?
if(errorMessage!=null){
%>
<!-- HTML code -->
<html>
<head>
<title>Error</title>
</head>
<body>
<h3>Application unavailable (<%= msgError %></h3>
</body>
</html>
<%
// end of jspService
return;
}//if
// retrieve the user's selection, if any
String choice = request.getParameter("cmbValeurs");
if(choice == null) choice = "";
%>
<%-- no error - HTML code for the normal page --%>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h3>Select a value</h3>
<form method="POST">
<select name="cmbValues">
<%
// dynamically display values
String selected="";
for (int i=0;i<values.length;i++){
if(values[i].equals(choice)) selected="selected"; else selected="";
out.println("<option "+selected+">"+values[i]+"</option>");
}//for
%>
</select>
<input type="submit" value="Submit">
</form>
<%
// Was a value selected?
if(!choice.equals("")){
// display the user's choice
%>
<hr>You have chosen the number<h2><%= choice %></h2>
<%
}//if
%>
</body>
</html>
Note the following points:
- the servlet's import statements are enclosed in a <% page import="..." %> directive
- The <%! ... %> tag encloses the application's global variables and Java methods
- The servlet’s init method, which is executed only once when the servlet loads, is called jspInit for a JSP page. These two methods serve the same purpose. Therefore, the code for the servlet’s init method has been included here in its entirety.
- The servlet's instance variables—those that must be accessible across multiple methods—have been included verbatim. These are primarily the title, values, and msgError variables, which are subsequently used in the JSP code.
- The <% ... %> tags enclose Java code that will be included in the _jspService method executed when a client makes a request.
- As with the servlet, the _jspService method will first check the value of the msgError variable to determine whether it needs to generate an error page. If there is an error, it generates the error page and exits (return).
- If there is no error, it generates the form with the list of values
- Once this is done, it checks whether the user selected a number; if so, it displays that number on the generated page
What are the advantages over a servlet? Undoubtedly, a clearer view of the generated HTML code. But there is still a lot of Java code that "clutters" this view. We’ll look at another method later called delegation, where we can put most of the Java code in a servlet, with the JSP page retaining only the HTML and JSP code. This clearly separates the processing part from the presentation part.
3.3. Deploying a Web Application on the Tomcat Server
We will now explain how to deploy Java web applications using the Tomcat server. While the following instructions are specific to this server, deploying a Java web application within another J2EE container will involve steps similar to those described here.
3.3.1. The server.xml and web.xml configuration files
Until now, to test our servlets and JSP pages, we have placed
- the servlets in the <tomcat>\webapps\examples\WEB-INF\classes folder. They were then accessible via the URL http://localhost:8080/examples/servlet/nomServlet
- the JSP pages in the directory tree <tomcat>\webapps\examples\jsp. They were then accessible via the URL http://localhost:8080/examples/jsp/nomPageJSP
We never explained why this was the case. The Tomcat server is configured in a text file called server.xml, located in the <tomcat>\conf directory:

This text file is actually an XML (eXtended Markup Language) file. An XML document is a text document containing tags, just like an HTML document. However, while HTML tags are well-defined, XML tags are not. Thus, the following document is an XML document:
An XML document is simply a "tagged" document that follows certain tagging rules:
- a tagged text in the form <xx att1="val1" att2="val2" ....>text</xx>
- a tag can stand alone and take the form <xx att1="val1" att2="val2" ..../>
The "att" fields are called attributes of the "xx" tag, and the "val" fields are the values associated with these attributes. Some HTML documents are not valid XML documents. For example, the HTML tag <br> is not a valid XML tag. It should be written as <br/> to be valid, in order to comply with the rule that all XML tags must be closed. A variant of HTML called XHTML was created to ensure that every XHTML document is a valid XML document. Some modern browsers are capable of displaying XML files. So if we call the XML document shown in the example above "person.xml" and view it with IE6, we get the following display:

IE6 recognizes the tags and highlights them. It also recognizes the document’s structure based on the tags. So if we call the following document “person2.xml”:
and view it with IE6, we get the same display:

IE6 correctly recognized the structure and content of the document. The whole point of an XML document lies in this property: it is easy to retrieve the structure and content of an XML document. This is done using a program called an XML parser. XML documents are becoming the standard for document exchange on the web. Let’s consider machine A, which needs to send a DOC document to machine B. The DOC document is constructed from information contained in database DB-A. Machine B must store the DOC document in database DB-B. The exchange can take place as follows:
- Machine A retrieves the data from database DB-A and encapsulates it in an XML text document
- the XML document is sent to machine B over the network
- Machine B analyzes the received document with an XML parser and extracts both the structure and the data (as IE6 did in our example). It can then store the received data in database DB-B
We won’t say any more about the XML language, which deserves a book all its own.
Here, then, Tomcat is configured by the XML file server.xml. If we view this file with IE6, we get a complex document. We will simply focus on the following lines:

It is the <Context ...> tag that interests us here. It is used to define web applications. Two of its attributes are worth noting:
- path: this is the name of the web application
- docBase: this is the folder in which it is located. Here it is a relative name: examples. Relative to which folder? The answer is also found in the server.xml file in the following line:

The line above defines the web server:
- name: name of the web server
- appBase: root of the document tree it serves. Again, we have a relative name: webapps. It is relative to the Tomcat server installation directory <tomcat>. Thus, this refers to the folder <tomcat>\webapps.
The examples web application stores its files in the examples folder (see docBase above). This name is relative to the root of the server’s web directory tree, i.e., <tomcat>\webapps. It is therefore the <tomcat>\webapps\examples folder. Let’s take a closer look at this folder:

There we find the WEB-INF\classes folder where we stored our servlets for testing. The WEB-INF folder contains a file called web.xml:

This file is used to configure the examples web application. We won’t go into the details of this file, which is too complex for now. We’ll simply focus on the following few lines:
<servlet>
<servlet-name>
servletToJsp
</servlet-name>
<servlet-class>
servletToJsp
</servlet-class>
</servlet>
The <servlet> tag is used to define a servlet within a web application. Note that the web application in question is examples. The servlet tag contains two other tags:
- <servlet-name>servletToJsp</servlet-name>: defines the name of the servlet
- <servlet-name>servletToJsp</servlet-name>: defines the name of the class to be executed when the servlet is requested. In this example, the servlet and its class have the same name. This is not mandatory.
How is the servlet servletToJsp requested by a browser from the Tomcat server?
- The browser requests the URL http://localhost:8080/examples/servlet/servletToJsp
- Tomcat parses the servlet path /examples/servlet/servletToJsp. It interprets the first part of the path /examples as the name of a web application and looks in its server.xml configuration file to see where the documents for this application are stored. As we saw earlier, this is in the <tomcat>\webapps\examples folder.
- Tomcat uses the rest of the servlet’s path to locate it within the examples web application. This path /servlet/servletToJsp indicates that it must execute the servlet named servletToJsp. Tomcat will then read the web.xml configuration file for the examples application, which it will find in <tomcat>\webapps\examples\WEB-INF. It will find in this file that the servlet servletToJsp is linked to the Java class servletToJsp (see the web.xml file above). It will then look for this class in the WEB-INF\classes folder of the examples web application, i.e., in <tomcat>\webapps\examples\WEB-INF\classes, and execute it.

3.3.2. Example: Deploying the "list" web application
We’ll revisit a servlet we’ve already studied, which presented the user with a list of numbers from which they selected one. The servlet then confirmed the number they had chosen:

As shown in the browser’s Address field above, the servlet’s class file was named gener3. Based on the explanations provided earlier:
- the URL /examples/servlet/gener3 indicates that this is a servlet named gener3 from the examples web application
- in the web.xml file of the examples application, there is nothing mentioning a servlet named gener3. How did Tomcat find it, then? Having gone through the entire web.xml file, I cannot answer with certainty... The question remains...
We choose to deploy the gener3.class servlet under the name lstValeurs in a web application called liste located in the E:\data\serge\Servlets\lstValeurs folder:

We place the gener3.class file in the WEB-INF\classes folder mentioned above:

We configure the liste web application by adding the following lines to the server.xml file above those that define the manager web application:
<!-- Perso: lstValeurs -->
<Context path="/liste" docBase="e:/data/serge/servlets/lstValeurs" />
<!-- Tomcat Manager Context -->
<Context path="/manager" docBase="manager" debug="0" privileged="true" />
<!-- Tomcat Examples Context -->
<Context path="/examples" docBase="examples" debug="0" reloadable="true" crossContext="true">
........
The line defining the lstValeurs application indicates that it is located in the e:/data/serge/servlets/lstValeurs folder. We must now define the web.xml file for this application. This file will define the application’s single servlet:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>lstValues</servlet-name>
<servlet-class>gener3</servlet-class>
</servlet>
</web-app>
The file above indicates that the servlet named lstValeurs is associated with the class file gener3.class. This web.xml file must be created and saved in the WEB-INF folder of the liste application:

The screenshot above shows a src folder in which the source file gener3.java has been placed. This folder may not exist. It serves no purpose in this demonstration. We are ready to run the tests:
- Stop and restart Tomcat so that it re-reads its server.xml configuration file. Here we are using Windows. On Unix, you can force Tomcat to re-read its configuration file without stopping it.
- Using a browser, request the URL http://localhost:8080/liste/servlet/lstValeurs

We can see that the previous URL contains the keyword *servlet*, just like all the servlet URLs used so far. We can eliminate this by associating the lstValeurs servlet with a URL pattern (*url-pattern*) in the application’s web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>lstValues</servlet-name>
<servlet-class>gener3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>lstValues</servlet-name>
<url-pattern>/values</url-pattern>
</servlet-mapping>
</web-app>
In the <servlet-mapping> tag, we associate the path /values with the lstValeurs servlet defined in the preceding lines. We save the new web.xml file and request the URL http://localhost:8080/liste/valeurs:

3.3.3. Deploying the public pages of a web application
We have just seen how to deploy a web application consisting of a single servlet. A web application can have many components: servlets, JSP pages, HTML files, Java applets, etc. Where do we place these application elements? If <application> is the web application directory defined by the application’s docBase attribute in the server.xml file of the Tomcat configuration ( ), we saw that servlets are placed in <application>\WEB-INF\classes. The other application components can be placed anywhere within the <application> directory tree except in the WEB-INF directory. Consider the JSP application listvaleurs.jsp we studied earlier:

This JSP page was stored in the <tomcat>\webapps\examples\jsp\perso\listvaleurs folder. This page could be a component of the previously deployed list application. Let’s place the listvaleurs.jsp file directly in this application’s folder:

Recall the configuration of the liste application in the server.xml file:
Any URL starting with the path /liste is considered part of the liste application and will be looked for in the specified folder. Let’s request the URL http://localhost:8080/liste/listvaleurs.jsp using a browser:

We have indeed obtained the expected JSP page.
3.3.4. Servlet Initialization Parameters
We have seen that a servlet is configured by the file <application>\WEB-INF\web.xml, where <application> is the folder of the web application to which it belongs. It is possible to include servlet initialization parameters in this file. Let’s return to our lstValeurs servlet from the liste web application, whose configuration file was as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>lstValues</servlet-name>
<servlet-class>gener3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>lstValues</servlet-name>
<url-pattern>/values</url-pattern>
</servlet-mapping>
</web-app>
The class associated with the servlet is the gener3 class. The source code for this class contains the definition of several constants:
public class gener3 extends HttpServlet{
// the page title
private final String title="Generating a form";
// the database of list values
private final String DSNValues = "odbc-values";
private final String admDbValues = "admDbValues";
private final String mdpDbValues = "mdpDbValues";
Let’s review the meaning of the four constants defined above:
title of the HTML document generated by the servlet | |
DSN name of the ODBC database from which the servlet retrieves data | |
username of a user with read access to the aforementioned database | |
their password |
If the administrator of the DSNValeurs database changes the password for the user admDbValeurs, the servlet source code must be modified and recompiled. This is not very practical. The servlet’s web.xml configuration file offers an alternative by allowing the definition of servlet initialization parameters using the <init-param> tag:
allows you to define the parameter name | |
defines the value associated with the previous parameter |
The servlet can access its initialization parameters using the following methods:
A method of the Servlet class, from which the HttpServlet class used for web programming is derived. Returns a ServletConfig object providing access to the servlet's configuration parameters. | |
A method of the ServletConfig class that returns the value of the initialization parameter "parameter" |
We configure the "liste" application with the following new web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>lstValues</servlet-name>
<servlet-class>gener3</servlet-class>
</servlet>
<servlet>
<servlet-name>lstValues2</servlet-name>
<servlet-class>gener5</servlet-class>
<init-param>
<param-name>title</param-name>
<param-value>Generate a form</param-value>
</init-param>
<init-param>
<param-name>DSNValues</param-name>
<param-value>odbc-values</param-value>
</init-param>
<init-param>
<param-name>admDbValues</param-name>
<param-value>admDbValues</param-value>
</init-param>
<init-param>
<param-name>mdpDbValues</param-name>
<param-value>mdpDbValues</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>lstValues</servlet-name>
<url-pattern>/values</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>lstValues2</servlet-name>
<url-pattern>/values2</url-pattern>
</servlet-mapping>
</web-app>
In the list application, we define a second servlet called lstValeurs2 linked to the gener5 class file. This file has been placed in <application>\WEB-INF\classes:

The lstValeurs2 servlet has four initialization parameters: title, DSNValeurs, admDbValeurs, mdpDbValeurs. Additionally, the alias /values2 has been defined for the servlet using the <servlet-mapping> tag. Thus, the lstValues2 servlet in the list application will be accessible via the URL http://localhost:8080/liste/valeurs2.
The servlet's source code has been modified as follows to retrieve the servlet's initialization parameters:
public class gener5 extends HttpServlet{
// the page title
private String title=null;
// the database of list values
private String DSNValues = null;
private String admDbValues = null;
private String dbPassword = null;
...............
// Initialization of the servlet
public void init(){
// retrieve the servlet's initialization parameters
ServletConfig config = getServletConfig();
title = config.getInitParameter("title");
DSNValues = config.getInitParameter("DSNValues");
admDbValues = config.getInitParameter("admDbValues");
mdpDbValues = config.getInitParameter("mdpDbValues");
//Have all parameters been retrieved?
if(title==null || DSNValues==null || admDbValues==null
|| mdpDbValues==null){
errorMessage = "Incorrect configuration";
return;
}
// populate the values array from an ODBC database
// with the DSN name: DSNvalues
...............
To test the servlet, you must restart Tomcat so that it can load the new web.xml configuration file for the "liste" application. Using a browser, request the servlet's URL: http://localhost:8080/liste/valeurs2:

If any of the initialization parameters required by the servlet are missing from the web.xml file, the following page is displayed:

3.3.5. Initialization Parameters for a Web Application
In the previous example, only the lstValeurs2 servlet has access to the title, DSNValeurs, admDbValeurs, and mdpDbValeurs parameters. It is possible that another servlet in the same liste application might need data from the same database used by the lstValeurs2 servlet. In that case, the parameters DSNValeurs, admDbValeurs, and mdpDbValeurs would need to be redefined in the configuration section of the new servlet’s web.xml file. Another solution is to define parameters common to multiple servlets at the application level rather than at the servlet level. The new web.xml file for the application becomes as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>DSNValues</param-name>
<param-value>odbc-values</param-value>
</context-param>
<context-param>
<param-name>admDbValues</param-name>
<param-value>admDbValues</param-value>
</context-param>
<context-param>
<param-name>mdpDbValues</param-name>
<param-value>mdpDbValues</param-value>
</context-param>
<servlet>
<servlet-name>lstValues</servlet-name>
<servlet-class>gener3</servlet-class>
</servlet>
<servlet>
<servlet-name>lstValues3</servlet-name>
<servlet-class>gener6</servlet-class>
<init-param>
<param-name>title</param-name>
<param-value>Generate a form</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>lstValues</servlet-name>
<url-pattern>/values</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>lstValues3</servlet-name>
<url-pattern>/values3</url-pattern>
</servlet-mapping>
</web-app>
The new servlet is called lstValeurs3, is linked to the gener6 class file, and has been associated with the alias /valeurs3 (servlet mapping). The title parameter is the only parameter that has been retained in the servlet definition. The others have been placed in the application configuration within <context-param> tags. This tag is used to define information specific to the application, not to a particular servlet or JSP page. How does the Java servlet access these parameters, often called context parameters? The methods available for obtaining context information are very similar to those used to obtain servlet-specific initialization parameters:
a method of the Servlet class from which the HttpServlet class used for web programming is derived. Returns a ServletContext object providing access to the application’s configuration parameters | |
method of the ServletContext class that returns the value of the initialization parameter "parameter" |
The gener6.java class makes only the following changes to the Java code from gener5.java used previously:
// retrieve the servlet's initialization parameters
ServletConfig config=getServletConfig();
title = config.getInitParameter("title");
ServletContext context = getServletContext();
DSNValues = context.getInitParameter("DSNValues");
admDbValues = context.getInitParameter("admDbValues");
mdpDbValues = context.getInitParameter("mdpDbValues");
//Have all parameters been retrieved?
if(title == null || DSNValues == null || admDbValues == null
|| mdpDbValues==null){
errorMessage = "Incorrect configuration";
return;
}
// populate the values array from an ODBC database
// with the DSN name: DSNvalues
...............
The title parameter specific to the servlet is obtained via a ServletConfig object. The other three parameters defined at the application level are obtained via a ServletContext object. We compile this class and place it, like the others, in <application>\WEB-INF\classes:

We restart Tomcat so that it takes the application’s new web.xml file into account and request the URL http://localhost:8080/liste/valeurs3:

3.3.6. Initialization Parameters for a JSP Page
We have seen how to define initialization parameters for a servlet or a web application. Can we do the same for a JSP page? Let’s go back to the beginning of the code for the listvaleurs.jsp page we already studied:
<%@ page import="java.sql.*, java.util.*" %>
<%!
// global application variables
// page title
private final String title="Generating a form";
// database of list values
private final String DSNValues = "odbc-values";
private final String admDbValues = "admDbValues";
private final String mdpDbValues = "mdpDbValues";
.........
We find the four constants title, DSNValues, admDbValues, and mdpDbValues defined in the application’s web.xml file. The constants DSNValues, admDbValues, and mdpDbValues have now been defined at the application level, so we can assume that a JSP page belonging to this application will have access to them. This is indeed the case. We know that the JSP page will be translated into a servlet. The servlet will have access to the context via the getServletContext() method. The case of the title constant is more delicate. In fact, we defined it at the servlet level rather than at the application level as follows:
<servlet>
<servlet-name>lstValeurs3</servlet-name>
<servlet-class>gener6</servlet-class>
<init-param>
<param-name>title</param-name>
<param-value>Generate a form</param-value>
</init-param>
</servlet>
For the JSP page, the previous syntax is no longer appropriate because the concept of a class file no longer applies. However, the configuration syntax for a JSP page is very similar to that of a servlet. It is as follows:
<servlet>
<servlet-name>JSPlstValues</servlet-name>
<jsp-file>/listvalues2.jsp</jsp-file>
...
</servlet>
In fact, a JSP page is treated as a servlet to which a name is assigned (servlet-name). Instead of associating a class file with this servlet, we associate the source file of the JSP page to be executed (jsp-file). Thus, the preceding lines define a servlet named JSPlstValues associated with the JSP page /listvalues2.jsp. The path /listvalues2.jsp is relative to the application root. Thus, in the case of our list application, the file listvalues2.jsp would be located in the docBase folder (see server.xml) of the list application:

The configuration of the JSP page will be as follows in the application’s web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>DSNValues</param-name>
<param-value>odbc-values</param-value>
</context-param>
<context-param>
<param-name>admDbValues</param-name>
<param-value>admDbValues</param-value>
</context-param>
<context-param>
<param-name>mdpDbValues</param-name>
<param-value>mdpDbValues</param-value>
</context-param>
.......
<servlet>
<servlet-name>JSPlstValues</servlet-name>
<jsp-file>/listvalues2.jsp</jsp-file>
<init-param>
<param-name>JSPtitle</param-name>
<param-value>Generate a form</param-value>
</init-param>
</servlet>
..........
<servlet-mapping>
<servlet-name>JSPlstValues</servlet-name>
<url-pattern>/jspvalues</url-pattern>
</servlet-mapping>
<servlet-mapping>
........
</web-app>
The JSP page listvaleurs2.jsp is located in the root directory of the liste application and is associated with the JSP servlet name JSPlstValeurs (servlet-name), which is itself associated with the alias /jspvaleurs (servlet-mapping). Thus, our JSP page will be accessible via the URL http://localhost:8080/liste/jspvaleurs.
The original JSP page listvaleurs.jsp is renamed to listvaleurs2.jsp and retrieves its four initialization parameters in the jspInit() method:
<%!
// global application variables
// page title
private String title=null;
// database of list values
private String DSNValues = null;
private String admDbValues = null;
private String dbPassword = null;
// list values
private String[] values = null;
// error message
private String errorMessage = null;
// Initialization of the JSP page - executed only once
public void jspInit(){
// retrieve the servlet's initialization parameters
ServletConfig config = getServletConfig();
title = config.getInitParameter("JSPtitle");
ServletContext context = getServletContext();
DSNValues = context.getInitParameter("DSNValues");
admDbValues = context.getInitParameter("admDbValues");
mdpDbValues = context.getInitParameter("mdpDbValues");
//Have all parameters been retrieved?
if(title == null || DSNValues == null || admDbValues == null
|| mdpDbValues == null) {
errorMessage = "Incorrect configuration";
return;
}
// populates the values array from an ODBC database
// with DSN name: DSNvalues
..............
The JSP page retrieves its initialization parameters in the same way as servlets. The previous file is saved in the root directory of the "liste" web application:

The Tomcat server is restarted to force it to reload the application’s new web.xml configuration file. You can then request the URL http://localhost:8080/liste/jspvaleurs:

3.3.7. Servlet/JSP Collaboration Within a Web Application
When a client makes a request to a web server, the response can be generated by multiple servlets and JSP pages. Until now, the response had been generated by a single servlet or JSP page. We have seen that the JSP page provides better readability of the generated HTML document structure. However, it also generally contains a lot of Java code. We can improve this by placing
- the Java code that does not generate the HTML code of the response into one or more servlets
- in JSP pages, the code for generating the various HTML documents sent in response to the client
This should help improve the separation of Java code and HTML code. We will apply this new structure to our list application: a Java servlet named lstValeurs4 will be responsible for reading the values from the database at startup and then processing client requests at . Depending on the result of this analysis, the client’s request will be directed to an error page (erreur.jsp) or to the page displaying the list of numbers (liste.jsp). The list application will therefore consist of a servlet and two JSP pages.
How can a servlet pass the request it received from a client to another servlet or to a JSP page? We will use the following methods:
method of the ServletContext class that returns a RequestDispatcher object. The url parameter is the name of the URL to which we want to forward the client’s request. This request forwarding can only occur within the same application. Therefore, the url parameter is a path relative to the web directory structure of that application. | |
A method of the RequestDispatcher interface that forwards the client’s request and the response object—which must be used to construct the response—to the previous URL. | |
When a servlet or JSP page passes a request to another servlet or JSP page, it generally needs to pass along information other than just the client’s request—information derived from its own processing of the request. The setAttribute method of the ServletRequest class allows you to add attributes to the client’s request object in a format resembling a dictionary of (attribute, value) pairs, where attribute is the name of the attribute and value is any object representing its value. | |
allows you to retrieve the values of a request’s attributes. This method will be used by the servlet or JSP page to which a request has been forwarded to obtain the information added to it. |
The servlet responsible for processing the form will be configured as follows in the web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>DSNValues</param-name>
<param-value>odbc-values</param-value>
</context-param>
<context-param>
<param-name>admDbValues</param-name>
<param-value>admDbValues</param-value>
</context-param>
<context-param>
<param-name>mdpDbValues</param-name>
<param-value>mdpDbValues</param-value>
</context-param>
............
<servlet>
<servlet-name>lstValues4</servlet-name>
<servlet-class>gener7</servlet-class>
<init-param>
<param-name>title</param-name>
<param-value>Form generation</param-value>
</init-param>
<init-param>
<param-name>JSError</param-name>
<param-value>/error.jsp</param-value>
</init-param>
<init-param>
<param-name>JSPlist</param-name>
<param-value>/list.jsp</param-value>
</init-param>
<init-param>
<param-name>URLservlet</param-name>
<param-value>/list/values4</param-value>
</init-param>
</servlet>
...........
<servlet-mapping>
<servlet-name>lstValues4</servlet-name>
<url-pattern>/values4</url-pattern>
</servlet-mapping>
.......
</web-app>
The lstValeurs4 servlet will have four initialization parameters specific to it:
the title of the HTML document to be generated | |
the URL of the error JSP page | |
The URL of the JSP page displaying the list of numbers | |
The URL associated with the action attribute of the form displayed by the JSPlist page. This URL will be that of the lstValeurs4 servlet |
The servlet will have the alias /valeurs4 (servlet-mapping) and will therefore be accessible via the URL http://localhost:8080/liste/valeurs4. It is linked to the class file gener7.java, whose complete source code is as follows:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.*;
public class gener7 extends HttpServlet{
// page title
private String title = null;
// database of list values
private String DSNValues = null;
private String admDbValues = null;
private String dbPassword = null;
// the JSP display pages
private String JSPerror = null;
private String JSPList = null;
// the servlet URL
private String servletURL = null;
// list values
private String[] values = null;
// error message
private String errorMessage = null;
// -----------------------------------------------------------------
// GET
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// Add "msgErreur" and "title" to the request attributes
request.setAttribute("errorMessage", errorMessage);
request.setAttribute("title", title);
request.setAttribute("servletURL", servletURL);
// Was there an error loading the servlet?
if(errorMessage != null){
// we pass control to an error JSP page
getServletContext().getRequestDispatcher(JSPerreur).forward(request, response);
// end
return;
}
// no error occurred
// we put the list of values in the request attributes
request.setAttribute("values", values);
// retrieve the user's selection, if any
String choice = request.getParameter("cmbValues");
if (choice == null) choice = "";
request.setAttribute("choice", choice);
// forward to the JSP page displaying the list
getServletContext().getRequestDispatcher(JSPliste).forward(request, response);
// end
return;
}//GET
// -----------------------------------------------------------------
// POST
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
// redirect to GET
doGet(request, response);
}//POST
// -----------------------------------------------------------------
// Initialize the servlet
public void init(){
// retrieve the servlet's initialization parameters
ServletConfig config = getServletConfig();
title = config.getInitParameter("title");
JSError = config.getInitParameter("JSError");
JSPlist = config.getInitParameter("JSPlist");
URLservlet = config.getInitParameter("URLservlet");
ServletContext context = getServletContext();
DSNValues = context.getInitParameter("DSNValues");
admDbValues = context.getInitParameter("admDbValues");
mdpDbValues = context.getInitParameter("mdpDbValues");
//Have all parameters been retrieved?
if(title == null || DSNValues == null || admDbValues == null
|| mdpDbValues==null || JSError==null || JSPList==null || URLServlet==null){
errorMessage = "Incorrect configuration";
return;
}
// populates the values array from an ODBC database
// with DSN name: DSNvalues
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try{
// Connect to the ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
connection = DriverManager.getConnection("jdbc:odbc:" + DSNValues, admDbValues, mdpDbValues);
// Statement object
st = connection.createStatement();
// execute SELECT query to retrieve the values
rs = st.executeQuery("select value from Tvalues");
// The values are retrieved and placed in a dynamic array
ArrayList lstValues = new ArrayList();
while(rs.next()){
// the value is added to the list
lstValues.add(rs.getString("value"));
}//while
// convert list to array
values = new String[lstValues.size()];
for (int i = 0; i < lstValues.size(); i++) {
values[i] = (String)lstValues.get(i);
}
} catch (Exception ex) {
// problem
errorMessage = ex.getMessage();
}finally{
try{rs.close();}catch(Exception ex){}
try{st.close();}catch(Exception ex){}
try{connection.close();}catch(Exception ex){}
}//try
}//init
}//class
The new feature in this class is that it forwards the client request to the JSPerreur page in case of an error, and to the JSPliste page otherwise. The class does not generate the response itself. The JSPerreur and JSPliste JSP pages handle this. Previously, the servlet added attributes (setAttribute) to the client request:
- an error message msgError in case of an error for the JSPerreur page
- the values (values) to display, the value selected (choice) by the user, the form title (title), and the URL (URLservlet) of the form’s action attribute for the JSPlist page
This class is compiled and placed in the application's classes:

The JSP page displaying an error message is configured as follows:
<servlet>
<servlet-name>JSPerreur</servlet-name>
<jsp-file>/error.jsp</jsp-file>
<init-param>
<param-name>mainServlet</param-name>
<param-value>/values4</param-value>
</init-param>
</servlet>
.........
<servlet-mapping>
<servlet-name>JSError</servlet-name>
<url-pattern>/JSError</url-pattern>
</servlet-mapping>
The JSP file associated with the error page is called error.jsp and is located in the application root:

It has the alias /JSPerreur, which makes it accessible via the URL http://localhost:8080/liste/JSPerreur. It has an initialization parameter called mainServlet, whose value is the alias of the main servlet described above. Note that this alias is relative to the root of the liste application; otherwise, it would be /liste/valeurs4. The code for the erreur.jsp page is as follows:
<%
// code from _jspService
// retrieve the mainServlet initialization parameter
String servletListValues = config.getInitParameter("mainServlet");
// retrieve the msgErreur attribute
String errorMessage = (String) request.getAttribute("errorMessage");
// Is the attribute valid?
if(errorMessage != null){
%>
<!-- HTML code -->
<html>
<head>
<title>Error</title>
</head>
<body>
<h3>Application unavailable (<%= msgError %>)</h3>
</body>
</html>
<%
} else { // invalid msgError attribute - return to main servlet
%>
<jsp:forward page="<%= servletListValeurs %>" />
<%
}
%>
This page should normally be called by the previous servlet, which should pass it the msgError attribute. However, there is nothing preventing you from calling it directly if you know its URL. Also, if you find that the msgError attribute is missing, you pass the request to the main servlet. Here, we use a tag specific to JSP pages, whose syntax is:
where URL is the URL of the servlet to which the client’s request is forwarded. If the msgError attribute is present, the error page is displayed.
The JSP page displaying the list of numbers is configured as follows:
<servlet>
<servlet-name>JSPliste</servlet-name>
<jsp-file>/list.jsp</jsp-file>
<init-param>
<param-name>mainServlet</param-name>
<param-value>/values4</param-value>
</init-param>
.........
<servlet-mapping>
<servlet-name>JSPlist</servlet-name>
<url-pattern>/JSPlist</url-pattern>
</servlet-mapping>
The JSP file associated with the error page is called liste.jsp and is located in the application root:

The servlet has the alias /JSPliste, which makes it accessible via the URL http://localhost:8080/liste/JSPliste. It has an initialization parameter called mainServlet, whose value is the alias of the main servlet. The code for the liste.jsp page is as follows:
<%-- page displaying the list of values --%>
<%
// jspService code
// retrieve the initialization parameter
String servletListValues = config.getInitParameter("mainServlet");
// retrieve the request attributes from the main servlet
String title = (String) request.getAttribute("title");
String[] values = (String[]) request.getAttribute("values");
String choice = (String) request.getAttribute("choice");
String URLservlet = (String) request.getAttribute("URLservlet");
// Are the attributes valid?
if(title==null || values==null || choice==null){
// there is an invalid attribute - we pass control to the servlet
%>
<jsp:forward page="<%= servletListValeurs %>" />
<%
}//if
%>
<%-- HTML code --%>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h3>Select a value</h3>
<form method="POST" action="<%= URLservlet %>">
<select name="cmbValeurs">
<%
// dynamically display the values
String selected="";
for (int i=0;i<values.length;i++){
if(values[i].equals(choice)) selected="selected"; else selected="";
out.println("<option "+selected+">"+values[i]+"</option>");
}//for
%>
</select>
<input type="submit" value="Submit">
</form>
<%
// Was a value selected?
if(!choice.equals("")){
// display the user's choice
%>
<hr>You have chosen the number<h2><%= choice %></h2>
<%
}//if
%>
</body>
</html>
This page behaves like the error.jsp page. It should normally be called by the /list/values4 servlet and receive the title, values, and choice attributes. If any of these parameters is missing, control is passed to the URLservlet servlet (/liste/valeurs4). If all parameters are present, the list of numbers is displayed along with the number chosen by the user, if any.
If you request the URL of the main servlet, you get the following result:

with the following source code (View/Source):
<html>
<head>
<title>Generating a form</title>
</head>
<body>
<h3>Select a value</h3>
<form method="POST" action="/list/values4">
<select name="cmbValeurs">
<option >0</option>
<option >1</option>
<option >2</option>
<option >3</option>
<option >4</option>
<option >6</option>
<option >5</option>
<option >7</option>
<option >8</option>
<option >9</option>
</select>
<input type="submit" value="Submit">
</form>
</body>
</html>
This HTML document was generated by the JSP page liste.jsp. We can see that the title, values, and URLservlet attributes were successfully retrieved.
To conclude on the collaboration between servlets and JSP pages, we observe that the JSP pages here are very short and lack Java code that does not directly contribute to creating the HTML response. The structure of the generated documents is thus more visible.
3.4. Lifecycle of Servlets and JSP Pages
3.4.1. The Lifecycle
Here we focus on the servlet lifecycle. The lifecycle of JSP pages follows from this. Consider a servlet being called for the first time. A class instance is then created by the web server and loaded into memory. It will then serve the request. Once this is done, the servlet is not unloaded from memory. It remains there to serve other requests in order to optimize server response times. It will be unloaded when a sufficiently long period of time has passed without it serving any new requests. This time is generally configurable within the web server.
While in memory, the servlet can handle multiple requests simultaneously. The web server creates one thread per request, all of which use the same servlet instance:
![]() |
All of the above threads share the variables of the servlet instance. It may be necessary to synchronize the threads to prevent corruption of the servlet’s data. We will return to this later.
When a servlet is loaded, a specific method of the servlet is executed:
For a JSP page, it is the method
public void jspInit(){
}
that is executed. Here is an example of a JSP page using the jspInit method:
<html>
<head>
<title>Synchronized counter</title>
</head>
<body>
Counter= <%= getCounter() %>
</body>
</html>
<%!
// global variables and methods of the JSP page
// instance variable
int counter;
// method to increment the counter
public int getCounter(){
// increment the counter
int myCounter = counter;
myCounter++;
counter = myCounter;
// return it
return counter;
}
// the method executed when the page first loads
public void jspInit(){
// initialize counter
counter = 100;
}
%>
The previous JSP page initializes a counter to 100 in jspInit. Any subsequent request to the servlet increments and then displays the value of this counter:
The first time:

The second time:

As can be seen above, between the two requests, the servlet was not unloaded; otherwise, the counter would have been 101 during the second request. When the servlet is unloaded, the method
is executed if it exists. For JSP pages, it is the method
public void jspDestroy(){
}
In these methods, you can, for example, close database connections that were opened in the corresponding init methods.
3.4.2. Synchronizing Requests to a Servlet
Let’s return to the previous JSP page that increments a counter and returns it to the web client. Suppose there are two simultaneous requests. Two threads are then created to execute them; these threads will use the same servlet instance, and thus the same counter. Recall the code that increments the counter:
public int getCounter(){
// increment the counter
int myCounter = counter;
myCounter++;
counter = myCounter;
// return it
return counter;
}
The counter increment was intentionally written in a clumsy manner. Suppose the execution of the two threads proceeds as follows:
![]() |
- At time T1, thread TH1 is executed. It reads the counter (=145) from myCounter, then it is interrupted and loses the processor. It therefore did not have time to increment myCounter and copy the new value to counter.
- At time T2, thread TH2 is executed. It reads the counter (=145) from myCounter, then it is interrupted and loses the processor. Note that the two threads have different myCounter variables. They share only instance variables, those that are global to the methods.
- At time T3, thread TH1 regains control and finishes. It therefore returns 146 to its client.
- At time T4, thread TH2 regains control and finishes. It also returns 146 to its client, when it should have returned 147.
This is a thread synchronization issue. When TH1 wants to increment the counter, it must prevent any other thread from doing so as well. To highlight this problem, we rewrite the JSP page as follows:
<html>
<head>
<title>Synchronized counter</title>
</head>
<body>
Counter= <%= getCounter() %>
</body>
</html>
<%!
// global variables and methods of the JSP page
// instance variable
int counter;
// method to increment the counter
public int getCounter(){
// read the counter
int myCounter = counter;
// wait 10 seconds
try{
Thread.sleep(10000);
} catch (Exception ignored) {}
// increment the counter
counter = myCounter + 1;
// return it
return counter;
}
// the method executed when the page first loads
public void jspInit(){
// initialize counter
counter = 100;
}
%>
Here, we have forced the thread to stop 10 seconds after reading the counter. It should therefore release the CPU, allowing another thread to read a counter that has not been incremented. When we make requests with a browser, we don’t notice any difference other than the 10-second wait before getting the result.

Now, if we open two browser windows and make two requests close enough together in time:


We get the same counter value. We can better highlight the problem with a programmed client rather than a manual one like the browser. Here is a Perl client that is called as follows:
*program URL N*
where
URL is the URL of the counting servlet
N is the number of requests to make to this servlet
Here are the results obtained for 5 requests, which clearly demonstrate the problem of poor thread synchronization: they all return the same counter value.
DOS>java clientCompterJSP http://localhost:8080/examples/jsp/perso/compteur/compteur2.jsp 5
Counter=121
Counter=121
Counter=121
Counter=121
Counter=121
The Java client code is as follows.
import java.net.*;
import java.util.regex.*;
import java.io.*;
public class JSPCounterClient {
public static void main(String[] params){
// data
String syntax = "Syntax: pg URL nbCalls";
// parameter validation
if(params.length!=2){
System.err.println(syntax);
System.exit(1);
}//if
// URL
URL urlCounter = null;
try{
urlCounter = new URL(params[0]);
String query = urlCounter.getQuery();
if (query != null) throw new Exception();
} catch (Exception ex) {
System.err.println(syntax);
System.err.println("Invalid URL [" + params[0] + "");
System.exit(2);
}//try-catch
// number of calls
int numCalls = 0;
try{
calls = Integer.parseInt(params[1]);
if(nbCalls <= 0) throw new Exception();
} catch (Exception ex) {
System.err.println("Syntax error");
System.err.println("Invalid number of calls [" + params[1] + "");
System.exit(3);
}//try-catch
// the parameters are correct - we can connect to the URL
try{
getCounters(counterURL, countOfCalls);
} catch (Exception ex) {
System.err.println(syntax);
System.err.println("The following error occurred: " + ex.getMessage());
System.exit(4);
}//try-catch
}//main
private static void getCounters (URL counterURL, int countOfCalls)
throws Exception {
// makes nbAppels calls to the URL urlCompteur
// displays the counter value returned by the web server each time
// Retrieve the information needed to connect to the tax server from urlCompteur
String path = urlCompteur.getPath();
if (path.equals("")) path = "/";
String host = urlCompteur.getHost();
int port = urlCompteur.getPort();
if (port == -1) port = urlCounter.getDefaultPort();
// make the calls to the URL
Socket[] clients = new Socket[nbCalls];
for (int i = 0; i < nbAppels; i++) {
// connect to the server
clients[i] = new Socket(host, port);
// create a write stream to the server
PrintWriter OUT = new PrintWriter(clients[i].getOutputStream(), true);
// request the URL - send HTTP headers
OUT.println("GET " + path + " HTTP/1.1");
OUT.println("Host: " + host + ":" + port);
OUT.println("Connection: close");
OUT.println("");
}//for
// local data
String response = null; // server response
// the pattern searched for in the server's HTML response
Pattern counterPattern = Pattern.compile("^\\s*Counter= (\\d+)");
// the pattern for a valid response
Pattern OKResponse = Pattern.compile("^.*? 200 OK");
// the result of the pattern match
Matcher result = null;
for(int i=0;i<nbCalls;i++){
// Each client reads the response sent by the server
// create the TCP client's input/output streams
BufferedReader IN = new BufferedReader(new InputStreamReader(clients[i].getInputStream()));
// read the first line of the response
response = IN.readLine();
// compare the HTTP line to the correct response template
result = responseOK.matcher(response);
if(!result.find()){
// there is a URL issue
throw new Exception("Client # " + i + " - The server responded: Unknown URL [" + urlCounter + "]");
}//if
// Read the response until the end of the headers
while((response = IN.readLine()) != null && response.equals("") === false) {
}//while
// The HTTP headers are finished—now we move on to the HTML code
// to retrieve the counter value
boolean counterFound = false;
while((response = IN.readLine()) != null){
// compare the line to the counter template
if(!counterFound){
result = counterPattern.matcher(response);
if(result.find()){
// meter found
System.out.println("Counter=" + result.group(1));
counterFound = true;
}//if
}//if
}//while
// done
clients[i].close();
}//for
}//getCounters
}//class
Let's explain the previous code:
- The program accepts two parameters:
- the URL of the JSP page for the counter
- the number of clients to create for this URL
- The program therefore begins by verifying the validity of the parameters: that there are indeed two, that the first resembles a URL syntactically, and that the second is an integer greater than 0. To verify that the URL is syntactically correct, we use the URL class and its URL(String) constructor, which creates a URL object from a string such as http://istia.univ-angers.fr. An exception is thrown if the string is not a syntactically valid URL. This allows us to verify the validity of the first parameter.
- Once the parameters have been verified, control is passed to the getCompteurs procedure. This procedure will create nbAppels clients, all of which will connect simultaneously (or nearly so) to the URL urlCompteur.
- The port and the machine to which the clients must connect are derived from the URL urlCompteur: [URL].getHost() returns the machine name, and [URL].getPort() returns the port.
- A first loop allows each client:
- connect to the web server
- to request the URL urlCompteur
In this loop, the client does not wait for the server’s response. This is because we want the server to receive nearly simultaneous requests.
- A second loop allows each client to receive and process the response sent by the server. The processing involves finding the line in the response that contains the counter value and displaying it.
To resolve the issue highlighted earlier (the same counter being sent to all five clients), we need to synchronize the threads of the counting service on a single object before entering the critical section for reading and updating the counter. The new JSP page is as follows:
<html>
<head>
<title>Synchronized counter</title>
</head>
<body>
Counter= <%= getCounter() %>
</body>
</html>
<%!
// global variables and methods of the JSP page
// instance variables
int counter;
Object lock = new Object();
// method to increment the counter
public int getCounter(){
// synchronize the critical section
synchronized(lock){
// read the counter
int myCounter = counter;
// wait 10 seconds
try{
Thread.sleep(10000);
} catch (Exception ignored) {}
// increment the counter
counter = myCounter + 1;
}//synchronized
// return it
return counter;
}//getCounter
// the method executed when the page first loads
public void jspInit(){
// initialize counter
counter = 100;
}
%>
When executed, the following results are obtained:
dos>c:\perl\bin\perl.exe client2.pl http://localhost:8080/examples/jsp/perso/compteur/compteur3.jsp 5
Counter= 104
Counter= 106
Counter= 105
Counter= 107
Counter= 108
The documentation indicates that the web server may sometimes create multiple instances of the same servlet. In this case, the previous synchronization no longer works because the lock variable is local to a single instance and is therefore not known to the other instances. The same applies to the counter variable. To make them global to all instances, we write:
// class variable
static int counter;
static Object lock = new Object();
The rest of the code remains unchanged.





