SE452: Lecture 3 (Servlet API and HTML forms)

Contents [0/20]

Overview of Today's Class [1/20]
The Deployment Descriptor [2/20]
Tomcat Setup [3/20]
HTML Forms [4/20]
GET vs. POST [5/20]
Request Parameters [6/20]
Deploy the example [7/20]
Request Attributes [8/20]
More advanced Forms [9/20]
Processing Form Elements [10/20]
HTTP Request Headers [11/20]
Common Request Headers [12/20]
HTTP Response API [13/20]
Common Response Headers [14/20]
Common Status Codes [15/20]
Conditional Get [16/20]
Authentication [17/20]
HTTP Basic Authentication [18/20]
An HTTP Basic Authentiction Example [19/20]
Homework Assignment [20/20]

Overview of Today's Class [1/20]

More on web.xml

Some more Tomcat details

Some HTML, creating forms, GET vs. POST

More Servlet API

Leading up to JSPs....

Ant - a sidebar

The Deployment Descriptor [2/20]

Last week, we discussed the web application deployment descriptor, and looked at a few examples.

web.xml is an xml document, and the container requires that it not only be well-formed, but valid. It is checked against the DTD or Schema (for Servlets 2.4, optionally). The container should report errors in the web.xml file to the developer in a reasonable format. For Tomcat, this will be in the logs.

All images taken from the Servlet 1.4 specification

The web.xml structure:
overview

The servlet node:
servlet

The servlet-mapping node:
servlet-mapping

The error-page node:
error-page

The env-entry node:
env-entry

A concrete example:

    <?xml version="1.0" encoding="UTF-8"?>

    <!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>
        <display-name>A Simple Application</display-name>
        <context-param>
            <param-name>Webmaster</param-name>
            <param-value>webmaster@mycorp.com</param-value>
        </context-param>
        <servlet>
            <servlet-name>catalog</servlet-name>
            <servlet-class>com.mycorp.CatalogServlet</servlet-class>
            <init-param>
                <param-name>catalog</param-name>
                <param-value>Spring</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>catalog</servlet-name>
            <url-pattern>/catalog/*</url-pattern>
        </servlet-mapping>
        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>
        <mime-mapping>
            <extension>pdf</extension>
            <mime-type>application/pdf</mime-type>
        </mime-mapping>
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
        </welcome-file-list>
        <error-page>
            <error-code>404</error-code>
            <location>/404.html</location>
        </error-page>
    </web-app>

Tomcat Setup [3/20]

Setting up the Invoker Servlet

The invoker servlet is a special servlet that allows you to run and test your servlets without first adding them in web.xml as both a servlet node and servlet-mapping node. This can save you some time during testing and debugging. It basically maps requests for: http://localhost:8080/yourApp/servlet/ServletName to the servlet that is deployed into the WEB-INF/classes directory for yourApp. The ServletName must be fully qualified, so if you want to invoke se452.example.ExampleServlet, you need to run http://localhost:8080/yourApp/servlet/se452.example.ExampleServlet. The invoker servlet was turned off for security purposes.

To enable it, go to "tomcat_home"/conf and edit web.xml. This is a special web.xml file for Tomcat to use for its own purposes. Just search the file for the word "invoker" and uncomment the region that looks like this:

        <servlet>
            <servlet-name>invoker</servlet-name>
            <servlet-class>
              org.apache.catalina.servlets.InvokerServlet
            </servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <load-on-startup>2</load-on-startup>
        </servlet>
    

and the one that looks like this:

    <servlet-mapping>
        <servlet-name>invoker</servlet-name>
        <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    

This will allow the invoker servlet to work for the entire container

HTML Forms [4/20]

A form is a way for HTML and browsers to allow a user to send data back to the server.

A form can contain a variety of inputs, including:

An HTML form is identified in HTML source by the <form> tag


        
        <form method="m" action="uri">
            <p>more html, including fields</p>
        </form>
        
        

The method is the HTTP request method to use when submitting the data (POST or GET)

The action attribute is the server resource that will handle the request. This points to the servlet URI that we will write to handle this form.

HTML is defined by the World Wide Web consortium (W3C). See their web site for specifications of HTML, XHTML, XML, XSLT, and many other languages and tools.

GET vs. POST [5/20]

The form data is submitted as part of the HTTP request as a sequence of URL-encoded name-value pairs.

Data needs to be URL encoded, since certain characters that can be submitted as part of a request aren't allowed in a URL (like a space for example...)

The GET method encodes the name-value pairs onto the request URI (i.e. Visible in the Location of the browser)

The POST method encodes the name-value pairs in the message body of the request. (invisible to the user, but not encrypted)

GET is the default method

Here is an example HTML form:

Enter your User ID and Password and click Login

User ID
Password

And the source to make it:


        
 <html>
 <head><title>Login Page</title></head>
 <body>
    <form method="post" action="/se452/login">
        <h4>Enter your User ID and Password and click Login</h4>
        <table cellpadding='2' cellspacing='1'>
            <tr>
                <td>User ID</td>
                <td><input type="TEXT" size="15" name="userid"></input></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="PASSWORD" size="15" name="password"/></td>
            </tr>
            <tr>
                <td colspan='2'>
                    <center><input type="SUBMIT" value="Login" /></center> 
                </td>
            </tr>
        </table>
    </form>
</body>
</html>
        
        

Request Parameters [6/20]

A servlet can access the data that is in the form via Request Parameters


        String getParameter(String name)
        

Example (a login Servlet):


            
package se452.forms;           

import java.util.HashMap;
import java.util.Map;
import javax.servlet.*;
import javax.servlet.http.*;

/** 
 *
 * @author  Matthew Wright
 * @version 
 */
