Software Engineering
Servlets

Agenda


Introduction

When a server has client's data to compute - a CGI program, usually written in C-like or Perl languages, is executed. A CGI receives parameters, executes one or more computations, gets a result, send it back to the client and exits. This means that at each client's request the same CGI program has to be loaded, executed and terminated. This procedure is actually the most popular in the client-server environment, but it often overloads servers.

Servlets are Java applications that can perform the same work of a CGI program. Their fast diffusion means they can be considered a valid alternative. Advantages offered by servlets have to be searched first of all in the Java Servlet API (Application Program Interface) that assures programmers they can write totally portable software according to the Java principle "Write Once Run Anywhere". Moreover Java application development is easier than C or Perl one, so it easier to create a Java error free application. All these advantages are obtained to the detriment of a longer execution time. To solve this problem JSDK developers decided to have servlet loaded and initialized just once in all their life cycle. According to this strategy, a servlet is loaded at the first execution and then it is ready to run again without reloading. A servlet life cycle ends only when a particular method is invoked.

JDK 6 Documentation
Java Platform, Standard Edition 6 API Specification
Java Platform Enterprise Edition, v 5.0 API Specifications
Servlet Examples with Code
 


HTML Forms

<FORM method="POST" action="subscribe.cgi">
<INPUT type=hidden name="userrequest" value="subsingle">
<INPUT type=hidden name="outputfile" value="suboutput">
<INPUT type=hidden name="errorfile" value="suberror">
<TABLE cols="3">

<TR>
<TD align="right">
Your E-mail Address:
</TD>

<TD>
<INPUT type="text" name="email">
</TD>

<TD align="left">
<INPUT type="submit" value="Subscribe">
</TD>
</TR>
</TABLE>
</FORM>

General Format of HTTP Messages

General format of a request message

General format of response message


GET and POST


CGI Programming

"CGI" stands for "Common Gateway Interface." CGI is the method by which a web server can obtain data from (or send data to) databases, documents, and other programs, and present that data to viewers via the web. More simply, CGI is programming for the web. A CGI can be written in any programming language.


A CGI Script

#!/usr/local/bin/perl

$mailprogram = "/usr/lib/sendmail";

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
        ($name, $value) = split(/=/, $pair);
        $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
        $FORM{$name} = $value;
}
$outputtemplate = "$FORM{'outputfile'}.html";
$errortemplate = "$FORM{'errorfile'}.html";
$mailthis = "To: [email protected]\n";

# make sure the user entered a valid email address.
$temp = $FORM{'email'};
$temp =~ s/_/a/g;
$temp =~ s/-/a/g;
unless ($temp =~ /\w+@\w+\.\w\w+/) {
        &error($FORM{'email'});
        exit;
}

$mailthis .= "From: $FORM{'email'}\n";
$mailthis .= $FORM{'userrequest'};

open(MAIL,"|$mailprogram -t");
print MAIL "$mailthis\n";        
close(MAIL);

&write_output_html($FORM{'email'});
exit;

sub write_output_html {

   $email_address = $_[0];

   open(OUTPUTTEMPLATE,"$outputtemplate") || die $!;

   print "Content-type: text/html\n\n";

   while ($line = ) {

       $line =~ s/\?email_address\?/$email_address/g;
       print $line;
   }

   close(OUTPUTTEMPLATE);
}

sub error {

   $email_address = $_[0];

   open(ERRORTEMPLATE,"$errortemplate") || die $!;

   print "Content-type: text/html\n\n";

   while ($line = ) {

       $line =~ s/\?email_address\?/$email_address/g;
       print $line;
   }

   close(ERRORTEMPLATE);

   exit;
}

A Template File

<HTML>
<HEAD>
<TITLE>Subscribe to the SORCER Newsletter</TITLE>
<META NAME="description" content="The SORCER Newsletter is a monthly email publication announcing 
the lab activities.">
<META NAME="keywords" content="SORCER Newsletter, Mailing List">
</HEAD>

