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]
|