August 19, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Understanding Servlets

  • April 8, 2003
  • By Steven Haines and Steven Potts
  • Send Email »
  • More Articles »

Understanding HTTP

Because you will be using HttpServlet class to implement most of the servlets that you will ever write, it is important for you to understand what HTTP is. HTTP stands for Hypertext Transfer Protocol. A protocol is simply a published agreement between clients and servers that specifies what data, and its syntax, will be passed from one party to the other.

HTTP is an application layer protocol, which means that it depends on lower-layer protocols to do much of the work. In the case of HTTP, this lower-layer protocol is TCP/IP. The information in HTTP is transferred as plain ASCII characters. Plain text is convenient for programmers because the instructions are human-readable. By contrast, binary protocols like those used in RMI and CORBA are much more difficult to decipher when searching for the cause of a programming error.

HTTP is a stateless and connectionless protocol. Stateless means that each request and response pair constitutes an entire conversation. There is no memory of one transaction available to the next transaction. It is kind of like computerized amnesia. Connectionless means that there is no concept of a logon or logoff in HTTP, as there is in FTP. In fact, the requester is anonymous from the protocol's point of view.

Being stateless is both good and bad. It is good from a performance standpoint because there is no need for the program that accepts HTTP requests (the Web server) to remember any state information. This greatly reduces the server's workload and makes it possible for one server to process thousands of clients. On the other hand, being stateless limits the usefulness of the protocol. If you want to create an application that does some work, asks the user some questions, then does some more work, you have to manage this in the code that you write. We will cover this problem of saving state later in the chapter.

A connectionless protocol also has positives and negatives. If no time is spent establishing a connection, the server can service more requests per unit of time. This also limits the usefulness of the protocol. If you want a user to logon, do some stuff, then logoff, you will have to write your own code to do that. Fortunately, the servlet classes support this requirement pretty well.

HTTP is a request and response protocol. This means that it is composed of pairs of requests and responses, as shown in Figure 21.7.

Figure 21.7.

The HTTP protocol is based on the assumption that every request will be answered with one response.

The format of the request is all done in plain text and is sent as a string from the client to the server. The server reads the message and performs the task that it has been instructed to do. In some cases, this task is to retrieve a static document and send it back to the client's browser for display. In other cases, this request is for a servlet to be run and the results of that, if any, to be sent to the client.

The GET Command

The most frequently used HTTP command is the GET command. This command states that the browser is to ask the server to send back a copy of a document. If that document has already been cached, the browser might use that one instead of retrieving it again. Listing 21.3 shows a simple HTTP GET request for a document.

Listing 21.3 A Request for xyz.html

GET /xyz.html HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*
  • The GET means that we want to retrieve a result. Also those parameters, if any, will be appended to the name of the document or servlet.

  • The User-Agent tag tells the server what version of the browser the client is running. This gives the server a chance to tailor the response to suit this browser.

  • The Accept tag tells the server what kind of replies, in addition to text, the browser can process.

The job of the Web server is to parse this text and decide how to handle the results. If you want to pass parameters to the server, you can do that by appending them to the name of the document, as shown in Listing 21.4.

Listing 21.4 Passing Parameters with GET

GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*

In this listing, we are telling the server to return that HTML page modified by the values in the parameters. The special syntax using the ? tells the server that parameters start here. A parameter/value pair is indicated by the =. The & indicates that another parameter follows this. Notice that there are no quotes around the strings. If numbers are placed on the line, they are sent as strings also, and it is up to the server or servlet to do any conversion or casting to another data type.

The parameters modify the behavior of the document or servlet. The nature of the modification is a decision of the page designer or servlet programmer. The names of the parameters are important because they will be used to extract the value for this parameter from the request object in the servlet.

There is a limit of 255 characters that can be used to pass parameters appended in this way. The reason for this is that some Web servers store this string in an environment variable that is rather small. If you use a length greater than 255, it may or may not work, depending on the client. In practice, if there is a parameter list that long, the programmer will use the POST command instead.