<!--BEGIN_TITLE_BLOCK-->
<font face="arial, helvetica" COLOR="#000066">
<font size=6>
<SPAN class=pagetitle1>Subscription Successful</SPAN>
</font>
</font>
<!--END_TITLE_BLOCK-->
<HR align="left" width="85%">
<P>
You have been successfully added to the SORCER Newsletter's mailing list at the
following e-mail address:
<BLOCKQUOTE>
<STRONG>?email_address?</STRONG>
</BLOCKQUOTE>

<P>If you change your mind, you can
<A href="http://www.sorcer.com/unsubscribe.html">unsubscribe</A> at any time.

</BODY>
</HTML>

PHP

PHP is a server-side scripting language that can be used on a host of webservers and platforms. What server-side scripting language means is that the script is put into the HTML files that make up a site, but the server processes the script BEFORE it is sent to the client browser. PHP code is not visible if you view the source of a page because the server processes the code and returns only the output. This is easier to code and debug than writing CGI scripts in Perl or C since the HTML form and related code are all in one page and PHP puts any errors on the browser.

Another advantage that PHP offers is the ability to directly connect to relational databases using full featured internal functions. It supports a whole fleet of databases including Oracle, DB2, mSQL and MySQL.

The PHP code stars with the <?php" tag and ends at "?> tag.


Servlets

Servlets are modules of Java code that run in a server application (hence the name "Servlets", similar to "Applets" on the client side) to answer client requests. Servlets are not tied to a specific client-server protocol but they are most commonly used with HTTP and the word "Servlet" is often used in the meaning of "HTTP Servlet".

Servlets make use of the Java standard extension classes in the packages javax.servlet (the basic Servlet framework) and javax.servlet.http (extensions of the Servlet framework for Servlets that answer HTTP requests). Since Servlets are written in the highly portable Java language and follow a standard framework, they provide a means to create sophisticated server extensions in a server and operating system independent way.

Typical uses for HTTP Servlets include:

 

Servlets have several advantages over CGI:


JavaServerPages (JSP)

 

In Java 2 Platform, Enterprise Edition (J2EE) v1.4, JSP technology has simplified the page and extension development models with the introduction of a simple expression language, tag files, and a simpler tag extension API, among other features. This makes it easier than ever for you to build pages based on JSP technology.

<HTML>
<BODY>
<%
    // This is a scriptlet.  Notice that the "date"
    // variable we declare here is available in the
    // embedded expression later on.
    System.out.println( "Evaluating date now" );
    java.util.Date date = new java.util.Date();
%>
Hello!  The time is now <%= date %>
</BODY>
</HTML>
 
<HTML>
<BODY>
<%
    // This scriptlet declares and initializes "date"
    System.out.println( "Evaluating date now" );
    java.util.Date date = new java.util.Date();
%>
Hello!  The time is now
<%
    // This scriptlet generates HTML output
    out.println( String.valueOf( date ));
%>
</BODY>
</HTML>
 

Servlets (Tomcat)  and IIS (Internet Information Services)

The ISPI (Internet Services Application Programming Interface) filter

AJP - Apache JServ Protocol


Servlet Advantages


How a Servlet Works

To execute a servlet it is necessary to connect the web server to a servlet engine (e.g. Tomcat or Apache/Tomcat) and to configure the web server in such a way it can recognize which clients' requests are directed to a servlet.

javax.servlet.GenericServlet class in J2EE
GenericServlet class derives form java.lang.Object class and implements Serializable, Servlet and ServletConfig interfaces. All servlets we'll develop in this document extend GenericServlet class or others derived from it. Now we are going to describe GenericServlet class methods.

init(ServletConfig)
This method is called when the servlet is initialized. Only after its execution the servlet is ready to handle clients' requests. If errors occur during init() execution an UnavaiableException is raised. init() method saves the ServletConfig object too. This object is used by getServletConfig() method.
service()
service() method handles and redirect to the right function clients' requests.
getServletInfo()
getServletInfo() returns a string containing servlet's description. This method is generally overwritten by servlets' developers.

log(String)
log() method writes the servlet name and received parameters in a log-file. This allows the webmaster to analyze servlets' executions.

destroy()
destroy() frees the memory and terminates the servlet execution. It also calls the log() method to notify the destroy operation. After a call to destroy() the servlet can't handle clients' requests until it is reloaded and reinitialized.

