Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Online Training

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
 
Training Index

Writing Advanced Applications
Chapter 4 Continued: Servlets

[<<BACK] [CONTENTS] [NEXT>>]

A servlet is a server-side program written in the JavaTM programming language that interacts with clients and is usually tied to a HyperText Transfer Protocol (HTTP) server. One common use for a servlet is to extend a web server by providing dynamic web content.

Servlets have an advantage over other technologies in that they are compiled, have threading capability built in, and provide a secure programming environment. Even web sites that previously did not provide servlet support, can do so now by using programs such as JRun or the Java module for the Apache web server.

The web-based auction application uses a servlet to accept and process buyer and seller input through the browser and dynamically return auction item information to the browser. The AuctionServlet program is created by extending the HttpServlet class. The HttpServlet class provides a framework for handling HTTP requests and responses.

This section examines the AuctionServlet and includes information on how to use Cookie and Session objects in a servlet.


HttpServlet

The AuctionServlet class extends HttpServlet, which is an abstract class.
  public class AuctionServlet extends HttpServlet {
A servlet can be either loaded when the web server starts up or loaded when requested by way of an HTTP URL that specifies the servlet. The servlet is usually loaded by a separate classloader in the web server because this allows the servlet to be reloaded by unloading the class loader that loaded the servlet class. However, if the servlet depends on other classes and one of those classes changes, you will need to update the date stamp on the servlet for it to reload.

After a servlet loads, the first stage in its lifecycle is the web server calls the servlet's init method. Once loaded and initialized, the next stage in the servlet's lifecycle is to serve requests. The servlet serves requests through its service, doGet, or doPost method implementations.

The servlet can optionally implement a destroy method to perform clen-up operations before the web server unloads the servlet.

The init Method

The init method is only called once by the web server when the servlet is first started. The init method is passed a ServletConfig object containing initialization information pertaining to the web server where the application is running.

The ServletConfig object is used to access information maintained by the web server including values from the initArgs parameter in the servlet properties file. Code in the init method uses the ServletConfig object to retrieve the initArgs values by calling the config.getInitParameter("parameter") method.

The AuctionServlet.init method also contacts the Enterprise JavaBeans server to create a context (ctx) object. The ctx object is used in the service method to establish a connection with the Enterprise JavaBeans server.

Context ctx=null;
private String detailsTemplate;

public void init(ServletConfig config) 
		throws ServletException{
  super.init(config);
  try {
    ctx = getInitialContext();
  }catch (Exception e){
    System.err.println(
                "failed to contact EJB server"+e);
  }
  try {
    detailsTemplate=readFile(
	    config.getInitParameter("detailstemplate"));
  } catch(IOException e) {
    System.err.println(
		"Error in AuctionServlet <init>"+e);
  }
}

The destroy Method

The destroy method is a lifecycle method implemented by servlets that need to save their state between servlet loading and unloading. For example, the destroy method would save the current servlet state, and the next time the servlet is loaded, that saved state would be retrieved by the init method. You should be aware that the destroy method might not be called if the server machine crashes.
public void destroy() {
  saveServletState();
}

The service Method

The AuctionServlet is an HTTP servlet that handles client requests and generates responses through its service method. It accepts as parameters the HttpServletRequest and HttpServletResponse request and response objects.
  • HttpServletRequest contains the headers and input streams sent from the client to the server.

  • HttpServletResponse is the output stream that is used to send information from the servlet back to the client.
The service method handles standard HTTP client requests received by way of its HttpServletRequest parameter by delegating the request to one of the following methods designed to handle that request. The different types of requests are described in the HTTP Requests section.
  • doGet for GET, conditional GET, and HEAD requests.
  • doPost for POST requests.
  • doPut for PUT requests.
  • doDelete for DELETE requests.
  • doOptions for OPTIONS requests.
  • doTrace for TRACE requests.
The AuctionServlet program provides its own service method implementation that calls one of the following methods based on the value returned by the call to cmd=request.getParameter("action"). These method implementations match the default implementations provided in the doGet and doPost methods called by the default service method, but add some auction application-specific functionality for looking up Enterprise Beans.
  • listAllItems(out)
  • listAllNewItems(out)
  • listClosingItems(out)
  • insertItem(out, request)
  • itemDetails(out, request)
  • itemBid(out, request)
  • registerUser(out, request)
public void service(HttpServletRequest request,
                HttpServletResponse response) 
		throws IOException {

  String cmd;
  response.setContentType("text/html");
  ServletOutputStream out = response.getOutputStream();
  if (ctx == null ) {
    try {
      ctx = getInitialContext();
    }catch (Exception e){
      System.err.println(
                  "failed to contact EJB server"+e);
    }
  }

  cmd=request.getParameter("action");
  if(cmd !=null)  {
    if(cmd.equals("list")) {
      listAllItems(out);
    }else 
    if(cmd.equals("newlist")) {
      listAllNewItems(out);
    }else if(cmd.equals("search")) {
      searchItems(out, request);
    }else if(cmd.equals("close")) {
      listClosingItems(out);
    }else if(cmd.equals("insert")) {
      insertItem(out, request);
    }else if (cmd.equals("details")) {
      itemDetails(out, request );
    }else if (cmd.equals("bid")) {
      itemBid(out, request) ;
    }else if (cmd.equals("register")) {
      registerUser(out, request);
    }
  }else{
    // no command set
    setTitle(out, "error");
  }
  setFooter(out);
  out.flush();
}

HTTP Requests

A request is a message sent from a client program such as a browser to a server program. The first line of the request message contains a method that indicates the action to perform on the incoming Uniform Resource Locator (URL). The two commonly used mechanisms for sending information to the server are POST and GET.
  • GET requests might pass parameters to a URL by appending them to the URL. GET requests can be bookmarked and emailed and include the information to the URL of the response.

  • POST requests might pass additional data to a URL by directly sending it to the server separately from the URL. POST requests cannot be bookmarked or emailed and do not change the URL of the response.
PUT requests are the reverse of GET requests. Instead of reading the page, PUT requests write (or store) the page.

DELETE requests are for removing web pages.

OPTIONS requests are for getting information about the communication options available on the request/response chain.

TRACE requests are for testing or diagnostic purposes because they let the client see what is being received at the other end of the request chain.

Using Cookies in servlets

HTTP cookies are essentially custom HTTP headers that are passed between a client and a server. Although cookies are not overwhelmingly popular, they do enable state to be shared between the two machines. For example, when a user logs into a site, a cookie can maintain a reference verifying the user has passed the password check and can use that reference to identify that same user on future visits.

Cookies are normally associated with a server. If you set the domain to .java.sun.com, then the cookie is associated with the domain. If no domain is set, the cookie is only associated with the server that created the cookie.

Setting a Cookie

The JavaTM Servlet API includes a Cookie class that you can use to set or retrieve the cookie from the HTTP header. HTTP cookies include a name and value pair.

The startSession method shown here is in the LoginServlet program. In this method, the name in the name and value pair used to create the Cookie is JDCAUCTION, and a unique identifier generated by the server is the value.

  protected Session startSession(String theuser, 
		String password,
        	HttpServletResponse response) {
    Session session = null;
    if ( verifyPassword(theuser, password) ) {
    // Create a session
      session = new Session (theuser);
      session.setExpires (sessionTimeout + i
	System.currentTimeMillis());
      sessionCache.put (session);

    // Create a client cookie
      Cookie c = new Cookie("JDCAUCTION", 
       	String.valueOf(session.getId()));
      c.setPath ("/");
      c.setMaxAge (-1);
      c.setDomain (domain);
      response.addCookie (c);
    }
    return session;
  }

Later versions of the Servlet API include a Session API, to create a session using the Servlet API in the previous example you can use the getSession method.

   HttpSession session = new Session (true);
The startSession method is called by requesting the login action from a POST to the LoginServlet as follows:
<FORM ACTION="/LoginServlet" METHOD="POST">
<TABLE>
<INPUT TYPE="HIDDEN" NAME="action" VALUE="login">
<TR>
<TD>Enter your user id:</TD>
<TD><INPUT TYPE="TEXT" SIZE=20 
  NAME="theuser"></TD>
</TR>
<TR>
<TD>Enter your password:<TD>
<TD><INPUT TYPE="PASSWORD" SIZE=20 
  NAME="password"></TD>
</TR>
</TABLE>
<INPUT TYPE="SUBMIT" VALUE="Login" NAME="Enter">
</FORM>
The cookie is created with an maximum age of -1, which means the cookie is not stored but remains alive while the browser runs. The value is set in seconds, although when using values smaller than a few minutes you need to be careful of machine times being slightly out of sync.

The path value can be used to specify that the cookie only applies to files and directories under the path set on that machine. In this example the root path / means the cookie is applicable to all directories.

The domain value in the example is read from the initialization parameters for the servlet. If the domain is null, the cookie is applied to that machines domain only.

Retrieving a Cookie

The cookie is retrieved from the HTTP headers with a call to the getCookies method on the request:
  Cookie c[] = request.getCookies();
You can later retrieve the name and value pair settings by calling the Cookie.getName method to retrieve the name, and the Cookie.getValue method to retrieve the value.

LoginServlet has a validateSession method that checks the user's cookies to find a JDCAUCTION cookie that was set in this domain:

  private Session validateSession 
                (HttpServletRequest request,
  		HttpServletResponse response) {
    Cookie c[] = request.getCookies();
    Session session = null;
    if( c != null ) {
      Hashtable sessionTable = new Hashtable();
      for (int i=0; i < c.length && 
             session == null; i++ ) {
        if(c[i].getName().equals("JDCAUCTION")) {
          String key = String.valueOf (c[i].getValue());
          session=sessionCache.get(key);
        }
      }
    }
    return session;
  }

If you use the Servlet session API then you can use the following method, note that the parameter is false to specify the session value is returned and that a new session is not created.

    HttpSession session = request.getSession(false);

Generating Sessions

The LoginServlet.validateSession method returns a Session object represented by the Session class. The Session class uses an identifier generated from a numeric sequence. This numbered session identifier is the value part of the name and value pair stored in the cookie.

The only way to reference the user name on the server is with this session identifier, which is stored in a simple memory cache with the other session IDs. When a user terminates a session, the LoginServlet logout action is called like this:

  http://localhost:7001/LoginServlet?action=logout
The session cache implemented in the SessionCache.java program includes a reaper thread to remove sessions older than a preset time. The preset timeout could be measured in hours or days depending on how many visitors visit the site.

Preventing Page Caching

The LoginServlet.setNoCache method sets the Cache-Control or Pragma values (depending on which version of the HTTP protocol is being used) in the response header to no-cache. The expiration header Expires is also set to 0, alternatively you can set the time to be the current system time. Even if the client does not cache the page, there are often proxy servers in a corporate network that would. Only pages using Secure Socket Layer (SSL) are not cached by default.
private void setNoCache (HttpServletRequest request,
               HttpServletResponse response) {
  if(request.getProtocol().compareTo ("HTTP/1.0") == 0) {
    response.setHeader ("Pragma", "no-cache");
  } else if (request.getProtocol().compareTo 
               ("HTTP/1.1") == 0) {
    response.setHeader ("Cache-Control", "no-cache");
  }
  response.setDateHeader ("Expires", 0);
}

Restricting Access and Redirections

If you install the LoginServlet as the default servlet or servlet to run when serving any page under the document root, you can use cookies to restrict users to certain sections of the site. For example, you can allow users who have cookies that state they have logged in to access sections of the site that require a login password and keep all others out.

The LoginServlet program checks for a restricted directory in its init method. The init method shown below sets the protectedDir variable to true if the config variable passed to it specifies a protected directory. The web server configuration file provides the settings passed to a servlet in the config variable.

public void init(ServletConfig config) 
	          throws ServletException  {
  super.init(config);
  domain = config.getInitParameter("domain");
  restricted = config.getInitParameter("restricted");
  if(restricted != null) {
    protectedDir=true;
  }
Later on in the validateSession and service methods, the protectedDir variable is checked and the HttpResponse.sendRedirect method is called to send the user to the correct page based on their login and session status.
  if(protectedDir) {
    response.sendRedirect (restricted+"/index.html");
  }else{
    response.sendRedirect (defaultPage);
  }

The init method also retrieves the servlet context for the FileServlet servlet so methods can be called on the FileServlet in the validateSession method. The advantage to calling methods on the FileServlet servlet to serve the files rather than serving the files from within the LoginServlet servlet, is you get the full advantage of all the functionality added into the FileServlet servlet such as memory mapping or file caching. The downside is that the code may not be portable to other servers that do not have a FileServlet servlet. This code retrieves the FileServlet context.

  FileServlet fileServlet=(FileServlet)
        config.getServletContext().getServlet("file");
The validateSession method prevents users without a logon session from accessing the restricted directory.

HTTP Error Codes

You can return a HTTP error code using the sendError method. For example, the HTTP 500 error code indicates an internal server error, and the 404 error code indicates page not found. This code segment returns the HTTP 500 error code.
  protected void service (HttpServletRequest request, 
        HttpServletResponse response) 
	throws ServletException {
     response.sendError (500);
  }

Reading GET and POST Values

The Servlet API has a getParameter method in the HttpServletRequest class that returns the GET or POST value for the name you supply.
  • The HTTP GET request handles name and value pairs as part of the URL. The getParameter method parses the URL passed in, retrieves the name=value pairs deliminated by the ampersand (&) character, and returns the value.

  • The HTTP POST request reads the name and value pairs from the input stream from the client. The getParameter method parses the input stream for the name and value pairs.

The getParameter method works well for simple servlets, but if you need to retrieve the POST parameters in the order they were placed on the web page or handle multi-part posts, you can write your own code to parse the input stream.

The next example returns POST parameters in the order they were received from the web page. Normally, the parameters are stored in a Hashtable which does not maintain the sequence order of elements stored in it. The example keeps a reference to each name and value pair in a vector that can be traversed to return the values in the order they were received by the server.

package auction;

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

public class PostServlet extends HttpServlet {
  private Vector paramOrder;
  private Hashtable parameters;

  public void init(ServletConfig config) 
	throws ServletException  {
    super.init(config);
  }


  public void service(HttpServletRequest request, 
	HttpServletResponse response) 
	throws IOException {

    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    if(request.getMethod().equals("POST") 
	&& request.getContentType().equals(
	"application/x-www-form-urlencoded")) {

      parameters=parsePostData(
                   request.getContentLength(), 
                   request.getInputStream());
    }

    for(int i=0;i<paramOrder.size();i++) {
      String name=(String)paramOrder.elementAt(i);
      String value=getParameter((
                     String)paramOrder.elementAt(i));
      out.println("name="+name+" value="+value);
    }
    out.println("</body></html>");
    out.close();
  }

  private Hashtable parsePostData(int length, 
	ServletInputStream instream) {
    String valArray[] = null;
    int inputLen, offset;
    byte[] postedBytes = null;
    boolean dataRemaining=true;
    String postedBody;
    Hashtable ht = new Hashtable();
    paramOrder= new Vector(10);
    StringBuffer sb = new StringBuffer();

    if (length <=0) {
      return null;
    }
    postedBytes = new byte[length];
    try {
       offset = 0;
       while(dataRemaining) {
         inputLen = instream.read (postedBytes, 
			offset, 
			length - offset);
         if (inputLen <= 0) {
           throw new IOException ("read error");
         }
         offset += inputLen;
         if((length-offset) ==0) {
           dataRemaining=false;
         }
       }
    } catch (IOException e) {
      System.out.println("Exception ="+e);
      return null;
    }

    postedBody = new String (postedBytes);
    StringTokenizer st = 
            new StringTokenizer(postedBody, "&");

    String key=null;
    String val=null;

    while (st.hasMoreTokens()) {
      String pair = (String)st.nextToken();
      int pos = pair.indexOf('=');
      if (pos == -1) {
        throw new IllegalArgumentException();
      }
      try {
         key = java.net.URLDecoder.decode(
                        pair.substring(0, pos));
         val = java.net.URLDecoder.decode(
                        pair.substring(pos+1, 
			pair.length()));
      } catch (Exception e) {
         throw new IllegalArgumentException();
      }
      if (ht.containsKey(key)) {
        String oldVals[] = (String []) ht.get(key);
        valArray = new String[oldVals.length + 1];
        for (int i = 0; i < oldVals.length; i++) {
           valArray[i] = oldVals[i];
        }
        valArray[oldVals.length] = val;
      } else {
        valArray = new String[1];
        valArray[0] = val;
      }
      ht.put(key, valArray);
      paramOrder.addElement(key);
    }
    return ht;
  }

  public String getParameter(String name) {
    String vals[] = (String []) parameters.get(name);
    if (vals == null) {
      return null;
    }
    String vallist = vals[0];
    for (int i = 1; i < vals.length; i++) {
      vallist = vallist + "," + vals[i];
    }
    return vallist;
  }
}
To find out whether the request is POST or GET, call the getMethod in the HttpServletRequest class. To determine the format of the data being posted, call the getContentType method in the HttpServletRequest class. For simple HTML web pages, the type returned by this call will be application/x-www-form-urlencoded.

If you need to create a post with more than one part such as the one created by the following HTML form, the servlet will need to read the input stream from the post to reach individual section. Each section distinguished by a boundary defined in the post header.

<FORM ACTION="/PostMultiServlet" 
   METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="TEXT" NAME="desc" value="">
<INPUT TYPE="FILE" NAME="filecontents" value="">
<INPUT TYPE="SUBMIT" VALUE="Submit" NAME="Submit">
</FORM>
The next example extracts a description and a file from the client browsers. It reads the input stream looking for a line matching the boundary string, reads the content line, skips a line and then reads the data associated with that part. The uploaded file is simply displayed, but could also be written to disk.
package auction;

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

public class PostMultiServlet extends HttpServlet {

   public void init(ServletConfig config) 
	throws ServletException  {
     super.init(config);
   }

   public void service(HttpServletRequest request, 
	HttpServletResponse response) 
	throws ServletException, IOException {

     response.setContentType("text/html");
     PrintWriter out = response.getWriter();
     if (request.getMethod().equals("POST") 
	&& request.getContentType().startsWith(
        "multipart/form-data")) {

       int index = request.getContentType().indexOf(
				"boundary=");
       if (index < 0) {
         System.out.println("can't find boundary type");
         return;
       }

       String boundary = 
		request.getContentType().substring(
		                           index+9);
       ServletInputStream instream = 
                            request.getInputStream();
       byte[] tmpbuffer = new byte[8192];
       int length=0;
       String inputLine=null;
       boolean moreData=true;

//Skip until form data is reached
       length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
       inputLine = new String (tmpbuffer, 0, 0, 
                                length);

       while(inputLine.indexOf(boundary) 
                         >0 && moreData) {
         length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
         inputLine = new String (tmpbuffer, 0, 0, 
                                  length);
         if(inputLine !=null)
           System.out.println("input="+inputLine);
           if(length<0) {
             moreData=false;
           }
         }

         if(moreData) {
           length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
           inputLine = new String (tmpbuffer, 0, 0, 
                                    length);

           if(inputLine.indexOf("desc") >=0) {
             length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
             inputLine = new String (tmpbuffer, 0, 0, 
                                      length);
             length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
             inputLine = new String (tmpbuffer, 0, 0, 
                                      length);
             System.out.println("desc="+inputLine);
     	   }
   	 }

         while(inputLine.indexOf(boundary) 
                           >0 && moreData) {
           length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
           inputLine = new String (tmpbuffer, 0, 0, 
                                    length);
         }
         if(moreData) {
           length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
           inputLine = new String (tmpbuffer, 0, 0, 
                                    length);

           if(inputLine.indexOf("filename") >=0) {
             int startindex=inputLine.indexOf(
                                        "filename");
             System.out.println("file name="+
                        inputLine.substring(
			startindex+10, 
			inputLine.indexOf("\"",
			startindex+10)));
             length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
             inputLine = new String (tmpbuffer, 0, 0, 
                                      length);
           }
         }
         byte fileBytes[]=new byte[50000];
         int offset=0;
         if (moreData) {
           while(inputLine.indexOf(boundary) 
                             >0 && moreData) {
             length = instream.readLine(
			tmpbuffer,
			0,
			tmpbuffer.length);
             inputLine = new String (tmpbuffer, 0, 0, length);
             if(length>0 && (
                  inputLine.indexOf(boundary) <0)) {
               System.arraycopy(
			tmpbuffer, 
			0, 
			fileBytes, 
			offset, 
			length);
               offset+=length;
             } else {
              moreData=false;
             }
           }
         }
// trim last two newline/return characters 
// before using data
        for(int i=0;i<offset-2;i++) {
          System.out.print((char)fileBytes[i]);
        }
     }
     out.println("</body></html>");
     out.close();
  }
}

Threading

A servlet must be able to handle multiple concurrent requests. Any number of end users at any given time could invoke the servlet, and while the init method is always run single-threaded, the service method is multi-threaded to handle multiple requests.

This means any static or public fields accessed by the service method should be restricted to simple thread access. The example below uses the synchronized keyword to restrict access to a counter so it can only be updated by one thread at a time:

  int counter
  Boolean lock = new Boolean(true);

  synchronized(lock){
    counter++;
  }

HTTPS

Many servers, browsers, and the Java Plug-In have the ability to support the secure HTTP protocol called HTTPS. HTTPS is similar to HTTP except the data is transmitted over a secure socket layer (SSL) instead of a normal socket connection. Web servers often listen for HTTP requests on one port while listening for HTTPS requests on another.

The encrypted data that is sent over the network includes checks to verify if the data has been tampered in transit. SSL also authenticates the webserver to its clients by providing a public key certificate. In SSL 3.0 the client can also authenticate itself with the server, again using a public key certificate.

Public key cryptography (also called asymmetric key encryption) uses a public and private key pair. Any message encrypted (made unintelligible) with the private key in the pair can only be decrypted with the corresponding public key. Certificates are digitally signed statements generated from a trusted third party Certificate Authority. The Certificate Authority needs proof that you are who you say you are because clients will be trusting the certificate they receive. It is this certificate that contains the public key in the public and private key pair. The certificate is signed by the private key of the Certificate Authority, and most browsers know the public key for the main Certificate Authorities.

While public key encryption is good for authentication purposes, it is not as fast as symmetric key encryption and so the SSL protocol uses both types of keys in the lifecycle of an SSL connection. The client and server begin an HTTPS transaction with a connection initialization or handshaking phase.

It is in the handshaking stage that the server is authenticated using the certificate that the client has received. The client uses the server's public key to encrypt messages sent to the server. After the client has been authenticated and the encryption algorithm or cipher has been agreed between the two parties, new symmetric session keys are used to encrypt and decrypt any further communication.

The encryption algorithm or cipher can be one of many popular algorithms like Rivest Shamir and Adleman (RSA) or Data Encryption Standard (DES). The greater the number of bits used to make the key, the more difficult it is to break into using brute force search techniques.

HTTPS using public key cryptography and certificates lets you provide the amount of privacy your application needs for safe and secure transactions. Servers, browsers, and Java Plug-In have their own setup for enabling HTTPS using SSL communications. In general, the steps involve the following:

  • Get a private key and a digitally-signed certificate with the matching public key.

  • Install the certificate in a location specified by the software you are using (server, browser, or Java Plug-In).

  • Enable SSL features and specify your certificate and private key files as instructed in your documentation.
You should enable SSL features according to your specific application requirements depending on the level of security you need. For example, you do not need to verify the identity of customers browsing auction items, but you will want to encrypt credit card and other personal information supplied when buyers and sellers register to participate.

HTTPS can be used for any data not just HTTP web pages. Programs written in the Java language can be downloaded over an HTTPS connection, and you can open a connection to a HTTPS server in the Java Plug-in. To write a program in the Java language that uses SSL. SSL requires an SSL library and a detailed knowledge of the HTTPS handshaking process. Your SSL library should cover the necessary steps as this information is restricted by export security control.

[TOP]


[ This page was updated: 13-Oct-99 ]

Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-99 Sun Microsystems, Inc.
All Rights Reserved. Legal Terms. Privacy Policy.