public class LoginServlet extends HttpServlet {
   
    protected Map users = new HashMap();
    /** 
     * Initializes the servlet with some usernames/password
    */  
    public void init() {
        users.put("mwright", "123abc");
        users.put("ltorvalds", "linux");
        users.put("test", "TEST");
    }

    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        String userid = request.getParameter("userid");
        String password = request.getParameter("password");
        if(userid != null && userid.length() != 0) {
            userid = userid.trim();
        }
        if(password != null && password.length() != 0) {
            password = password.trim();
        }
        if(userid != null &&
            password != null) {
                String realpassword = (String)users.get(userid);
                if(realpassword != null &&
                    realpassword.equals(password)) {
                    showPage(response, "Login Success!");
                } else {
                    showPage(response, "Login Failure! Username or password is incorrect");
                }
        }  else {
            showPage(response, "Login Failure!  You must supply a username and password");
        }
    } 
    
    /**
     * Actually shows the <code>HTML</code> result page
     */
    protected void showPage(HttpServletResponse response, String message)
    throws ServletException, java.io.IOException {
        response.setContentType("text/html");
        java.io.PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Login Servlet Result</title>");  
        out.println("</head>");
        out.println("<body>");
        out.println("<h2>" + message + "</h2>");
        out.println("</body>");
        out.println("</html>");
        out.close();
 
    }
    
    /** Handles the HTTP <code>GET</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    } 

    /** Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    }
}
            
            

Deploy the example [7/20]

Now, do a deploy... you will always need to follow these steps during the development process

  1. Compile the code
  2. Add the LoginServlet to web.xml in a servlet entry
  3. Add a servlet-mapping entry for /login to point to the new servlet entry
  4. Move the LoginServlet.class file to "app_home"/WEB-INF/classes/se452/forms
  5. Move the login.html file to "app_home"
  6. Point your browser to: http://localhost:8080/se452/login.html
  7. Try to log in!

Request Attributes [8/20]

A ServletRequest can also have attributes. Attributes are not the same as parameters. A parameter is something passed in from the user or the Request. An attribute is an Object associated with this request. If you look at the Servlet APIs, you will see that the following objects all have Attributes - ServletRequest, HttpSession, and ServletContext. These classes correspond with the different scopes that are available to the web application.

java.lang.Object getAttribute(java.lang.String name) 
java.util.Enumeration getAttributeNames() 
void setAttribute(java.lang.String name, java.lang.Object object)  

More advanced Forms [9/20]

Here is a more advanced form, with other HTML elements:

Software Engineering Survey

Name Information
First Name
Middle Initial
Last Name
Email

Address Information
Address
City
State ZIP

Company Information
Company Name
Company Type Private  Public  Government
Languages Used Java  C++  Visual Basic  C#  Perl 

Comments
 

And here's the source for it:


        
   <h2>Software Engineering Survey</h2>
    <form method="POST" action="/se452/servlet/survey">
      <table cellpadding="0" cellspacing="5">
        <tr><td colspan="2"><b>Name Information</b></td></tr>
        <tr>
          <td>First Name</td><td><input type="text" name="first" size="20"/></td>
        </tr>
        <tr>
          <td>Middle Initial</td><td><input type="text" name="middle" size="1" /></td>
        </tr>
        <tr>
          <td>Last Name</td><td><input type="text" name="last" size="30" /></td>
        </tr>
        <tr>
          <td>Email</td><td><input type="text" name="email" size="30" /></td>
        </tr>
        <tr><td colspan="2"><hr /></td></tr>
        <tr><td colspan="2"><b>Address Information</b></td></tr>
        <tr>
          <td>Address</td><td><input type="text" name="address" size="30" /></td>
        </tr>
        <tr>
          <td>City</td><td><input type="text" name="city" size="30" /></td>
        </tr>
        <tr>
          <td>State</td>
          <td>
            <select name="state">
              <option value="IL">Illinois</option>
              <option value="OH">Ohio</option>
              <option value="IN">Indiana</option>
              <option value="WI">Wisconsin</option>
              <option value="MI">Michigan</option>
            </select>
            ZIP<input type="text" name="zip" size="5"/>
          </td>
        </tr>
        <tr><td colspan="2"><hr /></td></tr>
        <tr><td colspan="2"><b>Company Information</b></td></tr>
        <tr>
          <td>Company Name</td><td><input type="text" name="company" size="30" /></td>
        </tr>
        <tr>
          <td>Company Type</td>
          <td><input type="radio" name="co_type" value="private" />Private
          &nbsp;<input type="radio" name="co_type" value="public" checked="true" />Public
          &nbsp;<input type="radio" name="co_type" value="government" />Government
          </td>
        </tr>
        <tr>
          <td valign="top">Languages Used</td>
          <td>
            <input type="checkbox" name="java">Java&nbsp;
            <input type="checkbox" name="cpp">C++&nbsp;
            <input type="checkbox" name="c">C&nbsp;
            <input type="checkbox" name="vb">Visual Basic&nbsp;
            <input type="checkbox" name="csharp">C#&nbsp;
            <input type="checkbox" name="perl">Perl&nbsp;
          </td>
        </tr>
        <tr><td colspan="2"><hr /></td></tr>
        <tr>
          <td valign="top">Comments</td><td><textarea name="comments" rows="2" cols="40"></textarea></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>
            <input type="submit" value="Submit" />
            <input type="hidden" name="page_name" value="login" />
          </td>
        </tr>
      </table>
    </form>
        
        

We'll go through each of the new elements of the form:

Processing Form Elements [10/20]

To process the new form elements with multiple available values , you can use the following methods of the ServletRequest


        Enumeration getParameterNames()
        

Returns an Enumeration of the parameter names in this request


        String[] getParameterValues(String name)
        

Returns a String array of values for a given Parameter name. This method is needed if you have parameters with multiple results, like a Select input.

Returns null if the Parameter doesn't exist

Here's an example that can be used to process the earlier form:


        
package se452.forms;           

import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;

/** 
 *
 * @author  Matthew Wright
 * @version 1.0
 */