All methods described above can be overwritten. It is often necessary to overwrite the init() method. When we decide to overwrite init() method it is important to remember:

1. New init() method has to manage the UnavailableException exception thrown on errors.
2. Parameters in the ServletConfig object have to be saved so that they'll be available to getServletConfig() method.

To simplify our work, it is possible to insert in new init() method the line:  super.init(ServletConfig).

It could be a good idea to overwrite the destroy() method too when our servlet executes long operations. In this way we'll be sure long operations will not be interrupted and that the servlet exits only when all clients have been served.

java.lang.Object
  extended byjavax.servlet.GenericServlet
      extended byjavax.servlet.http.HttpServlet
provides an abstract class to be subclassed to create an HTTP servlet suitable for a Web site. A subclass of HttpServlet must override at least one method, usually one of these:

There's almost no reason to override the service method. service handles standard HTTP requests by dispatching them to the handler methods for each HTTP request type (the doXXX methods listed above).


A Basic Servlet

 1 import java.io.PrintWriter;
 2 import java.io.IOException;
 3 import javax.servlet.ServletException;
 4 import javax.servlet.http.HttpServlet;
 5 import javax.servlet.http.HttpServletRequest;
 6 import javax.servlet.http.HttpServletResponse;
 7 
 8 public class BasicServlet extends HttpServlet {
 9 
10     public void doGet(HttpServletRequest request, HttpServletResponse response)
11         throws IOException, ServletException {
12
13         response.setContentType("text/html");
14
15         PrintWriter out = response.getWriter();
16         out.println("<HTML>");
17         out.println("<BODY>");
18         out.println("<HEAD>");
19         out.println("<TITLE>A Basic Servlet</TITLE>");
20         out.println("</HEAD>");
21         out.println("<BODY>");
22         out.println("<H1>A Basic Servlet</H1>");
23         out.println("<P>");
24         out.println("This page was produced by a servlet. Oh boy.");
25         out.println("</BODY>");
26         out.println("</HTML>");
27     }
28 }

Servlet Lifecycle


doGet() and doPost()


Initialization Parameters

 1 // ParamServlet.java
 2 
 3 import java.io.PrintWriter;
 4 import java.io.IOException;
 5 import javax.servlet.ServletException;
 6 import javax.servlet.ServletConfig;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class ParamServlet extends HttpServlet {
12 
13     String DEFAULT_QUESTION = "(2 * b) || !(2 * b)";
14     String DEFAULT_ANSWER = "Get thee to a nunnery!";
15     String question;
16     String answer;
17 
18     public void init(ServletConfig config)
19         throws ServletException {
20 
21         super.init(config);
22 
23         question = config.getInitParameter("question");
24         if (question == null) {
25             question = DEFAULT_QUESTION;
26         }
27 
28         answer = config.getInitParameter("answer");
29         if (answer == null) {
30             answer = DEFAULT_ANSWER;
31         }
32     }
33 
34     public void doGet(HttpServletRequest request, HttpServletResponse response)
35         throws IOException, ServletException {
36 
37         response.setContentType("text/html");
38 
39         PrintWriter out = response.getWriter();
40         out.println("<HTML>");
41         out.println("<BODY>");
42         out.println("<HEAD>");
43         out.println("<TITLE>A Servlet that uses Parameters</TITLE>");
44         out.println("</HEAD>");
45         out.println("<BODY>");
46         out.println("<H1>Q & A</H1>");
47         out.println("<P>");
48         out.println("Question: " + question);
49         out.println("<P>");
50         out.println("Answer: " + answer);
51         out.println("</BODY>");
52         out.println("</HTML>");
53     }
54 }

