WebLogic Server JavaServer Pages (JSPs)

JSPs evolved to help solve some of the issues of creating dynamic Web pages with servlets. JSPs, also a part of the J2EE standards, enable the quick and efficient building of dynamic and personalized Web content.

When a WebLogic Server client issues an HTTP request, the WebLogic Server JSP container executes the appropriate JSP page, and then sends the response back to the requester.

Sound familiar? At base, JSPs are simply a more efficient way of building servlets. But instead of the assembly-language-like coding style required for creating servlets, JSPs are encoded just like a Web page but with special embedded tags and Java code. When the WebLogic Server container grabs a JSP page to service requests, it first compiles and translates that JSP page into a servlet. This servlet then exists to service further requests.

Chapter 4, Using WebLogic Server JavaServer Pages, contains more detail on how to build JSPs and the best practices for doing so.

Servlets or JSPs?

A typical application architecture for WebLogic Server can include both servlets and JSPs. The question of when to use JSPs instead of servlets, and/or both together, is an easy one. However, there are some basic guidelines that you can use to help you decide which technology is appropriate for your given task.

Use JSPs if:

  • You are building HTML pages that are not trivial (having more than a few lines and with advanced features such as tables and so forth).

  • You have one development group doing the interface design (Web pages) while another is building the Java code.

  • Your HTML code changes much more frequently than the presentation logic specified by Java code.

Use servlets if:

  • You are planning to service clients other than Web browsers, such as application clients. Even in this case, it is often useful to prototype in JSP.

  • You have a complex user interaction model, which includes complicated Web pages that are highly customized.

Use both JSPs and servlets if:

  • You have application requirements indicating both the previously stated scenarios for JSP pages and servlets.

  • You are using the MVC model (described in Chapter 4). In this model, you have servlets handling input from clients and directing requests to the appropriate JSP page to generate the HTML.

This chapter covers everything you need to know about developing servlets. Chapter 4 covers JSP development.

Even though JSP is the predominant paradigm for building J2EE application presentation logic, it is necessary to understand how servlets work in order to fully understand and make use of the power of the JSP model. Learning the servlet paradigm will allow you to take advantage of the power of JSPs.


Developing Servlets

Developing servlets is remarkably easy. The next sections cover:

  • The anatomy of a servlet

  • Session tracking

  • Cookies and URL rewriting

  • Security and WebLogic Server servlets

Anatomy of a Servlet

The servlet classes that you build must extend the class javax.servlet.http.HttpServlet. This class is one of the standard classes available as part of the Java extensions. For your convenience, these Java extensions are included as part of the WebLogic Server package.

A servlet instantiated by the WebLogic Server container begins by calling the init()method in your servlet class. This method must take as a parameter an instance of the ServletConfig class that contains information about the configuration of the servlet generated by the container.

When developing a servlet, you begin by extending the HttpServlet class, which provides implementations of all these methods, including the service() method. In this way, you are not required to re-implement every single method, but only those you'll need to change from the default behavior.

To implement a servlet, you override one of a number of different methods included from the default HttpServlet object provided. The focal method is called the service() method. It is called every time a request is made for your servlet.

There are two parameters accepted by the service method: an instance of the Javax.servlet.http.HttpServletRequest class and an instance of the Javax.servlet.http.HttpServletResponse class. The container uses the HTTP ServletRequest object request to pass the contents of the HTTP request to your servlet. The Javax.servlet.http.HttpServletResponse object directs your HTTP response to the requester.

The default implementation of the service() method dispatches calls to other, more specialized methods based on the request type. You can override this default behavior. The specialized methods exist to handle different types of user input, such as Web forms. These other, more specialized methods for handling different types of requests into servlets are discussed later in this chapter.

A Basic Servlet

No programming book would be complete without at least one “Hello World” demonstration. Let's look at a basic Hello World servlet.

First, we need to import the requisite classes into our servlet. For convenience, we grab everything in the javax.servlet, javax.servlet.http, and java.io packages by adding the following to the top of our servlet classfile, which we are calling HelloServlet.java:

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

// Next, we define our class:
public class HelloServlet extends HttpServlet {