public class SurveyServlet extends HttpServlet {
   

    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        response.setContentType("text/html");
        java.io.PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Survey Servlet</title>");  
        out.println("</head>");
        out.println("<body>");
        out.println("<table>");
        /* get the parameters and list them, with their values */
        Enumeration parameters = request.getParameterNames();
        if(parameters.hasMoreElements()) {
            out.println("<tr><th>Parameter Name</th><th>Parameter Value</th></tr>");
        }
        while(parameters.hasMoreElements()) {
            String parameter = (String)parameters.nextElement();
            // get the parameter values
            String[] values = request.getParameterValues(parameter);
            if(values != null) {
                for(int i = 0; i < values.length; i++) {
                    out.println("<tr><td><b><font color=\"blue\">" + parameter + "</font></b></td>" +
                            "<td>" + values[i] + "</td></tr>");
                }
            }
        }
        out.println("</table>");
        out.println("</body>");
        out.println("</html>");
        out.close();
    } 

    /** Handles the HTTP <code>GET</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    } 

    /** Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    }

}
        
        
        

HTTP Request Headers [11/20]

Here's an example HTTP request. This is sent by the client, and is the mechanism that the client uses to tell the server about itself and what it is requesting. Since HTTP is a line based protocol, the headers all appear on a separate line. We'll need to understand what some of these headers are if we are to communicate properly with the client for certain applications.

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)
Host: localhost
Connection: Keep-Alive
        

The class ServletRequest contains methods that provide information about the current request

        
        int getContentLength()
        

The length, in bytes, of the request body. Returns -1 if length isn't known.

        
        String getContentType()
        

The MIME type of the request body.

        
        String getProtocol()
        

The name and version of the protocol the client uses. In the form: protocol / majorVersion . minorVersion (e. g., HTTP/ 1.1 )

        
        String getRemoteAddr()
        

The IP address of the client.

        
        String getRemoteHost()
        

The fully qualified host name of the client.

        
         String getScheme()
        

The name of the scheme (protocol) used to make this request, e. g., http , https , or ftp .

        
        boolean isSecure()
        

Whether this request was made using a secure channel, such as https .


There are also HTTP specific headers, and these are defined in HttpServletRequest

        
        String getAuthType()
        

The name of the authentication scheme used, e. g., BASIC or SSL or null

        
        String getContextPath()
        

The portion of the request URI that indicates the context of the request.

        
        String getMethod()
        

The name of the HTTP request method e. g., GET, POST, or PUT.

        
        String getPathInfo()
        

Any extra path information associated with the URL the client sent.

        
        String getPathTranslated()
        

Any extra path information after the servlet name but before the query string, and translates it to a real path.

        
        String getQueryString()
        

The query string that is appended to the request URL after the path.

        
        String getRemoteUser()
        

The login of the user making this request, if the user has been authenticated, or null .

        
        String getRequestURI()
        

The part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.

        
        String getServletPath()
        

The part of this request's URL that calls the servlet.


Most of the above Request information is actually stored in a Request Header. Each header is one line of the HTTP request, in a key : value format. To learn what these headers are, it pays to look at the CGI (Common Gateway Interface) specification

The CGI spec is at http://hoohoo.ncsa.uiuc.edu/cgi/overview.html. CGI scripts can be written in almost any language, but most commonly are C, Perl, Python, or a similar scripting language. The CGI spec defines a number of Environment Variables that are used by CGI scripts to pass data from the server to the script (and back out)

Here's a CGI script written in Perl that prints the CGI variables


        
#!/usr/bin/perl
print "Content-type:text/html\n\n"; 
print <<EOF; 
<html><head><title>Print CGI Environment</title></head>
<body> 
EOF
print "<table><tr><th>Key</th><th>Value</th></tr>"
foreach $key (sort(keys %ENV)) { 
	print "<tr><td bgcolor=\"#F76541\">$key</td>";
	print "<td>$ENV{$key}</td></tr>\n"; 
} 
print "</table>\n";
print "</body></html>"; 
        
        

Common Request Headers [12/20]

User-Agent - Identifies the browser type and version, e. g.,Mozilla/ 4.72 [en] (X11; U; Linux 2.2.14- 5.0 i686)

Host - Indicates the host given in the request URL, e. g., se.cs.depaul.edu. Required in HTTP 1.1

Accept - Indicates MIME types browser can handle, e. g.,image/gif, image/jpeg, image/png, */*