Last Modified Date

 1 // ModificationTimeServlet.java
 2 
 3 import java.io.PrintWriter;
 4 import java.io.IOException;
 5 import javax.servlet.ServletException;
 6 import javax.servlet.ServletConfig;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class ModificationTimeServlet extends HttpServlet {
12 
13     String DEFAULT_QUESTION = "(2 * b) || !(2 * b)";
14     String DEFAULT_ANSWER = "Get thee to a nunnery!";
15     String question;
16     String answer;
17     private long modificationTime; // in millisecs
18 
19     public void init(ServletConfig config)
20         throws ServletException {
21 
22         super.init(config);
23 
24         question = config.getInitParameter("question");
25         if (question == null) {
26             question = DEFAULT_QUESTION;
27         }
28 
29         answer = config.getInitParameter("answer");
30         if (answer == null) {
31             answer = DEFAULT_ANSWER;
32         }
33 
34         // Round to nearest second
35         modificationTime = (System.currentTimeMillis() / 1000) * 1000;
36     }
37 
38     public long getLastModified(HttpServletRequest request) {
39 
40         return modificationTime;
41     }
42 
43     public void doGet(HttpServletRequest request, HttpServletResponse response)
44         throws IOException, ServletException {
45 
46         response.setContentType("text/html");
47 
48         PrintWriter out = response.getWriter();
49         out.println("<HTML>");
50         out.println("<BODY>");
51         out.println("<HEAD>");
52         out.println("<TITLE>A Servlet that uses Parameters</TITLE>");
53         out.println("</HEAD>");
54         out.println("<BODY>");
55         out.println("<H1>Q & A</H1>");
56         out.println("<P>");
57         out.println("Question: " + question);
58         out.println("<P>");
59         out.println("Answer: " + answer);
60         out.println("</BODY>");
61         out.println("</HTML>");
62     }
63 }

Form Data


Using Form Parameters

 1 // FormServlet.java
 2 
 3 import java.io.PrintWriter;
 4 import java.io.IOException;
 5 import javax.servlet.ServletException;
 6 import javax.servlet.ServletConfig;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10  
11 public class FormServlet extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14         throws IOException, ServletException {
15 
16         response.setContentType("text/html");
17 
18         PrintWriter out = response.getWriter();
19         out.println("<HTML>");
20         out.println("<BODY>");
21         out.println("<HEAD>");
22         out.println("<TITLE>A Form Servlet</TITLE>");
23         out.println("</HEAD>");
24         out.println("<BODY>");
25         out.println("<H1>A Servlet in Top Form</H1>");
26         out.println("<P>");
27         out.println("Name: " + request.getParameter("name"));
28         out.println("<P>");
29         out.println("Rank: " + request.getParameter("rank"));
30         out.println("<P>");
31         out.println("Serial Number: " + request.getParameter("serial"));
32         out.println("</BODY>");
33         out.println("</HTML>");
34     }
35
36     public void doPost(HttpServletRequest request, HttpServletResponse response)
37         throws IOException, ServletException {
38 
39         doGet(request, response);
40     }
41 }
 1 <HTML>
 2 <HEAD>
 3 <TITLE>A Form for a Servlet</TITLE>
 4 </HEAD>
 5 <BODY>
 6 <CENTER>
 7 <H1>We Have Ways To Make You Talk</H1>
 8 <FORM action="/examples/servlet/FormServlet">
 9 <TABLE>
10 <TR>
11 <TD>
12 <STRONG>Name:</STRONG>
13 </TD>
14 <TD>
15 <INPUT type="text" name="name">
16 </TD>
17 </TR>
18 <TR>
19 <TD>
20 <STRONG>Rank:</STRONG>
21 </TD>
22 <TD>
23 <INPUT type="text" name="rank">
24 </TD>
25 </TR>
26 <TR>
27 <TD>
28 <STRONG>Serial Number:</STRONG>
29 </TD>
30 <TD>
31 <INPUT type="text" name="serial">
32 </TD>
33 </TR>
34 <TR>
35 <TD colspan="2" align="center">
36 <INPUT type="submit" value="Submit">
37 </TD>
38 </TR>
39 </TABLE>
40 </FORM>
41 </CENTER>
42 </BODY>
43 </HTML>