    // And finally, we define our two methods:
    // The Service Methods to Handle HTTP Requests and Responses
    public void service(HttpServletRequest requ,
                  HttpServletResponse resp)
      throws IOException
    {
      // Now Set the Response Content Type
      resp.setContentType("text/html");
      // Now obtain a PrintWriter stream to write to.
      PrintWriter out = resp.getWriter();

      // Now Print Out Our Text
      out.println("<html><head><title>" +
                 "Hello World!</title></head>" +
                 "Hello World!</h1></body></html>");
    }

    // The INIT Method Called by the Container Before the
    // First Call to the Service Method.
    public void init(ServletConfig config)
      throws ServletException
    {
      // Must call super.init to parse init arguments
      super.init(config);
      // ...
    }
} // HelloServlet

Let's take a closer look at what went on in this example. The most important method that we implemented was the service() method, which takes two of the request and response objects as parameters. The request object encapsulates all the details and parameters of the HTTP request. In the case of this example, there is no information that the servlet cares about other than the fact that the request was made. Later in this chapter, we examine how to receive information from clients through this object and handle the requests appropriately.

WebLogic Server immediately begins creating a response for the client in the response object, which includes the HTTP response header. In order to create the body of the response for the client, we call the out method on the response object to grab a PrintWriter stream. We then use the standard print methods to write text to the stream.

Note that we did not close by calling the flush() method on the output stream. This allows WebLogic Server to try and keep open the socket with the client using a feature of HTTP 1.1 called Keep-Alive. Using this functionality allows WebLogic Server to be more efficient by reusing sockets whenever possible.

Keep-Alive is a key component of the HTTP 1.1 protocol. It helps Web servers be more efficient by minimizing the number of times that a socket is created to service a given client. To explain: Each Web page has multiple components on it that are actually downloaded separately and put together by the Web browser.

These components might include not only the HTML page itself, but also images, sounds, and so forth.

In the early days of the Web, the HTTP protocol required that the client and Web server mutually establish a socket for every one of these requests. With the advent of HTTP 1.1, it is possible to have the Web server maintain a single socket to the client for all that client's requests in a given period of time.

Keep-Alive can work if all the following conditions are met:

  1. The client specifies that it can do Keep-Alive by including either an “accept Keep-Alive” message in its request or specifies that it supports HTTP 1.1. Every commercial Web browser supports HTTP 1.1.

  2. WebLogic Server is able to determine the content length when it writes the response. This implies that the application code does not call flush() or improperly set the wrong content length in the response.

  3. The client does not break the socket, and there is no interruption in the connection between the client and the server.


Because the creation, removal, and establishment of sockets are very expensive to a server, Keep-Alive enhances scalability. You should do everything possible to encourage WebLogic Server to use Keep-Alive: Therefore, do not close streams at the end of your servlets. And, do not exceed the buffer size. If you know the content length, set it to get past this restriction. Setting the content length is discussed later in this chapter.

What happens to all the sockets? Of course, clients and servers must close sockets connecting them; otherwise, you end up with empty sockets consuming resources. There are several ways to close a socket if:

  • The socket is removed by network failure

  • The client breaks the connection

  • A timeout limit is reached

WebLogic Server enables you to specify the number of seconds that Keep-Alive is maintained. The default value is 30 seconds. The socket timeout interval can be modified on a per-server basis, using the WebLogic Server console.

You should increase the timeout value if you have users who spend very large amounts of time interacting with your Web application and repeatedly make requests at very short intervals.

The next step is to compile the servlet using your favorite Java compiler, package it up as a Web application, and then deploy it.

Deploying the Basic Servlet in WebLogic Server

In order to deploy the basic servlet, use an example deployment process that applies to every example in this chapter. The deployment process has four steps:

1.
Set up the development environment.

2.
Copy and unpack the example.

3.
Build and deploy the example.

4.
View the example.

First, find the example code for the basic servlet on the CD accompanying this book. It is located in the Web archive file named HelloServlet.war, which is located in the subdirectory /examples/ch3.

Step 1: Setting Up the Development Environment

Create a new, empty directory on your local hard disk. For this example, the directory c:dev10 will be used. You can do this either using the Windows 2000 Explorer or through the DOS command-line shell. To access a command-line shell, type the letters “cmd” into the dialog box displayed when you click on Run on the Windows Start menu.

Then, set your environment variables correctly so that you can access the WebLogic Server Java services in WebLogic Server, such as the included Java compiler:

c:eawlserver6.0configmydomainsetEnv.cmd

The preceding path may differ if you have installed WebLogic Server on a different drive. In Figure 3-1, WebLogic Server is installed on the C: drive.

Figure 3-1. Setting the Environment


Next, change to the new directory that you just created. You can do this using the cd command (see Figure 3-2).

Figure 3-2. Changing to the Example Directory


Step 2: Copying and Unpacking the Example

You should now copy over the example code from the CD-ROM into this directory. If your CD-ROM drive is the E: drive, you could use the following command:

copy E:examplesch3HelloServlet.war c:dev10

Double check that the file has arrived correctly by doing a directory listing using the dir command (see Figure 3-3).

Figure 3-3. Checking that the Web Archive Has Arrived


Unpack the package using the jar utility that is included as part of WebLogic Server. This utility is used to package and unpackage application components. To extract all the components from the .war file, type the following into the command line:

"jar xvf *.war"

You should see something like Figure 3-4.

Figure 3-4. Unpacking the Example Package


The jar tool is very powerful and used throughout J2EE applications. Virtually all the components of J2EE applications are packaged and unpackaged using jar.

To see all the things jar can do and to display all the available options, type “jar” by itself into the command line.

The jar utility creates packages in the Zip file format. This means that you can use a standard utility, such as WinZip (http://www.winzip.com), to view the contents of any J2EE application package.


Step 3: Building and Deploying the Example

A compile script for the example is included with this package. This script only works for Microsoft Windows, but can be easily tailored to work for other platforms. Remember to edit the build script to point to the proper location of your WebLogic Server deployment if you did not install WebLogic Server on the C: drive.

Type “build” and press Enter. The compilation, packaging, and deployment of the application should take place automatically (see Figure 3-5).

Figure 3-5. Compiling the Servlet with the Build Script


The build script takes advantage of a feature of WebLogic Server called directory deployments of applications. If you copy an application component into the applications directory of your WebLogic Server installation, the application code is automatically recognized and made available for deployment. If that application component is already deployed, the new and updated version is distributed to all instances of WebLogic Server that have it deployed.

You can view deployed applications in the WebLogic Server console at http://127.0.0.1:7001/console/ (see Figure 3-6).

Figure 3-6. Viewing Deployed Applications in the WebLogic Server Console


Step 4: Viewing the Example

To view the example, point a Web browser to http://127.0.0.1:7001/HelloServlet/. Don't forget to include the “/” at the end of the URL.

You should see something like Figure 3-7.

Figure 3-7. Output of the Hello World Servlet


If you do not see anything, be sure to check out the execution window for your Examples Server. The servlet in this example is designed to print out any problems to the console window for review.

If you receive an error that you cannot locate the server, or the connection is refused, then you likely need to turn off your HTTP proxy settings inside the Web browser (see Figure 3-8).

Figure 3-8. Connection Failed Error


About the Packaging and Deployment Process

The build.bat script included with this example performs four steps. First, it sets an environment variable for the deployment directory that you plan to use to install your WebLogic Server application components:

set DEPLOY_DIR=C:eawlserver6.0configmydomainapplications

Next, this script removes any packages that you might have previously built:

del %DEPLOY_DIR%HelloServlet.war

This action effectively undeploys the component from WebLogic Server, because WebLogic Server watches the applications directory. If anything changes in the applications directory for a server instance, WebLogic Server recognizes that and makes the appropriate changes to its deployed application components. We take advantage of this feature to deploy and undeploy applications from a running WebLogic Server instance. In production situations, it is recommended that you use the WebLogic Server console to deploy application components.

Next, the script calls the Java compiler, javac, which is included with WebLogic Server:

javac -d WEB-INFclasses *.java

This compiles all the Java files into the directory WEB-INFclasses. This is required by the J2EE definition of a Web application, which is discussed in a moment.

Finally, the jar utility mentioned previously is used to create a new application package:

jar cvf %DEPLOY_DIR%HelloServlet.war *

The parameters cvf tell jar that we are creating an archive, with jar displaying verbose output, and that we are specifying the files to be included. The second parameter on the command line, %DEPLOY_DIR%HelloServlet.war, tells jar to output the file to a war located in our deployment directory with the name HelloServlet.war. The third parameter, a wild card specified by *, tells jar to include every file in the current directory and those below it into the package.

About Web Applications (.war Files)

A Web application archive encapsulates a Web application, including servlets, JSP pages, static HTML pages, and supporting Java code. These files can be deployed on any application server that supports the appropriate J2EE standards.

Web application files use the Zip file format, the de facto standard for compressing and bundling multiple files into a single unit. Web applications also include information about how each application component should be deployed, including security information and mappings to URLs. The J2EE standards also define a directory structure for the Web application packages.

The WEB-INF Directory

Each Web application includes a directory called WEB-INF. This directory, unlike the rest of the components in the .war file, is not made directly available to client browsers. Instead, it contains the deployment information in the form of XML files called deployment descriptors. XML, the emerging industry standard for encapsulating data in a common format, is used extensively in J2EE applications. WebLogic Server builds many services around XML. More information on XML is available in the WebLogic Server documentation at http://www.weblogic.com/docs60/xml/index.html.

The Java code used in the Web application is placed in a directory under WEB-INF as WEB-INF/classes. The web.xml file contains mappings to tell the application server how to deploy those classes for given requests.

Application Deployment Descriptors

The deployment descriptors tell the J2EE application server how to deploy the components inside the Web application. There are two deployment descriptors. The first, web.xml, defines deployment information that is standard on every application server. The second, weblogic.xml, is application-server specific and encapsulates deployment information that is only relevant to the application server being used.

In the Hello World servlet, a simple deployment descriptor is included under the name web.xml in the WEB-INF directory. This deployment descriptor is discussed in detail later in this chapter.

The Lifecycle of a Servlet

The lifecycle of a servlet is relatively simple. Although much of the lifecycle is automatically handled, understanding how servlets behave in the context of WebLogic Server helps you understand best practices for development.

Loading and Instantiation

WebLogic Server is responsible for loading and instantiating servlets. In this case, instantiating means creating one or more instances of a servlet.

Initialization

WebLogic Server then calls the init() method of your servlet. This method initializes your servlet to handle subsequent requests, such as database connections or initialization of per-instance local variables.

Each servlet instance created can have per-instance local variables. Unless you're prepared to deal with per-instance local variables in a multi-user distribution, don't use per-instance local variables. You can use local variables within servlet methods, but not on a per-servlet instance basis.

Request Handling

WebLogic Server encapsulates the details of an incoming request into an instance of the javax.servlet.HttpServletRequest object. WebLogic Server then automatically calls an appropriate method in the servlet to handle this request. In the generic case, this generates calls to the service() method of the servlet. In other cases, such as handling POSTs and GETs, other methods are called.

There are two options when building servlets: multi-threaded and single-threaded. Single-threaded servlets implement the SingleThreadModel interface in their class declaration. This model means that only one request can be served at a time by your servlet class, even though WebLogic Server starts multiple threads of execution. Single-threading limits scalability, so it is not appropriate for Web sites where thousands of requests are handled per second.

WebLogic Server creates a pool of servlets if you implement SingleThreadModel. However, this pool is currently statically defined to be of size 5.


End of Service

WebLogic Server removes a servlet instance from active duty by calling the Destroy() method in response to a command from the WebLogic Server console, or when WebLogic Server is shut down.

End of service is different than undeployment of a servlet from a WebLogic Server. Undeployment is when the administrator of WebLogic Server removes a servlet from service. In the end-of-service section of the servlet lifecycle, the WebLogic Server container removes a servlet instance whenever the servlet engine deems necessary.

Handling Basic Servlet Requests

The servlet gains access to the request object when it is passed as a parameter to the appropriate method handling the request. In the generic case for a request, the service () method of the servlet handles the request:

// The Service Method to Handle HTTP Requests and Responses
public void service(HttpServletRequest requ,
                    HttpServletResponse resp)
       throws IOException
{
.
.

In this example, an instance of the javax.servlet.HttpServletRequest object is available through the variable name requ inside the scope of that method.

Accessing Data in the Servlet Request Object

The javax.servlet.HttpServletRequest object supports a number of methods for accessing data regarding a given request. Request object methods include:

  • public String getMethod()— Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. Unless the Web browser is instructed otherwise, all requests are GETs of information.

  • public String getAuthType()— Returns a string containing the name of the authentication scheme used to protect the servlet, for example, BASIC or SSL, or null if the servlet was not protected.

  • public String getRequestURL()— Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. For example, this would return http://learnWeblogic.com/index.jsp for the HTTP request of GET http://learnWeblogic.com/index.jsp HTTP/1.0.

  • public String getProtocol()— Returns a string containing the name and version of the protocol the request uses in the form protocol/majorVersion.minorVersion, for example, HTTP/1.1.

  • public String getServletPath()— Returns a string containing the part of this request's URL that calls the servlet. This includes either the servlet name or a path to the servlet, but does not include any extra path information or a query string.

  • public String getPathInfo()— Returns a string containing any extra path information associated with the URL the client sent when it made the request.

  • public String getPathTranslated()— Returns a string representing any extra path information after the servlet name but before the query string, and translates it to a real path.

  • public String getQueryString()— Returns the query string that is contained in the request URL after the path. This method returns null if the URL does not have a query string.

  • public int getContentLength()— Returns an integer representing the length, in bytes, of the request body in the input stream, or -1 if the length is not known. This is only useful when PUT or POST HTTP requests are made.

  • public String getContentType()— Returns the MIME type of the body of the request, or null if the type is not known.

  • public String getServerName()— Returns the host name of the server that received the request.

  • public int getServerPort()— Returns the port number on which this request was received. Typically, this is the port on which WebLogic Server is listening.

  • public String getRemoteAddr()— Returns the Internet Protocol (IP) address of the client that sent the request.

  • public String getRemoteHost()— Returns the fully qualified name of the client that sent the request, or the IP address of the client if the name cannot be determined.

  • public String getRemoteUser()— Returns the login of the user making this request if the user has been authenticated, or null if the user has not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and type of authentication.

  • public String getScheme()— Returns the name of the scheme used to make this request, for example, http, https, or ftp.

A complete list of request methods is available in the JavaDoc for the HttpServletRequest object. You can find this packaged with WebLogic Server, or online at http://java.sun.com/j2ee/j2sdkee/techdocs/api/index.html.


The following code illustrates the process of obtaining the request object and using multiple methods to determine information about the request. First, define a servlet class:

public class viewRequestServlet extends HttpServlet {

When you create a servlet, be sure to define it as a public class so that WebLogic Server (or any other application server) can access your class. Application servers can display lack-of-access errors that are very difficult to diagnose.


As with any other servlet discussed so far, the only work to be done is in the service() method of the servlet. WebLogic Server generates an instance of the HttpServletRequest object that encapsulates the details surrounding the servlet requests. This object is specific to this request and is passed as a parameter along with the response object.

public void service(HttpServletRequest req, HttpServletResponse
res)
              throws ServletException, IOException
         {

Set the appropriate return content type, and begin to compose the HTML page:

    res.setContentType("text/html");
    PrintWriter     out = res.getWriter();

    out.println("<html>");
    out.println("<head><title>viewRequest Servlet</title></
head>");
    out.println("<body>");

The HttpUtils.getRequestURL(javax.servlet.http.HttpServletRequest) method, which is available in the HttpUtils package, can be used to acquire an instance of a string representing the URL with a request scheme and complete host:

out.println("<h1>Requested URL:</h1>");
out.println("<pre>");
out.println(HttpUtils.getRequestURL(req).toString());
out.println("</pre>");

Next, call a sampling of the available methods for the HttpServletRequest object and print out the results for each:

        out.println("<h1>HttpServletRequest information:</
h1><pre>");

    // Returns the Request Method.  For Example, PUT or GET.
    out.println("<br>Request method " + req.getMethod());

    // Returns Request Scheme.  Likely "HTTP 1.1"
    out.println("<br>Request scheme " + req.getScheme());

    // The protocol type for the request.  Likely HTTP.
    out.println("<br>Request protocol " + req.getProtocol());

    // A subset of the complete URL.
    out.println("<br>Request URL " + req.getRequestURI());

    // Info on the path to the servlet.
    out.println("<br>Servlet path "     +   req.getServlet-
Path());
    out.println("<br>Path info "        +   req.getPathInfo());
    out.println("<br>Path translated "  +req.getPathTrans-
lated());
    out.println("<br>Query string "     +   req.getQue
ryString());

    // Info on the Request Content
    out.println("<br>Content length "   + req.getCon-
tentLength());
    out.println("<br>Content type "     +   req.getContent-
Type());

    // Local Server Details.
    out.println("<br>Server name "      +   req.getServerName());
    out.println("<br>Server port "      +   req.getServerPort());

    // Remote Host and User Information
    out.println("<br>Remote user "      +   req.getRemoteUser());
    out.println("<br>Remote address "   +   req.getRemoteAddr());
    out.println("<br>Remote host "      +   req.getRemoteHost());

Finally, close off the HTML page:

       out.println("</body></html>");
  }
}

The output from an execution of this servlet might look like Figure 3-9.

Figure 3-9. Output from Servlet Execution


Deploying the viewRequestServlet in WebLogic Server

The viewRequestServlet is part of the viewRequestServlet.war package, which can be found on the CD accompanying this book in the directory examplesch3. It can be compiled, packaged, and deployed using the process previously described for the Hello World example. Be sure to create a separate directory for building and deploying each servlet.

Generating the Servlet Response

As you have seen, the HTTP response that your servlet generates is handled by the instance of the HttpServletResponse object passed to your servlet via the service() method. Methods standard to this HttpServletResponse object enable you to format the response you send to clients.

Getting an Output Stream

First, we'll use the response object, the HttpServletResponse object, to get a stream to write your output to the client:

// Now obtain a PrintWriter stream to write to.
PrintWriter out = resp.getWriter();

Setting the Response Content Type

You must define the type of content (the MIME type) that you send to the client. In most cases, you'll use WebLogic Server to send out HTML as in the following:

// Now Set the Response Content Type
resp.setContentType("text/html");

You can then print to that stream:

// Now Print Out the Text
out.println("<html><head><title>" +
            "Hello World!</title></head>" +
            "Hello World!</h1></body></html>");

Note that in no case have we explicitly closed/flushed the output stream. This is intentional. As noted previously, WebLogic Server is very efficient at buffering the responses that it sends back to clients. In addition, WebLogic Server supports the notion of HTTP 1.1 Keep-Alive. Using this optimization, WebLogic Server tries to keep open sockets for as long as possible. This saves greatly in terms of the overhead required to create and destroy sockets.


Other Useful Response Methods

There are a number of other useful methods to use when generating responses:

  • public void sendError(int status) throws IOException;

  • public void sendError(int status, String message) throws IOException;

These methods allow you to send an error message to the client. To send a status of 808 with a message of "invalid state acquired", use the following code:

public void service(HttpServletRequest req, HttpServletResponse
res)
       throws ServletException, IOException
 {
res.sendError(808, "invalid state acquired");
 }

  • public void sendRedirect(String location) throws IOException;— Allows you to redirect the request to a different URL. To redirect the client to http://www.bea.com, include the following code in your servlet:

public void service(HttpServletRequest req, HttpServletResponse
res)
       throws ServletException, IOException
  {
res.sendRedirect(http://www.bea.com/)
}

  • public void setDateHeader(String headername, long date);— Sets a response header with the given name and date value. The date is specified in terms of milliseconds since the epoch. If the header has already been set, the new value overwrites the previous one. The containsHeader method can be used to test for the presence of a header before setting its value.

  • public boolean containsHeader(String name);— Used to test for the presence of a header before setting its value.

  • public void setHeader(String headername, String value);— Sets a response header with the given name and value. If the header has already been set, the new value overwrites the previous one. If the header value has already been flushed, then this method and all other methods dealing with the header are ignored.

  • public void addHeader(String headername, String value);— Adds a response header with the given name and value. This method allows response headers to have multiple values.

  • public void addIntHeader(String headername, int value);— Adds a response header with the given name and integer value. This method allows response headers to have multiple values.

  • public void setIntHeader(String headername, int value);— Sets a response header with the given name and integer value. If the header has already been set, the new value overwrites the previous one.

Using Default Methods to Handle Web Forms

In the previous examples, we built servlets that override default methods such as service().

Overriding the default methods is not always required. If it is not overwritten, the default service() method automatically dispatches requests to the appropriate method, based on the request type. There are a number of other useful default methods. For example, the servlet specification defines methods for handling different types of HTTP requests. These methods take the form of “do<request type>”, where the type of HTTP request the method handles replaces <request type>.

Servlet default methods that deal with HTTP interactions (GETs and POSTs) are doGet() and doPost(), respectively. The next section discusses the mechanics behind Web forms and the use of these methods.

About GETs

A GET request instructs the Web server to return a given resource to the client. A sample GET might look like the following:

GET http://www.bea.com/pictures/nickd/index.html HTTP/1.1

The Web server receives this GET, parses it, and responds with the appropriate resource via the protocol specified, version 1.1 of HTTP.

About POSTs

POSTs are the mechanism for transferring data from the Web browser to the servlet. POSTs are most often used to transfer data (user name, password, bid amount, etc.) from Web forms.

The parameters to POSTs consist of name/value pairs. Each field in the form is given a name. When the user completes that field in the form, the name is initialized with the value the user entered. Once the request is completed (when the user presses the Submit button), the name/value pairs are encapsulated in the HTTP request sent to the Web server, and eventually handed off to the servlet specified in the form.

Note

At best, this section is a simplification of the HTTP protocol as it relates to POSTs and GETs in a WebLogic Server application. For a more detailed look into the HTTP protocol, the specification is located at a number of sites on the Internet. One reliable mirror is located at ftp://ftp.isi.edu/in-notes/rfc2616.txt.

The complete listing of these standards can be located at the World Wide Web Consortium (W3C) Web site at http://www.W3C.org. Other methods that are part of the servlet specification for HttpServlet include:

  • doPut, for HTTP PUT requests.

  • doDelete, for HTTP DELETE requests.

More information on each of these methods, which are not commonly used, can be found in the API documentation for servlets. Currently, this API documentation is located on the JavaSoft Web site at http://java.sun.com/products/servlet/2.2/javadoc/index.html.


POSTs on the Form Side

The first step in building a Web form is to code the HTML. The following is a very basic HTML page for a Web form:

<html>
<body bgcolor=#FFFFFF>
<h1>
My Form!
</h1>

<p>
<font face="Helvetica">
<form method="post" action="formServlet">
  <table border="0" bgcolor=#eeeeee align=center cellspacing=10>
    <tr>
      <td>Username:</td>
      <td>
        <input type="TEXT" name="username">
      </td>
    </tr>
    <tr>
      <td>Your age:</td>
      <td>
        <input type="TEXT" name="age">
      </td>
    </tr>
  </table>
  <p>
  <center>
    <input type="SUBMIT" name="submit" value="Submit">
  </center>
</form>
</font>
</body>
</html>

In a Web browser, this page might look like the Web input form in Figure 3-10.

Figure 3-10. Web Input Form


The form has two fields, Username and Your Age. When the user completes the form and presses Submit, a POST of the data is sent to WebLogic Server. WebLogic Server encapsulates that request in an instance of the HttpServletRequest object.

The next step is to write a method called doPost() into the servlet that handles the POST. As specified by the HTML form, the servlet that handles the POST is called formServlet.

POSTs on the Servlet Side

When a POST is received, WebLogic Server calls the doPost() method in the servlet. The method signature looks like the following:

public void doPost(HttpServletRequest req, HttpServletResponse
res)
       throws IOException, ServletException

This is very similar to the service() method and is used in much the same way. The first step is to create an Enumeration of all the names of the parameters specified in the request using the getParameterNames() method available as part of the HttpServletRequest object:

Enumeration ParamNames = req.getParameterNames();

Then, that Enumeration can be traversed to look at each individual name/value pair:

while(ParamNames.hasMoreElements()){

      // Get the next name.
      String ParamString = (String)ParamNames.nextElement();

      // Print out the current name's value:
      pw.println("<b>" + ParamString + ":</b> " +
                 req.getParameterValues(ParamString)[0]);
      pw.println("<P>");

     }
}

The getParameterValues() method returns an array of string objects containing the values of the given request name, or null if the parameter does not exist. This method is useful in situations in which a given parameter is POSTed with more than one value for a given name. In this simple case, we only need to look at the first value in the array at index 0.

All name/value pairs are encoded as strings. So, for example, if you are attempting to receive a dollar amount or a phone number, the return type out of the getParameterValues method always will be a string, which you must be sure to parse appropriately.

You can also access each parameter value directly by explicitly asking for it by name:

req.getParameter("name");

This returns the value of a request parameter called "name" as a String, or null if the parameter does not exist. You should only use this method when you are sure the parameter has only one value. If the parameter might have more than one value, you would use getParameterValues(java.lang.String. A complete doPost() method for this form is included later in this section.

Note

Handling secure logins is slightly different from standard Web forms. Forms for secure logins are covered in Chapter 4, Using WebLogic Server JavaServer Pages.


Handling GETs and POSTs Together

Servlets can handle both GET and POST inside a single class. You can treat the doGet and doPost methods just as you treated the service() method in previous examples.

A simple servlet with a doGet method might look like the following:

// Import Classes and Declare Servlet Class
import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class viewRequestServlet extends HttpServlet {

    // Define Method to Handle GETs
   public void doGet(HttpServletRequest req, HttpServletResponse
res)
           throws ServletException, IOException
    {

      /* Set the appropriate return content type,
         and compose the HTML page: */
      res.setContentType("text/html");
      PrintWriterout = res.getWriter();

      out.println("<html>");
      out.println("<head><title>doGet Servlet</title></head>");
      out.println("<body></body></html>");
    }
}

The output of the servlet should be a simple HTML page with no content.

Extending the Servlet

We can now put together a single servlet to handle both the initial GET from a user and the subsequent POST. This simply involves creating a servlet with both the doGet() and doPost() methods. First, we need to import the necessary classes and declare our servlet class:

package com.learnweblogic.examples.ch3;

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

public class formServlet extends HttpServlet{

  /*  The doGet method handles the initial invocation of
      the servlet.  The default service() method recognizes
      that it has received a GET and calls this method
      appropriately. It responds with a form that uses
      the POST method to submit data.
  */
  public void doGet(HttpServletRequest req, HttpServletResponse
res)
    throws IOException, ServletException
  {
    res.setContentType("text/html");
    res.setHeader("Pragma", "no-cache");

    PrintWriter   out = res.getWriter();

    out.println("<html>");
    out.println("<body bgcolor=#FFFFFF>");
    out.println("<h1>");
    out.println("My Form!");
    out.println("</h1>");
    out.println("<font face=Helvetica>");
    out.println("<form method=post action=FormServlet>");
    out.println("<table border=0 bgcolor=#eeeeee cellspac-
ing=10>");
    out.println("<tr>");
    out.println("<td>Username:</td>");
    out.println("<td>");
    out.println("<input type=TEXT name=username>");
    out.println("</td>");
    out.println("</tr>");
    out.println("<tr>");
    out.println("<td>Your age:</td>");
    out.println("<td>");
    out.println("<input type=TEXT name=age>");
    out.println("</td>");
    out.println("</tr>");
    out.println("</table>");
    out.println("<p>");
    out.println("<center>");
    out.println("<input type=SUBMIT name=submit value=Submit>");
    out.println("</center>");
    out.println("</form>");
    out.println("</font>");
    out.println("</body>");
    out.println("</html>");
  }

  /* Finally, include a separate doPost() method to be called
     when the user responds by clicking on the submit button: */

  /*
    Responds to the "POST" query from the
    original form supplied by the doGet() method.
  */
  public void doPost(HttpServletRequest req, HttpServletResponse
res)
    throws IOException, ServletException
  {

    // Set the content type of the response.
    res.setContentType("text/html");
    res.setHeader("Pragma", "no-cache");

    PrintWriter pw = res.getWriter();

    pw.println("<HTML><HEAD><TITLE>Form Completed</TITLE></
HEAD>");
    pw.println("<BODY>The information you have" +
      " submitted is as follows:");
    pw.println("<P>");

    // Loop through all the name/value pairs.
    Enumeration ParamNames = req.getParameterNames();

    // Loop through all the name/value pairs.
    while(ParamNames.hasMoreElements()) {

      // Get the next name.
      String ParamString = (String)ParamNames.nextElement();

      // Print out the current name's value:
      pw.println("<b>" + ParamString + ":</b> " +
        req.getParameterValues(ParamString)[0]);
      pw.println("<P>");
    }
    pw.println("</BODY></HTML>");
  }
}

Figure 3-11 shows what the first screen for the user might look like.

Figure 3-11. The User's First Screen


The completed form after the POST is shown in Figure 3-12.

Figure 3-12. After the POST


Why is the input type defined in the HTML page posted as one of the HTML POST parameters? This is to support pages that may have multiple different submit buttons, each with a different name and value. Your servlet can look at the value of the submit parameter to see which button was pressed and handle the POST appropriately.

Deploying the Form Servlet in WebLogic Server

Use the code included on the CD accompanying this book to deploy the form servlet. The Web application archive is located in the file /examples/ch3/formServlet.war. Use the process described for the Hello Servlet example as your guide.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.181.47