Accept-Encoding - Indicates encodings browser can handle, e. g., gzip or compress

Connection - keep-alive : browser can handle persistent connection.

Authorization - User identification for password-protected pages.

Cookie - Cookies previously sent to the client by the same server.

If-Modified-Since - Send the page only if it has been changed after specified date.

Referer - URL of the referring Web page.


The request headers API

String getHeader( String name)

Returns the value of the specified request header as a String.

Enumeration getHeaderNames()

Returns an enumeration of all the header names this request contains.

Enumeration getHeaders( String name)

Returns all the values of the specified request header as an Enumeration of String objects.

Example:


        
        Enumeration headers = request.getHeaderNames();
        while(headers.hasMoreElements()) {
            String headerName = (String)headers.nextElement();
            String value = request.getHeader(headerName);
            out.println("      <tr><td bgcolor=\"coral\">" + headerName + "</td>" +
                "<td>" + value + "</td></tr>");
            }
            out.println("    </table>");
        }

        
        

Once example of using headers to do something useful is in the case of compressing content. Data can be sent in compressed format, which allows downloads of text data to be much faster. Browsers indicate if they can read compressed data in the Accept-Encoding request header.

Example

/*
 * CompressedSurveyServlet.java
 *
 */

package se452.forms;

import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.zip.ZipOutputStream;
import java.util.zip.GZIPOutputStream;