Reading All Parameters

 1 // In file Servlets/ex5/AllParamsServlet.java
 2 
 3 import java.io.PrintWriter;
 4 import java.io.IOException;
 5 import java.util.Enumeration;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.ServletConfig;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 public class AllParamsServlet extends HttpServlet {
13 
14     public void doGet(HttpServletRequest request, HttpServletResponse response)
15         throws IOException, ServletException {
16 
17         response.setContentType("text/html");
18 
19         PrintWriter out = response.getWriter();
20         out.println("<HTML>");
21         out.println("<BODY>");
22         out.println("<HEAD>");
23         out.println("<TITLE>A Servlet that Reports all Parameters</TITLE>");
24         out.println("</HEAD>");
25         out.println("<BODY>");
26         out.println("<H1>The Parameters and Their Values:</H1>");
27 
28         Enumeration names = request.getParameterNames();
29         while (names.hasMoreElements()) {
30             out.println("<P>");
31             String name = (String) names.nextElement();
32             String value = request.getParameter(name);
33             out.println("Parameter Name: " + name + "<BR>");
34             out.println("Parameter Value: " + value);
35         }
36 
37         out.println("</BODY>");
38         out.println("</HTML>");
39     }
40 
41     public void doPost(HttpServletRequest request, HttpServletResponse response)
42         throws IOException, ServletException {
43 
44         doGet(request, response);
45     }
46 }

Request Headers


Request Convenience Methods


HTTP Request Headers


Using Request Headers: Compressing Pages

 1 // CompressServlet.java
 2 
 3 import java.io.PrintWriter;
 4 import java.io.IOException;
 5 import java.io.OutputStream;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.ServletConfig;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 import java.util.zip.GZIPOutputStream;
12 
13 public class CompressServlet extends HttpServlet {
14 
15     public void doGet(HttpServletRequest request, HttpServletResponse response)
16         throws IOException, ServletException {
17 
18         response.setContentType("text/html");
19 
20         PrintWriter out;
21         String zipped = " (Compressed Document)";
22 
23         String acceptedEncodings = request.getHeader("Accept-Encoding");
24         if ((acceptedEncodings != null)
25             && (acceptedEncodings.indexOf("gzip") != -1)) {
26 
27             // GZIP is accepted, so send a compressed document
28             OutputStream gzipper = new GZIPOutputStream(response.getOutputStream());
29             out = new PrintWriter(gzipper);
31             response.setHeader("Content-Encoding", "gzip");
32         }
33         else {
34             out = response.getWriter();
35             zipped = " (Uncompressed Document)";
36         }
37 
38         out.println("<HTML>");
39         out.println("<BODY>");
40         out.println("<HEAD>");
41         out.println("<TITLE>A Romantic Servlet" + zipped + "</TITLE>");
42         out.println("</HEAD>");
43         out.println("<BODY>");
44         out.println("<H1>How do I love thee? Let me count the ways.</H1>");
45 
46         out.println("<P>");
47 
48         for (int i = 1; i < Integer.MAX_VALUE; ++i) {
49             out.print(Integer.toString(i) + ", ");
50             if ((i % 100) == 0) {
51                 out.println("");
52                 out.println("<P>");
53             }
54         }
55 
56         out.println(Integer.toString(Integer.MAX_VALUE));
57 
58         out.println("</BODY>");
59         out.println("</HTML>");
60     }
61 
62     public void doPost(HttpServletRequest request, HttpServletResponse response)
63         throws IOException, ServletException {
64 
65         doGet(request, response);
66     }
67 }

HTTP Response


Status Codes


Response Headers


Setting Header Lines


HTTP Response Headers


Cache-Control Header


Refresh Header

Note that this is commonly set via <META HTTP-EQUIV="Refresh" CONTENT="5; URL=http://host/path"> in the HEAD section of the HTML page, rather than as an explicit header from the server.

But for servlets, setting the header directly is easier and clearer. Note that this header means "reload this page or go to the specified URL in N seconds." It does not mean "reload this page or go to the specified URL every N seconds." So you have to send a Refresh header each time, and sending a 204 (No Content) status code stops the browser from reloading further, regardless of whether you explicitly send the Refresh header or use <META HTTP-EQUIV="Refresh" ...>.


Session Tracking API


Using HttpSession


URL-rewriting

URL rewriting involves placing the session key (normally stored as jsessionid in a browser cookie) as a parameter in every HTML link in a web page. This is necessary when a browser has cookie support disabled. Every URL written out by a servlet or JSP page should be run through the following methods in the servlet API:

