Objective: Write a servlet to access the database.
There are not many useful tutorials on the web that explain servlets in a clear manner because at the rate at which most tools like Eclipse and NetBeans move, tutorials go quickly out of date. A link to one as recent as March 2008 is at the bottom of this page. Most of the information is contained in specifications, which give too much information, and written books, which require money. I will attempt to put down in a clear manner servlets and the instructions to build a simple servlet using the environment we have so far developed.
It is important to note here at the beginning of this subject that there are a myriad of ways to develop and deploy a web based servlet application. There are literally dozens of tools, IDEs, plugins, etc. that help the developer create and publish these kinds of applications. The method used here is merely a suggested one using the most popular tools to do so.
From here we will introduce servlets, their basic life cycle and interface and demonstrate the simple HelloWorld servlet code. We will walk you through the installation and configuration of one of the most popular servlet containers, Tomcat. Once Tomcat is running we will discuss how servlets are deployed in Tomcat using Web application Archive (WAR) files and discuss the basics of creating a WAR file with its web.xml deployment descriptor.
We will then walk you through building a simple WAR file using Eclipse and Maven. At this point, you will be able to implement the subject assignment: the DVD Catalog servlet.
Servlets generate dynamically HTML files in response to a HTTP request, most often sent by a web browser. Servlets (the actual code you write) execute not in their own context but in the context of a "servlet container." The container is responsible for grokking the HTTP request, parsing the incoming headers and data, and providing objects that your servlet uses to serve the request. Using these objects, which we discuss below, your code generates the HTML that the servlet container puts back into a HTTP response that is sent back to the browser.
All servlets implment the javax.servlet.Servlet interface. From this interface a servlet must implement the methods to serve the HTTP request. The methods that a servlet must provide are:
The basic life-cycle of a servlet begins when the servlet container first encounters a HTTP request that the servlet is meant to service. Before the request is given to the servlet, its code is loaded into the container’s context and the init method is called to allow the servlet to initialize its resources. After the init method is called the service method is called for every HTTP request received by the container destined for the servlet.
It is important to keep in mind that if the servlet container is multi-threaded, there may be multiple threads calling the service method at the same time. Thus, it is important to use proper thread synchronization in your servlet code to protect the servlet’s resources.
The servlet’s life-cycle will continue until the container calls the servlet’s destroy method. Until the destroy method is called, the servlet remains in memory and may or may not be serving HTTP requests. This is another important thing to consider in managing the servlet’s resources. (As they are held even if the servlet’s code is idle.)
The javax.servlet.http.HttpServlet provides a generic HTTP servlet for us to use. This class implements the service method of the generic Servlet interface and identifies the type of HTTP request. When your servlet inherits from HttpServlet, you must provide methods to handle the various types of HTTP requests:
The most common types of HTTP requests that our servlets will handle are Get and POST requests. You need not provide implementations for all of these methods: only the types of HTTP requests you want to handle. Thus, if you are only interested in handling Get requests, your servlet need only implement the doGetmethod. Additionally, if you want to handle both Get and POST requests and don’t distinguish the handling between the two, you can simply call doGet from the doPost method (or vice versa).
The doGet method has the following parameters:
void doGet( HttpServletRequest request, HttpServletResponse response ) ...
The request parameter represents the HTTP request packet and from which you canp obtain the HTTP header information, the query parameters and the POST data. To obtain the parameters intended as the input parameters to your servlet, the HttpServletRequest class provides the getParameter and getParameters methods. Thus, you need not parse the query and POST data your self, the request object will provide the information for you. The getParameters method is used when the parameter may contain multiple values. This is common with HTML forms and the SELECT tag.
The HttpServletResponse class provides methods to allow you to enter data into the HTTP response packet and, most importantly, provides a OutputStream (or PrintWriter) into which you will write the HTML that forms the response.
Thus, the HelloWorld servlet consists of the following code:
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class myServlet extends HttpServlet { protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>Hello World Servlet</title>"); out.println("</head>"); out.println("<body>"); out.println("Hello world from Provo!"); out.println("</body>"); out.println("</html>"); } }
The setContentType method is an example of how you modify the HTTP header information to be sent back in the response packet. As you can see, once the PrintWriter (or OutputStream) is obtained from the response object it is a simple matter of writing out the HTML tags and data to the stream.
For such a simple application, it is not necessary to provide the init and destroy methods. For our DVD Catalog application, the init method is where we could load our database driver and prepare such things a connection pool to our database.
There are many ways to deploy a web application in a servlet container. The most common is the standardized Web application Archive (WAR) file. A WAR file is simply a normal JAR file with a specific directory structure and a .war extension. The directory structure is:
/ - root of the archive; location of HTML, JSP, image files, etc. +- WEB-INF/ - directory for supporting files +- classes/ - directory for compiled servlets and other Java files +- lib/ - directory for library .jar files the application is dependent on +- web.xml - deployment descriptor
The deployment descriptor is a XML file that specifies to the servlet container the specifics of the application.
<web-app> <servlet> <servlet-name>hello</servlet-name> <servlet-class>myServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/MyHelloWorld</url-pattern> </servlet-mapping> </web-app>
Given this web.xml file in a .war file named myapp.war, this deployment descriptor indicates that the myServlet class will be called from the following URL:
http://localhost:8080/myapp/MyHelloWorld
The servlet tag associates a sevlet name by which the servelet is identified throughout the rest of the deployment descriptor. The servlet-name is the name, and the servlet class is the class (with package name, if required). The servlet-mapping tag associates the servlet with the path that the servlet container will use to access the servlet. The url-pattern is the name following the WAR filename in the URL.
There are a number of ways to deploy a WAR file on Tomcat. We will use the Tomcat Manager. From the default Tomcat page (http://localhost:8080), select the Tomcat Manager link. This next page shows the currently deployed applications. At the bottom of the page is a form to upload a WAR file. Once the WAR file is deployed you can see the status of the application and there are various commands available to manage it.
(If the application fails to deploy, check the Tomcat log files in
%CATALINA_HOME%\logs.)
To build a servlet in Eclipse you start with a new Maven project just as you did previously with the JDBC application. These are the additional steps required to build a simple servlet:
maven.war.webxml=${maven.src.dir}/main/resources/web.xml
This identified the deployment descriptor to the WAR plugin to Maven. The WAR plugin will automatically create the WAR file with the correct directory structure.
%CATALINA_HOME%\common\lib\servlet-api.jar %CATALINA_HOME%\common\lib\jsp-api.jar
This will add the servlet and JSPs libraries so you can compile against the APIs.
With the project now setup, you can create your servlet in the src/main/java directory. To build the application, right-click on the project.xml file, select Maven | Run Maven to create the properties for an external tool launch: Change “test” in the Name field and select the Choose button to select the default WAR goal. Select Run.
If the build completed successfully the war application will be located in the target directory, named with your project’s Artifact ID and the .war extension. You can verify the contents of the WAR file from a console and the following command:
jar -tf <war filename>
To be successfully deployed the WAR file must contain the following:
WEB-INF/classes/... (the class files of your servlet) WEB-INF/web.xml (the deployment descriptor)
Now you can deploy your servlet in Tomcat.
(The DVD catalog .jsp code.)