/**
 *
 * @author  Matthew Wright
 * @version 1.0
 */
public class CompressedSurveyServlet extends HttpServlet {
    
    
    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        // get compression support
        String encodings = request.getHeader("Accept-Encoding");
        String footer;
        ByteArrayOutputStream bstream = new ByteArrayOutputStream(1024);
        // the eventual stream that will be used
        OutputStream ostream;
        
        response.setContentType("text/html");
        if(encodings != null &&
        encodings.indexOf("gzip") != -1) {
            footer = "GZIP compressed";
            ostream = new GZIPOutputStream(bstream);
            response.setHeader("Content-Encoding", "gzip");
        } else if(encodings != null &&
        encodings.indexOf("compress") != -1) {
            footer = "ZIP compressed";
            ostream = new ZipOutputStream(bstream);
            response.setHeader("Content-Encoding", "compress");
        } else {
            footer = "Non-compressed";
            ostream = bstream;
        }
        // instead of writing to the outputstream of the response
        // directly, write to a PrintWriter first, which is either
        // a ByteArray, GZIP, or Zip OutputStream.
        java.io.PrintWriter out = new PrintWriter(ostream);
        
        
        out.println("<html><head><title>Survey Servlet</title></head>");
        out.println("<body>");
        out.println("  <table>");
        out.println("    <tr><td colspan=\"2\"><h1>Thank you for submitting your survey</h1></td></tr>");
        out.println("    <tr><td colspan=\"2\">You submitted the following information</td></tr>");
        out.println("    <tr><td>Name</td><td>" + request.getParameter("first") + " " +
            request.getParameter("middle") + " " +
            request.getParameter("last") + "<br/>" +
            request.getParameter("email") + "</td></tr>");
        out.println("    <tr><td>Address</td><td>" +
            request.getParameter("address") + "<br/>" +
            request.getParameter("city") + ",&nbsp;" +
            request.getParameter("state") + "&nbsp;&nbsp;" +
            request.getParameter("zip") + "</td></tr>");
        out.println("   <tr><td>Company</td><td>" +
            request.getParameter("company") + "<br/> which is a " +
            request.getParameter("co_type") +
            " organization</td></tr>");
        // get the languages and put them in a string which can be displayed
        String[] languages = {"vb", "perl", "cpp", "java", "c", "csharp"};
        String langresponse = new String();
        for(int i = 0; i < languages.length; i++) {
            if("on".equals(request.getParameter(languages[i]))) {
                langresponse += " " + languages[i];
            }
        }
        out.println("    <tr><td>Languages</td><td>" + langresponse + "</td></tr>");
        out.println("    <tr><td>Comments</td><td>" +
            request.getParameter("comments") + "</td></tr>");
        