public String HttpServletResponse.encodeURL( String url );
public String HttpServletResponse.encodeRedirectURL( String url );

The latter method is used to encode any URL used as an argument in the sendRedirect method. If the user's browser does support cookies, the URLs are simply returned unchanged. Session tracking via URLs can lead to a single browser supporting multiple sessions through several windows.

Example: instead
out.print("<HR><A HREF=\"");
out.print(req.getRequestURI());
out.print("\">Back to the shop</A></BODY></HTML>");
use:
out.print("<HR><A HREF=\"");
out.print(res.encodeUrl(req.getRequestURI()));
out.print("\">Back to the shop</A></BODY></HTML>");

creates:
http://yucca.cs.ttu.edu/servlets-examples/servlet/ShoppingCartServlet2;jsessionid=E9177C551F54C53D847764C63233AD43


Session Tracking - Example
ShoppingCartServlet, ShoppingCartServlet2

This section shows how to

Session Tracking allows a Servlet to associate a request with a user. A session can extend across requests and connections of the stateless HTTP. Sessions can be maintained in two ways:

  1. By using Cookies. A Cookie is a string (in this case that string is the session ID) which is sent to a client to start a session. If the client wants to continue the session it sends back the Cookie with subsequent requests. This is the most common way to implement session tracking.
  2. By rewriting URLs. All links and redirections which are created by a Servlet have to be encoded to include the session ID. This is a less elegant solution (both, for Servlet implementors and users) because the session cannot be maintained by requesting a well-known URL. It also does not allow the use of static pages. All HTML pages which are sent within a session have to be created dynamically.

    Our next Servlet manages a virtual shopping cart. Users can add various items to their shopping cart via HTML forms. The shopping cart contents are stored on the server and each user gets his own shopping cart which is selected automatically whenever he makes a request to the Servlet.

    In the simplified version that we implement in class ShoppingCartServlet there are only two kinds of items, named FOO and BAR. By pressing a button in an HTML form a single FOO or BAR item can be put into the shopping cart. There's another button to see the current contents of the shopping cart and a button to order the selected items, thus clearing the shopping cart.

    The first version of the Servlet, called ShoppingCartServlet, which works with Cookie-style sessions only, consists of the two standard methods, doGet and doPost:

    Note that req.getSession is called for every POST request. It is important that the session object is requested on a regular basis because the Web Server may set a session timeout. Requesting the session ensures that the session's time-to-live is reset. The only reason for not calling req.getSession in the doGet method of this version of the Servlet is to make the response to doGet cachable.

    Adding Support for URL Rewriting

    To make the Servlet usable with URL rewriting (for clients without Cookie support or with Cookie support turned off) we have to make some modifications.

    The formerly static "Online Shop" page which is created by doGet needs to be modified to include an ACTION URL which contains an encoded session ID in the HTML form. This is done with the encodeUrl method of HttpServletResponse. We also need to call req.getSession to keep the session alive. The additional code to check for a new session can be avoided by using getSession(false). If there is no session or an invalid session we do not force the creation of a new session. This is deferred until the doPost method is called. Finally, the response has to be marked as not cachable by calling res.setHeader("pragma", "no-cache"), as usual.

    The doPost method requires only a minor change. The Servlet's URI which is used to link back to the "Online Shop" page needs to be encoded with res.encodeUrl, as in the doGet method.

    Beginning with version 2.1 of the Servlet API, the abbrevation URL is consistently spelled in upper case in all method names. The old method names have been deprecated but are still supported in 2.1. The method encodeUrl which is used in the shopping cart Servlet should be replaced by encodeURL when writing a 2.1-compliant Servlet.

    Modified Cart Servlet is available as ShoppingCartServlet2.


Servlet Clients

 

HTTP is “stateless”

Protocols that maintain “state” are complex!


Creating a URL

    try {
	// With components.
        URL url = new URL("http", "hostname", 80, "index.html");
        // With a single string.
        url = new URL("http://hostname:80/index.html");
    } catch (MalformedURLException e) {
    
    }

Converting Between a URL and a URI

    URI uri = null;
    URL url = null;
    
    // Create a URI
    try {
        uri = new URI("file://D:/almanac1.4/Ex1.java");
    } catch (URISyntaxException e) {

    }
    

    // Convert an absolute URI to a URL
    try {
        url = uri.toURL();
    } catch (IllegalArgumentException e) {
        // URI was not absolute
    } catch (MalformedURLException e) {

    }
    
 
   // Convert a URL to a URI
    try {
        uri = new URI(url.toString());
    } catch (URISyntaxException e) {

    }

Parsing a URL

    try {
        URL url = new URL("http://hostname:80/index.html#_top_");
    
        String protocol = url.getProtocol();    // http
        String host = url.getHost();            // hostname
        int port = url.getPort();               // 80
        String file = url.getFile();            // index.html
        String ref = url.getRef();              // _top_
    } catch (MalformedURLException e) {
    }

Sending a POST Request Using a URL

    try {
        // Construct data
        String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8");
        data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8");
    
        // Send data
        URL url = new URL("http://hostname:80/cgi");
        URLConnection conn = url.openConnection();
        conn.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
        wr.write(data);
        wr.flush();
    
        // Get the response
        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = rd.readLine()) != null) {
            // Process line...
        }
        wr.close();
        rd.close();
    } catch (Exception e) {

    }

Getting Text from a URL

    try {
        // Create a URL for the desired page
        URL url = new URL("http://hostname:80/index.html");
    
        // Read all the text returned by the server
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String str;
        while ((str = in.readLine()) != null) {
            // str is one line of text; readLine() strips the newline character(s)
        }
        in.close();
    } catch (MalformedURLException e) {

    } catch (IOException e) {

    }

Getting an Image from a URL

    try {
        // Create a URL for the image's location
        URL url = new URL("http://hostname:80/image.gif");
    
        // Get the image
        java.awt.Image image = java.awt.Toolkit.getDefaultToolkit().getDefaultToolkit().createImage(url);
    } catch (MalformedURLException e) {

    } catch (IOException e) {

    }

Getting a Jar File Using a URL

    try {
        // Create a URL that refers to a jar file on the net
        URL url = new URL("jar:http://hostname/my.jar!/");
    
        // Create a URL that refers to a jar file in the file system
        url = new URL("jar:file:/c:/almanac/my.jar!/");
    
        // Get the jar file
        JarURLConnection conn = (JarURLConnection)url.openConnection();
        JarFile jarfile = conn.getJarFile();
    
        // When no entry is specified on the URL, the entry name is null
        String entryName = conn.getEntryName();  // null
    
    
        // Create a URL that refers to an entry in the jar file
        url = new URL("jar:file:/c:/almanac/my.jar!/com/mycompany/MyClass.class");
    
        // Get the jar file
        conn = (JarURLConnection)url.openConnection();
        jarfile = conn.getJarFile();
    
        // Get the entry name; it should be the same as specified on URL
        entryName = conn.getEntryName();
    
        // Get the jar entry
        JarEntry jarEntry = conn.getJarEntry();
    } catch (MalformedURLException e) {

    } catch (IOException e) {

    }

Accessing a Password-Protected URL

    // Install the custom authenticator
    Authenticator.setDefault(new MyAuthenticator());
    
    // Access the page
    try {
        // Create a URL for the desired page
        URL url = new URL("http://hostname:80/index.html");
    
        // Read all the text returned by the server
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String str;
        while ((str = in.readLine()) != null) {
            // str is one line of text; readLine() strips the newline character(s)
        }
        in.close();
    } catch (MalformedURLException e) {
    } catch (IOException e) {
    }
    
    public class MyAuthenticator extends Authenticator {
        // This method is called when a password-protected URL is accessed
        protected PasswordAuthentication getPasswordAuthentication() {
            // Get information about the request
            String promptString = getRequestingPrompt();
            String hostname = getRequestingHost();
            InetAddress ipaddr = getRequestingSite();
            int port = getRequestingPort();
    
            // Get the username from the user...
            String username = "myusername";
    
            // Get the password from the user...
            String password = "mypassword";
    
            // Return the information
            return new PasswordAuthentication(username, password.toCharArray());
        }
    }