Another drawback of passing the parameters this way is that they appear in the address bar of the browser. If your password is one of the data items, this could be a problem because the history kept by your browser now contains your password in plain text.

Calling a servlet is very similar. Listing 21.5 contains the HTTP message to invoke a servlet:

Listing 21.5 Calling a Servlet

GET /xyz.html?myparm=hello&myotherparm=world HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*

Notice that we don't specify the name of the server in this command. This is because a socket to this machine has already been opened before this message is sent. Notice also that there is no special syntax to indicate that this is a servlet. It is the responsibility of the Web server to figure out what kind of request it has been given.

The POST Command

The POST command is used to send data to the Web server. By convention, POST requests are not answered out of cache, but rather sent to the server every time. Listing 21.6 contains an example of a post command.

Listing 21.6 The POST Command

POST /xyz.html HTTP/1.0
User-Agent: Mozilla/4.51  (WinNT; I)
Accept: image/gif, image/jpeg, image/pjpeg, */*
Content-Length: 34
Content-Type:application/x-www-form-urlencoded

myparm=hello&myotherparm=world

Notice that there is a blank line between the header and the contents of the message; this is required. The length must also be passed as well as a content type. There is no stated limit to the length of the parameters to be passed using the POST command. In addition, the values of the parameters are not displayed on the command line of the browser. Aside from these differences, the behavior of the GET and the POST commands are identical.

The Other Commands

The HEAD command is like a GET command that returns only the header, but not the contents of the response. This can be useful if the browser wants only information about the document, but it doesn't have much practical value for servlet development. Other commands such as PUT, DELETE, LINK, and UNLINK are in the specification, but because they have little or no value to the servlet developer, we will not cover them here.

HTTP 1.1

A new version, HTTP 1.1, has been proposed and published by the Internet Engineering Task Group (IETF). This new version will add quite a few improvements to the HTTP 1.0 standard, but none that directly impact servlet developers. One improvement that indirectly impacts developers is the fact that connections are now kept alive by default. This means that the server will discontinue its conversation with the client, but without actually closing the connection. This connection can be reused, but it is not associated with the client that used it last. This behavior changes the performance, but not the syntax, of the HTTP commands.

Programming HTTP

The browser is a program that processes HTTP commands, among other things. The Web server is also an HTTP processing program. Both of these programs fill a place in our programming world, but they are not the only ways to process HTTP commands.

You can write a fairly simple pair of Java programs that communicate with each other, with browsers, and with servers using HTTP. Understanding how they work will clarify many points that are sometimes fuzzy when dealing with browsers and Web servers. Listing 21.7 shows a simple Java program that is able to talk to the Tomcat server using port 1776.

Listing 21.7 The HTTPFetch Class

/*
 * HTTPFetch.java
 *
 * Created on June 18, 2002, 2:54 PM
 */


import java.io.*;
import java.net.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTTPFetch
{
  
  /** Creates new HTTPFetch */
  public HTTPFetch()
  {
  }
  
  public static void main (String[] args)
  {
   try
   {
     URL url = new URL(
     "http://localhost:1776");
     BufferedReader in = new BufferedReader(
           new InputStreamReader(url.openStream()));
     String line;
     while ((line = in.readLine()) != null)
     {
      System.out.println(line);
     }
     in.close();
   }catch(Exception e)
   {
     e.printStackTrace();
   }
  }
}

This program simply initiates communication with the Tomcat server and receives the default home page. This is the page that was shown in Figure 21.3.

This program makes heavy use of the HTTP processing built into Java. We first declare a new URL object and pass in the address of the Tomcat server as a parameter to the constructor.

     URL url = new URL(
     "http://localhost:1776");

Next, we open the URL's inputStream in a Buffered reader.

     BufferedReader in = new BufferedReader(
           new InputStreamReader(url.openStream()));
     String line;