        out.println("<i color=\"blue\">" + footer + "</i>");
        out.println("</body></html>");
        out.close();
        int len = bstream.size();
        response.setContentLength(len);
        bstream.writeTo(response.getOutputStream());
    }
    
    /** Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    }
    
    /** Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    }
    
}

        

HTTP Response API [13/20]

The server communicates with the client via response headers. These are set via the response API. In class HttpServletResponse:

        public void setContentLength( int len)
        

Sets the Content-Length header.

        public void setContentType( String type)
        

Sets the Content-Type header.

        public void setStatus( int statusCode)
        

Sets the status code for this response. This method is used to set the return status code when there is no error, e. g., SC_OK or SC_MOVED_TEMPORARILY . Should set status before sending document.

        public void sendError( int statusCode)
        public void sendError( int statusCode,String message)
        

Sends an error response to the client using the specified status code and an (optional) descriptive message. Wraps the message inside a small HTML document.

        public void sendRedirect( String location)
        

Sends a temporary redirect response to the client using the specified URL. May specify relative URL.

        public boolean containsHeader( String name)
        

Whether the named response header has already been set.

        public void setHeader( String name, String value)
        

Sets a response header with the given name and value. If the header is already set, the new value overwrites the previous one.

        public void addHeader( String name, String value)
        

Adds a response header with the given name and value. Response headers may have multiple values.

        public void setDateHeader( String name, long date)
        public void setIntHeader( String name, int value)
        

Sets a response header with the given name and date or integer value.

        public void addDateHeader( String name, long date)
        public void addIntHeader( String name, int value)
        

Adds a response header with the given name and date or integer value.

Common Response Headers [14/20]

Common Response Headers

Content-Encoding - The way the document is encoded.

Content-Length - The number of bytes in the document.

Content-Type - The MIME type of the document.

Expires - The time at which document should be considered out- of- date and thus should no longer be cached.

Last-Modified - The time the document was last modified.

Location - The URL to which browser should reconnect.

Refresh - The number of seconds until browser should reload page. Can also include URL to connect to.

Common Status Codes [15/20]

Common Status Codes

HTTP response status code:

Setting the status code allows you to:

Common Status Codes

200 (OK) - Everything is fine, document follows. Default for servlets.

204 (No Content) - Browser should keep displaying previous document.

301 (Moved Permanently) - Requested document permanently moved elsewhere (indicated in Location header. Browsers go to new location automatically

302 (Found) - Requested document temporarily moved elsewhere (indicated in Location header). Browser goes to new location automatically.

304 (Not Modified) - When the request header If-Modified-Since present, the requested document was available and not modified.

401 (Unauthorized) - Browser tried to access password-protected page without proper Authorization header.

404 (Not Found) - No such page (Have you seen this before?!)

Conditional Get [16/20]

One thing we can use these headers for is conditional get. When the request header If-Modified-Since is present in a request, it is called a conditional get. The browser sends this header.

Advantage: reduce network traffic and server load.

Web brower (client):

Web server:

A servlet may take advantage of the conditional get.

Explicitly setting the Last-Modified header


        long t= System.currentTimeMillis();
        response.setDateHeader("Last-Modified", t)
        

Overriding the getLastModified() method in class HttpServlet


	long getLastModified( HttpServletRequest request) {
		return System.currentTimeMillis();
	}
        

Authentication [17/20]

Authentication: The mechanism by which communicating entities prove to one another that they are acting on behalf of specific identities. A web client can authenticate a user to a web server using one of the following mechanisms:

We'll look at the first one now, and the last one later

HTTP Basic Authentication [18/20]

Based on a username and password.

Basic Authentication is not a secure authentication protocol.

The process:

An HTTP Basic Authentiction Example [19/20]

/*
 * AuthenticationServlet.java
 *
 */
 