Getting the Response Headers from an HTTP Connection

    try {
        // Create a URLConnection object for a URL
        URL url = new URL("http://hostname:80");
        URLConnection conn = url.openConnection();
    
        // List all the response headers from the server.
        // Note: The first call to getHeaderFieldKey() will implicit send
        // the HTTP request to the server.
        for (int i=0; ; i++) {
            String headerName = conn.getHeaderFieldKey(i);
            String headerValue = conn.getHeaderField(i);
    
            if (headerName == null && headerValue == null) {
                // No more headers
                break;
            }
            if (headerName == null) {
                // The header value contains the server's HTTP version
            }
        }
    } catch (Exception e) {
    }

Here's a sample of headers from a website:

    Key=Value
    
    null=HTTP/1.1 200 OK
    Server=Netscape-Enterprise/4.1
    Date=Mon, 11 Feb 2002 09:23:26 GMT
    Cache-control=public
    Content-type=text/html
    Etag="9fa67d2a-58-71-3bbdad3283"
    Last-modified=Fri, 05 Oct 2001 12:53:06 GMT
    Content-length=115
    Accept-ranges=bytes
    Connection=close

Getting the Cookies from an HTTP Connection

When the server wants to set a cookie in the client, it includes a response header of the form

    Set-Cookie: cookie-value; expires=date; path=path; domain=domain-name; secure

cookie-value is some arbitrary string data that should be returned to the server in future URL requests. The life time of the cookie is specified by expires. If expires is not specified, the cookie expires at the end of the session. When a URL request is made, the cookie should be sent along only if domain-name matches the end of the fully-qualified host name of the URL request and path matches the beginning of the path of the URL request. If secure is specified, the cookie should be sent to the server only through HTTPS.

    try {
        // Create a URLConnection object for a URL
        URL url = new URL("http://hostname:80");
        URLConnection conn = url.openConnection();
    
        // Get all cookies from the server.
        // Note: The first call to getHeaderFieldKey() will implicit send
        // the HTTP request to the server.
        for (int i=0; ; i++) {
            String headerName = conn.getHeaderFieldKey(i);
            String headerValue = conn.getHeaderField(i);
    
            if (headerName == null && headerValue == null) {
                // No more headers
                break;
            }
            if ("Set-Cookie".equalsIgnoreCase(headerName)) {
                // Parse cookie
                String[] fields = headerValue.split(";\\s*");
    
                String cookieValue = fields[0];
                String expires = null;
                String path = null;
                String domain = null;
                boolean secure = false;
    
                // Parse each field
                for (int j=1; j<fields.length; j++) {
                    if ("secure".equalsIgnoreCase(fields[j])) {
                        secure = true;
                    } else if (fields[j].indexOf('=') > 0) {
                        String[] f = fields[j].split("=");
                        if ("expires".equalsIgnoreCase(f[0])) {
                            expires = f[1];
                        } else if ("domain".equalsIgnoreCase(f[0])) {
                            domain = f[1];
                        } else if ("path".equalsIgnoreCase(f[0])) {
                            path = f[1];
                        }
                    }
                }
    
                // Save the cookie...
            }
        }
    } catch (MalformedURLException e) {
    } catch (IOException e) {
    }

Here's a sample of cookies from two websites:

    B=a43ka6gu6f4n4&b=2; expires=Thu, 15 Apr 2010 20:00:00 GMT;
        path=/; domain=.yahoo.com
    
    PREF=ID=e51:TM=686:LM=86:S=BL-w0; domain=.google.com; path=/;
        expires=Sun, 17-Jan-2038 19:14:07 GMT
 

javax.servlet.http.Cookie - defined in servlet API
Java 2 Platform Enterprise Edition, v 1.4 API Specification


Sending a Cookie to an HTTP Server

    try {
        // Create a URLConnection object for a URL
        URL url = new URL("http://hostname:80");
        URLConnection conn = url.openConnection();
    
        // Set the cookie value to send
        conn.setRequestProperty("Cookie", "name1=value1; name2=value2");
    
        // Send the request to the server
        conn.connect();
    } catch (MalformedURLException e) {
    } catch (IOException e) {
    }

Directory structure for a sample Web application