Finally, we look through it and write each line to the screen.

     while ((line = in.readLine()) != null)
     {
      System.out.println(line);
  }

To run this program, you type the following at the command line, not in a browser:

  java HTTPFetch

Instead of displaying this page in a nice graphical format, as a browser would, this program just writes the code to standard output as shown here.

<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
 "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
  <head>
  <meta http-equiv="Content-Type" content="text/html;
        charset=iso-8859-1">
  <title>Jakarta Project - Tomcat</title>
  <style type="text/css">
   <!--
    body {
      color: #000000;
      background-color: #FFFFFF;
      font-family: Arial, "Times New Roman", Times;
      font-size: 16px;
    }
 
    A:link {
      color: blue
    }
 
    A:visited {
      color: blue
    }
 
    td {
      color: #000000;
      font-family: Arial, "Times New Roman", Times;
      font-size: 16px;
    }
 
    .code {
      color: #000000;
      font-family: "Courier New", Courier;
      font-size: 16px;
    }
   -->
  </style>
</head>
 
<body>
 
<!-- Header -->
<table width="100%">
  <tr>
    <td align="left" width="130"><a href=
"http://jakarta.apache.org/tomcat/index.html"><img src=
"tomcat.gif" height="92" width="130" border="0" alt=
"The Mighty Tomcat - MEOW!"></td>
.
.
. 

Because of its length, only the first part of the output is displayed here, and that part is formatted to fit on this page. This program is similar to a browser's view source command.

The second part of this example is the HTTPServer program shown here in Listing 21.8.

Listing 21.8 The HTTPServer Class

/*
 * HTTPServer.java
 *
 * Created on June 18, 2002, 3:07 PM
 */


import java.io.*;
import java.net.*;

/**
 *
 * @author Stephen Potts
 * @version
 */
public class HTTPServer
{
  
  /** Creates new HTTPServer */
  public HTTPServer()
  {
  }
  
  public static void main(String[] args)
  {
   try
   {
     ServerSocket sSocket = new ServerSocket(1777);
     System.out.println("Created the socket");
     
     while (true)
     {
      System.out.println("Waiting for a client...");
      Socket newSocket = sSocket.accept();
      System.out.println("accepted the socket");
      
      OutputStream os = newSocket.getOutputStream();
      BufferedReader br = new BufferedReader(
      new InputStreamReader(newSocket.getInputStream()));
      
      String inLine = null;
      while (((inLine = br.readLine()) != null)
      && (!(inLine.equals(""))))
      {
        System.out.println(inLine);
      }
      System.out.println("");
      
      StringBuffer sb = new StringBuffer();
      sb.append("<html>\n");
      sb.append("<head>\n");
      sb.append("<title>Java Primer Plus\n");
      sb.append("</title>\n");
      sb.append("</head>\n");
      sb.append("<body>\n");
      sb.append("<H1>HTTPServer Works!</H1>\n");
      sb.append("</body>\n");
      sb.append("</html>\n");
      
      String string = sb.toString();
      
      //Put the output into a byte array
      byte[] byteArray = string.getBytes();
      
      //add some header information
      os.write("HTTP/1.0 200 OK\n".getBytes());
      os.write(new String(
      "Content-Length: "+ byteArray.length + "\n").getBytes());
      os.write("Content-Type: text/html\n\n".getBytes());
      //add the output
      os.write(byteArray);
      os.flush();
      
      //close it up
      os.close();
      br.close();
      newSocket.close();
     }//while
     
   }catch(Exception e)
   {
     e.printStackTrace();
   }
   
  }//main
}//class

This program is another very simple TCP/IP sockets program. The first thing that we do is create the socket:

     ServerSocket sSocket = new ServerSocket(1777);
     System.out.println("Created the socket");