package se452.headers;           

import javax.servlet.*;
import javax.servlet.http.*;
import sun.misc.BASE64Decoder;
import java.util.Map;
import java.util.HashMap;
import java.io.PrintWriter;
import java.util.Date;

/** 
 *
 * @author  Matthew Wright
 * @version 1.0 
 */
public class AuthenticationServlet extends HttpServlet {
    
    protected Map users = new HashMap();
    
    public void init() {
        users.put("mwright", "abc123");
        users.put("default", "tester");
        users.put("joe", "Gr8P@ssWurd");
    }

    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
    * @param request servlet request
    * @param response servlet response
    */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        response.setContentType("text/html");
        java.io.PrintWriter out = response.getWriter();

        String authentication = request.getHeader("Authorization");
        if(authentication != null) {
            String credentials = authentication.substring(6).trim();
            BASE64Decoder decoder = new BASE64Decoder();
            String userpass = new String(decoder.decodeBuffer(credentials));
            int i = userpass.indexOf(":");
            if (i > 0) {
                String username = userpass.substring(0,i);
                String password = userpass.substring(i + 1);
                String pw = (String)users.get(username);
                if(pw != null && pw.equals(password)) {
                    authorize(response);
                    return;
                }
            }
        }
        authenticate(response);
        out.close();
    } 
    
    /**
     * Attempts to authenticate the user by setting the
     * correct headers
     */
    void authenticate(HttpServletResponse response) {
       response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
       response.setHeader("WWW-Authenticate", "Basic realm=\"JavaSecrets\"");
    }
    
    /**
     * Sends a response the user that indicates they are authorized
     */
    void authorize(HttpServletResponse response)
        throws java.io.IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        
        out.println("<html><head><title>Protected Page: Java Secrets</title></head>");
        out.println("<body>Access granted. " + new Date() + "</body></html>");
    }
    
    /** Handles the HTTP <code>GET</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    } 

    /** Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, java.io.IOException {
        processRequest(request, response);
    }

}

Homework Assignment [20/20]

Create an HTML form that submits a POST request to a new servlet. The form should contain text fields, check boxes, radio buttons, and combo or list boxes. At least one control should allow multiple selections.

Name the file form.html, and place it in the default directory of your webapp.

Write a new servlet that will handle the POST request (and a GET request, like in HW1). The servlet should read and do something with each request parameter. Examples could be performing a calculation with the data, or displaying it in a certain format. The output needs to be dependent on the input data, not the same every time. Be creative!

Finally, when submitting the homework, do the following:

  1. Make sure that JAVA_HOME/bin directory is in your path (if you type jar at the command line and get an error message, then your PATH isn't set right. You will need to run something like
    set PATH=%PATH%;%JAVA_HOME%\bin
    on Windows, or export PATH=$PATH:$JAVA_HOME/bin in bash or ksh
  2. Open a command window
  3. Change to the TOMCAT_HOME/webapps/myapp directory, where myapp is your DePaul ID
  4. run the command jar cf myapp.war * (where myapp is your DePaul ID. For detail on the jar command, see the JDK tools docs)
  5. Send me the .war file as an email attachment

Questions or problems? Send me an email or post to the Discussion forum on the DL web site.


Revised: 09/28/2003