Harri Laine (4.2.2007)
The programming technique originally demonstrated for the realisation of Web-applications was the CGI technique (common gateway interface). In CGI the requested program is run in the server as a separate process. Programs may be written in any programming language, also in Java. The best performance is achieved with compiled programs. However, in practice, interpreted languages and just-in- time compiled languages have been most popular. The best known example is Perl. Their performance is slowed down by the loading of the processing environment. A lot of other things than just the program code must be loaded into the memory when setting up a process. This is also true forthe interpreted Java language. Loading and starting of the Java interpreter are quite heavy operations. The servlet technique was introduced as a solution to manage the loading problem and to run Java programs efficiently. In this technique the basic idea is that the Java run time environment is started as an ongoing process. The programs (servlets) will be loaded when they are called for the first time. They stay loaded into the run time environment and thus may be started quickly when a new service request arrives. The ongoing run time environment also makes it possible to store information in the main memory and thus to transfer it more quickly between separate server programs. The idea of an ongoing environment process was presented in connection with Java but has later spread so that nowadays many web-server products are able to keep alive Perl or PHP interpreters and load the program code only once.
Servlets are a Java-based basic technique for the realisation of web-applications. For example, the JSP technique utilises servlets so that the JSP pages will be compiled as servlets for execution. In JSP pages the role of the HTML and the software code has been reversed as compared to standard servlets. When using servlets an HTML page is produced with the Java output statements. In JSP the static HTML comprises the basis for the page where Java code may be included to produce the dynamic parts of the page.
A lot of information about servlets may be found in
The following articles are good for introduction:
- Stefan Zeiger : Servlet Essentials
- Hans Bergsten: An Introduction to Java Servlets
- Mark Andrews: STORY OF A SERVLET: AN INSTANT TUTORIAL
- MageLang Institute: Fundamentals of JavaTM Servlets Preface
- Dynamic Information Systems Corporation: Developing JDBC Servlet Applications
A servlet consists of a primary Java class and any number of assisting classes. It is typically called by the name of the primary class but it may be renamed in the deployment description. Assisting classes may serve many servlets.
A run time environment is needed to host the servlets. This environment is attached to a web server and to a java run time environment. A servlet will be loaded into the environment when it is called for the first time. It may be loaded also as soon as the environment is started or when the program code has been changed. This behaviour is, however, environment specific. Servlet classes, assisting classes, class libraries, static HTML pages and other files used in the application should be deployed so that the environment is able to locate and load them.
Servlets need an environment to host them. The are many such environments (application server software) on the market. The Computer Science department uses the Apache Tomcat server. The server is installed on the users.cs.helsinki.fi computer.
To use Tomcat you must first assign values for a few environment variables and specify the port that the server uses for requests. The folder structure needed for deploying the application must also be constructed. The ordering script wanna-tomcat takes care of most of these initialization tasks. This script needs to be run only once. It
Activates the start command start-tomcat Activate the stop command stop tomcat Creates the file .tomcat in which the necessary environment variables and the default running time of the server are specified Creates a deployment directory structure for application tsoha (a copy of the deployment structure used in the examples of this material).
The Tomcat server is started with the command start-tomcat and turned off with command stop-tomcat. Before these commands can be used, the environment should have been ordered using the command wanna-tomcat. When testing the application, it will be unnecessary to leave the server running if you don’t use it.
The files and programs of the application must be deployed according to the Tomcat specifications. The script wanna-tomcat creates the basic directrory structure. An examle loading script wanna tsoha completes it with an example application.Let us call the folder *user*/tomcat/webapps/ the TOMCAT folder (*user* is your username).
Let APPLICATION be the root directory of the application. Its path is *user*/tomcat/webapps/*application_name*. The ordering script (wanna-tomcat) specifies the initial part of the path. You specify the name of the application yourself. Our example applications is called 'tsoha'. Tomcat is able to locate the components of the application if they are deployed as follows:
Folder APPLICATION should contain the static HTML pages, style sheets, images, and JavaScripts files. You may, of course, use subfolders. For example, the images could be placed in the folder APPLICATION/images/ .
File APPLICATION/WEB-INF/web.xml is the deployment descriptor of the application. This file specifies the initialization parameters. It assigns names for the servlets. Each servlet must be identified and their URLs be specified in the web.xml file.
Folder APPLICATION/WEB-INF/classes/ should contain the servlet classes as well as the assisting classes (the compiled *.class files). If there are any local packages, they should be deployed as subfolders. For example, the classes of the package 'box’ should be stored in the folder APPLICATION/WEB-INF/classes/box/
It is recommended that the source code be kept separate from the deployment structure. The location of the servlet source code is not significant. The compiled *.class files must be copied to the deployment folder for the execution.
In our example environment source codes are kept in folder APPLICATION/src/
Environment variable CLASSPATH has an important role in Java. All the libraries and external classes must be located in folders that are listed in the CLASSPATH. This is true for both compilation and execution. Database driver is an exception. Its path need not be included in the compile CLASSPATH. You may use the command setup tomcat to modify the CLASSPATH to include the libraries that belong to the Tomcat installation. If there are local packages and libraries in the APPLICATION/WEB-INF/lib folder these must be included in the compile CLASSPATH. Ant software can be used to control the compilation and deployment. There is a separate instruction on the use of ant.
Servlet URLs are constructed as defined in files *application_name*.xml and web.xml . By default the URL is of form http://t-*user*.users.cs.helsinki.fi/*application_name*/servlet/*Servlet_name*
Static pages located in folder APPLICATION are referred to with URLs of form
http://t-*user*.users.cs.helsinki.fi/*application_name*/*page_name.html*For example, http://t-laine.users.cs.helsinki.fi/tsoha/servlet/PgTesti identifies the servlet PgTesti that belongs to the example application tsoha.
A servlet consists of one Java class which inherits the library class HttpServlet. The class can utilise other Java classes. The actual service is provided by the service methods doPost and doGet. Which one of the methods is started to take care of the service request depends on the call. If the call is given through an HTML link or an HTML-form is defined to be handled using method 'get', then the method doGet will provide the service, otherwise doPost is the service provider. In several cases it may be a good idea to program both methods to provide the same service. The service can then be requested both from a link and as a form handler. If you want to be sure that request parameters are not included in the URL and that they are not visible in the address field of the browser, you should use a form haldler and the method 'post' in issuing the request.
When the servlet engine receives a request for the servlet it starts the service as a new thread. There may be parallel threads running the same code. The service methods must be coded as thread safe. In other words, it must be possible to run them in parallel without them messing up each other's data. This is achieved the simplest by using only the local variables and objects in the service methods.
When information about the session state is needed this should be transmitted through the web pages and the browser. Hidden fields and cookies may be used for this. If class or object variables of the servlet class are used, their assignment operations must be protected against parallel use.
The lifespan of a servlet consists of the initialization, the service stage and the removal.
Initialization of a servlet takes place after the servlet code has been loaded into the servlet engine. During the initialization a single object of the class is created and its init method is run. Tasks that may be done in the init method may include setting up the class variables and loading the database driver. The init method is executed only once.
The service stage consists of repeated executions of the doGet and doPost methods. They carry out their service as threads (a kind of lightweight process). Each call is taken care of as a separate thread. The values of the variables within the method (the state of the method) are lost when the execution of the method ends.
Removal takes place when the servlet is removed from the engine. This happens, for example, when the server is closed. If there are any clean-up operations to be done, they should be coded as the destroy method.
The servlet interface has been defined in J2EE specifications as javax.servlet and javax.servlet.http packages. These must be included in the program with import. In addition, a library to implement the interfaces must be available and included in the CLASSPATH. The implementation library servlet.jar that is included in the Tomcat installation ($CATALINA_HOME/common /lib/servlet.jar). This package must be included also in the compile CLASSPATH.
All servlet classes have to inherit the class HttpServlet. This specifies the signatures of the service methods doGet and doPost There are also some other service methods, for example, for file upload.
public void doPost( HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ...}All service methods have two parameters HttpServletRequest and HttpServletResponse objects. The HttpServletRequest object offers services for handling of the request parameters. The HttpServletResponse object delivers the result of the service to the web browser.
Preliminary actions typically include:
- reconstruction of the state of the session
- preparations for producing output
- extracting the parameters which were provided in the request, and
- establishing the database connection
Reconstruction of the state of the session
HttpSession objects provide a convenient way to store the state of the session. Any objects may be stored in a HttpSession object as values of its attributes, the names of which you assign yourself. The getSession method of the HttpServletRequest object either creates a new HttpSession object or locates the one previously created for the same session. The servlet engine takes care of sending the session identifier as a cookie to the browser and picking up the identifier from the cookie received with the request. There are also other techniques for transmitting the session identifiers. HttpSession object has methods setAttribute and getAttribute for storing and locating the stored objects. The reconstruction of the state of the session must be made very first before any results are written.
Cookies and hidden form fields may be used instead of the HttpSession object for transmitting information between servlets. State information may also be stored in the database.
Preparations for output
Some preliminary actions must be carried out before any output may be produced. They include
- definition of the type of the result, and
- selection of the output ‘device’
The following code shows one way of doing this:
resp.setContentType("text/html"); PrintWriter pw = res.getWriter();In addition, one might construct web page title information at this phase.. If many servlets share the same title information, one could define a separate class to provide these and other common parts of the pages. Another way is to define a new class in the class hierarchy, between the HttpServlet and your own servlet classes.
Extracting the request parameter values
From the callers point of view request parameters for servlets are similar to the request parameters when using CGI. The service method may access the parameters by asking the HttpServletRequest object for the parameter values for a given parameter name:
String value = req.getParameter("parameter_name");
The value is provided as a String object. If the value is something else, it should be transformed. If no value was provided in the request for the given name, the result is a null. If the same paramerer name appears many times in the parameter set, the values of the parameter should be extracted using method getParameterValues, which produces a String array.
Establishing a database connection
When the servlet uses a database, the forming of the database connection is also a typical preliminary action. If a connection pool is used, a connection is requested from the pool. However, study projects are not allowed to use pools of open connections.
To create a connection a database-specific driver must be loaded first. This driver provides a method for creating connections. It might be useful to define a class to take care of database connections. This class may be between HttpServlet and your own servlet classes in the class hierarchy, as is the case with our example class DatabaseServlet. This class requires that specifications for the connections are given in a separate configuration file (an example of a configuration file). The address of the configuration file is given in the web.xml file (here is an example of how to define the address). The database connections rely on a database driver. A driver for our Oracle database is /opt/oracle/jdbc/lib/ojdbc14.jar. and it should be copied in APPLICATION/WEB INF/lib/ folder.
N.B.: Our setup command for oracle setup oracle includes the above-mentioned driver in the CLASSPATH. If this command has been issued in the session before the start-tomcat command , the driver will also be included in the runtime CLASSPATH. If tomcat is started this way, APPLICATION/WEB INF/lib/ should not contain a copy of the driver. If you copy the driver, you should not issue the setup oracle command before starting Tomcat.
A connection to a postgerSQL database running in db.cs.helsinki.fi under user account username is created as:
Connection conn = createConnection("org.postgresql.Driver", "jdbc:postgresql://localhost/username", username,password);Here, portnumber is the one provided by wanna-postgres script and username is the account name.
The driver for PostgreSQL may be found in /opt/jdbc/jdbc7.0-1.2.jar.
What is in the body of the service depends on what the service method is to do. Even the most simple service constructs a new web page in HTML format. A text is written on the page by using the printing device (above PrintWriter ) attached to the HttpServletResponse object. One design pattern is to construct a form with the same servlet that handles the form after it has been filled.
A Statement or a PreparedStatement object is created to carry out most of the database operations. CallableStatement objects can used for executing database procedures and functions. PreparedStetement and CallableStatement classes inherit the Statement class. Next, all the objects of these classes are called statement objects. The statement objects are created using methods of the Connection object They must always be closed before exiting the program. Nearly all the database operations can cause a SQLException exception, which must be caught in the program. It is not necessary to embed database processing directly in the code of service methods, a separate database interface class might be a good idea.
In the following example of the database loop:
Statement stm=null; ResultSet rs=null; String kysely= "select nimi from opiskelija where hetu like \'0101%\' order by nimi"; // born 1st of january try { stm= conn.createStatement(); rs= stm.executeQuery(kysely); while (rs.next()) { pw.println(rs.getString("nimi")+"<br>"); } } catch (SQLException e) { databaseError(e.getErrorCode(), e.getMessage(), pw); // databaseError is a private error method } // finally assures that close is done finally { try { if (rs!=null) rs.close(); if (stm!=null) stm.close(); } catch (SQLException ee) {} }
As a last step of the service method the database resources must be freed and an HTML page must be ended. The freeing of database resources includes closing ResultSets and Statements by the calling the close methods of these objects. In the JDBC manual it is stated that this is not usually necessary because the Java garbage collector takes care of the matter. However, some database servers (also Oracle) require that the resources are explicitly freed by calling the close methods.
The example application is deployed as follows:
~laine/tomcat/webapps |
|
tsoha.xml ( the browser may have its own style for xml, save it for examination) |
|
~laine/tomcat/webapps/tsoha |
|
|
|
|
|
|
|
testing.gif -an image used in servlet only |
|
~laine/tomcat/webbapps/tsoha/WEB-INF |
|
web.xml (the browser may have its own style for xml, save it for examinationi) |
|
~laine/tomcat/webapps/tsoha/WEB-INF/classes |
|
ServletTest.class SessionTest.class PgTest.class |
|
~laine/tomcat/webapps/tsoha/WEB-INF/lib |
|
ojdbc14..jar - Oracle JDBC-driver |
|
~laine/tomcat/webapps/tsoha/src |
|
SessionTest.java (ServletTest, modified to include a simple test for sessions, counts the number of requests served within this session) |