Notice that we used a different port number because we have Tomcat on 1776, and we don't want a conflict. We loop and wait for a communication from a client on port 1777.

     while (true)
     {
      System.out.println("Waiting for a client...");
      Socket newSocket = sSocket.accept();
      System.out.println("accepted the socket");

When we get a communication from that port, we will create a handle to the socket that the client has handed us, and call it newSocket. We will use it to send information back to the client.

      OutputStream os = newSocket.getOutputStream();

From this point on, the program acts like any other Java IO program. We get the InputStream from the client.

      BufferedReader br = new BufferedReader(
      new InputStreamReader(newSocket.getInputStream()));

We echo the information that the client sends us to standard output.

      String inLine = null;
      while (((inLine = br.readLine()) != null)
      && (!(inLine.equals(""))))
      {
        System.out.println(inLine);
      }
      System.out.println("");

We then create some HTML code and put it in a StringBuffer.

      StringBuffer sb = new StringBuffer();
      sb.append("<html>\n");
      sb.append("<head>\n");
      sb.append("<title>Java Primer Plus\n");
      sb.append("</title>\n");
      sb.append("</head>\n");
      sb.append("<body>\n");
      sb.append("<H1>HTTPServer Works!</H1>\n");
      sb.append("</body>\n");
      sb.append("</html>\n");

We transform it to a String object, and then to a byteArray so that the OutputStream can accept it.

      String string = sb.toString();
      
      //Put the output into a byte array
      byte[] byteArray = string.getBytes();

Next, we add the HTTP header information.

      os.write("HTTP/1.0 200 OK\n".getBytes());

We add the Content-Length.

      os.write(new String(
      "Content-Length: "+ byteArray.length + "\n").getBytes());

We add the Content-Type.

      os.write("Content-Type: text/html\n\n".getBytes());

Next, we add the HTML that we wrote earlier.

      os.write(byteArray);
      os.flush();

Finally, we close up shop.

      //close it up
      os.close();
      br.close();
      newSocket.close();

Run this server by typing the following:

java HTTPServer

It pauses at the Waiting for a client ... until a client tries to connect. Open a browser and type the following:

http://localhost:1777/

Note that a Web server doesn't need to be running for this to work. This program is its own server.

Created the socket
Waiting for a client...

Action by the browser causes this server to receive the following communication:

accepted the socket
GET / HTTP/1.1
Host: localhost:1777
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US;
            rv:0.9.4.1)
 Gecko/20020508 Netscape6/6.2.3
Accept: text/xml, application/xml, application/xhtml+xml,
 text/html;q=0.9, image/png, image/jpeg, image/gif;q=0.2,
 text/plain;q=0.8, text/css, */*;q=0.1
Accept-Language: en-us
Accept-Encoding: gzip, deflate, compress;q=0.9
Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66
Keep-Alive: 300
Connection: keep-alive

Waiting for a client...

You end this program by typing Ctrl-c.

We see that the browser issued a GET. We also see that the browser didn't stipulate which document to return. The server has to decide what to do in this case. Normally, commercial servers return index.html.

We see that the browser message is in HTTP 1.1. We also see that it was a Netscape 6.2.3 browser. We also see several more pieces of information that we could make use of if we were writing a fancy server. At the end, it loops back and waits for a client. The server responds to this request by stuffing the HTTP commands that we created into the OutputStream that the client sent to us. The result is displayed on the screen, as shown in Figure 21.8.

Figure 21.8

The HTTP protocol is sent to the browser that displays it.

We can see that the browser had no trouble receiving and understanding this communication. If we run the HTTPFetch command against the HTTPServer command, we can see the details of what the HTTPServer returned. All that we have to do is change the port number in the HTTPFetch program to 1777, and we are ready.

     URL url = new URL("http://localhost:1777");

Open a second command window and type

java HTTPFetch

The result will now be output to the screen.

<html>
<head>
<title>Java Primer Plus
</title>
</head>
<body>
<H1>HTTPServer Works!</H1>
</body>
</html>

Note - If you understand this section on HTTP, you will be in a great position to comprehend what is happening behind the scenes when your servlets are running.






Page 4 of 9



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel