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 7 Continued: Servlet Debugging

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

You can debug servlets with the same jdb commands you use to debug an applet or an application. The JavaTM Servlet Development Kit (JSDK) provides a standalone program called servletrunner that lets you run a servlet without a web browser. On most systems, this program simply runs the java sun.servlet.http.HttpServer command. You can, therefore, start a jdb session with the HttpServer class.

A key point to remember when debugging servlets is that Java Web server and servletrunner achieve servlet loading and unloading by not including the servlets directory on the CLASSPATH. This means the servlets are loaded using a custom classloader and not the default system classloader.


Running servletrunner in Debug Mode

In this example, the servlets examples directory is included on the CLASSPATH. You can configure the CLASSPATH for debug mode as follows:
Unix

$ export CLASSPATH=./lib/jsdk.jar:./examples:$CLASSPATH  

Windows

$ set CLASSPATH=lib\jsdk.jar;examples;%classpath%
To start the servletrunner program you can either run the supplied startup script called servletrunner or just supply the servletrunner classes as a parameter to jdb. This example uses the parameter to servletrunner.
$ jdb sun.servlet.http.HttpServer
Initializing jdb...
0xee2fa2f8:class(sun.servlet.http.HttpServer)
> stop in SnoopServlet.doGet
Breakpoint set in SnoopServlet.doGet
> run
run sun.servlet.http.HttpServer
running ...
main[1] servletrunner starting with settings:
port = 8080
backlog = 50
max handlers = 100
timeout = 5000
servlet dir = ./examples
document dir = ./examples
servlet propfile = ./examples/servlet.properties

To run SnoopServlet in debug mode, enter the following URL in a browser where yourmachine is the machine where you started servlet runner and 8080 is the port number displayed in the settings output.

http://yourmachine:8080/servlet/SnoopServlet

In this example jdb stops at the first line of the servlet's doGet method. The browser will wait for a response from your servlet until a timeout is reached.

main[1] SnoopServlet: init

Breakpoint hit: SnoopServlet.doGet (SnoopServlet:45)
Thread-105[1] 
We can use the list command to work out where jdb has stopped in the source.

Thread-105[1] list
41        throws ServletException, IOException
42        {
43      PrintWriter     out;
44    
45 =>   res.setContentType("text/html");
46      out = res.getWriter ();
47    
48      out.println("<html>");
49      out.println("<head>
                     <title>Snoop Servlet
                     </title></head>");
Thread-105[1] 
The servlet can continue using the cont command.
Thread-105[1] cont

Running Java Web Server in Debug Mode

The JSDK release does not contain classes available in the Java Web server and it also has its own special servlet configuration. If you cannot run your servlet from servletrunner, then the other option is to run the Java Web server in debug mode.

To do this add the -debug flag for the first parameter after the java program. For example in the script bin/js change the JAVA line to look like the following. In releases prior to the Java 2 platform release, you will also need to change the program pointed to by the variable $JAVA to java_g instead of java.

Before:

exec $JAVA $THREADS $JITCOMPILER $COMPILER $MS $MX \

After:

exec $JAVA -debug $THREADS $JITCOMPILER 
                                  $COMPILER $MS $MX \

Here is how to remotely connect to the Java Web Server. The agent password is generated on the standard output from the Java Web Server so it can be redirected into a file somewhere. You can find out where by checking the Java Web Server startup scripts.

jdb -host localhost -password <the agent password>
The servlets are loaded by a separate classloader if they are contained in the servlets directory, which is not on the CLASSPATH used when starting the Java Web server. Unfortunately, when debugging remotely with jdb, you cannot control the custom classloader and request it to load the servlet, so you have to either include the servlets directory on the CLASSPATH for debugging or load the servlet by requesting it through a web browser and then placing a breakpoint once the servlet has run.

In this next example, the jdc.WebServer.PasswordServlet is included on the CLASSPATH when Java Web server starts. The example sets a breakpoint to stop in the service method of this servlet, which is the main processing method of this servlet.

The Java Web Server standard output produces this message, which lets you proceed with the remote jdb session:

Agent password=3yg23k
$ jdb -host localhost -password 3yg23k
Initializing jdb...
> stop in jdc.WebServer.PasswordServlet:service
Breakpoint set in jdc.WebServer.PasswordServlet.service
> stop
Current breakpoints set:
        jdc.WebServer.PasswordServlet:111

The second stop lists the current breakpoints in this session and shows the line number where the breakpoint is set. You can now call the servlet through your HTML page. In this example, the servlet is run as a POST operation

<FORM METHOD="post" action="/servlet/PasswordServlet">
<INPUT TYPE=TEXT SIZE=15 Name="user" Value="">
<INPUT TYPE=SUBMIT Name="Submit" Value="Submit">
</FORM>

You get control of the Java Web Server thread when the breakpoint is reached, and you can continue debugging using the same techniques as used in the Remote Debugging section.


Breakpoint hit: jdc.WebServer.PasswordServlet.service 
(PasswordServlet:111) webpageservice Handler[1] where
[1] jdc.WebServer.PasswordServlet.service 
                               (PasswordServlet:111)
[2] javax.servlet.http.HttpServlet.service 
                               (HttpServlet:588)
[3] com.sun.server.ServletState.callService 
                               (ServletState:204)
[4] com.sun.server.ServletManager.callServletService 
                               (ServletManager:940)
[5] com.sun.server.http.InvokerServlet.service 
                               (InvokerServlet:101)

A common problem when using the Java WebServer and other servlet environments is that Exceptions are thrown but are caught and handled outside the scope of your servlet. The catch command allows you to trap all these exceptions.

webpageservice Handler[1] catch java.io.IOException
webpageservice Handler[1] 
Exception: java.io.FileNotFoundException        
 at com.sun.server.http.FileServlet.sendResponse(
                                FileServlet.java:153)
 at com.sun.server.http.FileServlet.service(
                                FileServlet.java:114)
 at com.sun.server.webserver.FileServlet.service(
                                FileServlet.java:202)
 at javax.servlet.http.HttpServlet.service(
                                HttpServlet.java:588)
 at com.sun.server.ServletManager.callServletService(
			        ServletManager.java:936)
 at com.sun.server.webserver.HttpServiceHandler
           .handleRequest(HttpServiceHandler.java:416)
 at com.sun.server.webserver.HttpServiceHandler
           .handleRequest(HttpServiceHandler.java:246)
 at com.sun.server.HandlerThread.run(
                                HandlerThread.java:154)

This simple example was generated when the file was not found, but this technique can be used for problems with posted data. Remember to use cont to allow the web server to proceed. To clear this trap use the ignore command.

webpageservice Handler[1] ignore java.io.IOException
webpageservice Handler[1] catch
webpageservice Handler[1] 

[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.