Un punto importante a recordar cuando depuramos servlets es que el servidor Web Java y servletrunner realizan la carga y descargas de servlets, pero no incluyen el directorio servlets en el CLASSPATH. Esto significa que los servlets se cargan usando un cargador de clases personalizado y no por el cargador de clases por defecto del sistema.
Para arrancar el programa servletrunner, podemos ejecutar el script de arranque suministrado llamado servletrunner o simplemente suministramos las clases servletrunner como parámetros de jdb. Este ejemplo usa el parámetro servletrunner.Unix $ export CLASSPATH=./lib/jsdk.jar:./examples:$CLASSPATH Windows $ set CLASSPATH=lib\jsdk.jar;examples;%classpath%
Para ejecutar SnoopServlet en modo depuración, introducimos la siguiente URL donde yourmachine es la máquina donde arrancamos el servletrunner y 8080 es el número d puerto mostrado en las selecciones de salida.$ 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
En este ejemplo jdb para en la primera línea del método doGet del servlet. El navegador espera una respuesta de nuestro servlet hasta que se pase el timeout.http://yourmachine:8080/servlet/SnoopServlet
Podemo usar el comando list para saber dónde se ha parado jdb en el fuente.main[1] SnoopServlet: init Breakpoint hit: SnoopServlet.doGet (SnoopServlet:45) Thread-105[1]
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]
El servlet puede continuar usando el comando cont.
Thread-105[1] cont
Para hacer esto añadimos la bandera -debug como el primer parámetro después del programa java. Por ejemplo en el script bin/js cambiamos la línea Java para que se parezca a esto. En versiones anteriores de la plataforma java 2, también tendremos que cambiar el puntero del programa a la variable $JAVA a java_g en vez de a java.
Antes:
exec $JAVA $THREADS $JITCOMPILER $COMPILER $MS $MX \
Depués:
exec $JAVA -debug $THREADS $JITCOMPILER
$COMPILER $MS $MX \
Aquí está como conectar remotamente con el Java Web Server. La password de agente es generada sobre la slaida estandard desde el Java Web Server pero puede ser redirigida a un fichero en cualquier lugar. Podemos encontrar dónde chequeando los scripts de arranque del Java Web Server.
Los servlets se cargan por un cargador de clases separado si están contenidos en el directorio servlets, que no está en el CLASSPATH usado cuando se arrancó el Java Web server. Desafortunadamente, cuando depuramos en modo remoto con jdb, no podemos controlar el cargador de clases personalizado y solicitarle que cargue el servlet, por eso tenemos que incluir el directorio servlets en el CLASSPATH para depurar o cargar el servlet requiriéndolo a través de un navegador y luego situando un punto de ruptura una vez que el servlet está ejecutando.jdb -host localhost -password <the agent password>
En este siguiente ejemplo, se incluye el jdc.WebServer.PasswordServlet en el CLASSPATH cuando se arranca el Java Web server. El ejemplo selecciona un punto de ruptura para parar el método service de este servlet, que es el método de proceso principal.
La salida estándard del Java Web Server standard produce este mensaje, que nos permite seguir con la sesión remota de jdb:
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
El segundo stop lista los puntos de ruptura actuales en esta sesión y muestra el número de línea donde se encuentan. Ahora podemos llamar al servlet a través de nuestra página HTML. En este ejemplo, el servlet está ejecutando una operación POST:
Obtenemos el control del thread del Java Web Server cuando se alcanza el punto de ruptura, y podemos continuar depurando usando las mismas técnicas que se usarón en la sección Depuración Remota.<FORM METHOD="post" action="/servlet/PasswordServlet"> <INPUT TYPE=TEXT SIZE=15 Name="user" Value=""> <INPUT TYPE=SUBMIT Name="Submit" Value="Submit"> </FORM>
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)
Un problema común cuando se usan el Java WebServer y otros entornos de servlets es que se lanzan excepiones pero son capturadas y manejadas desde fuera del ámbito del servlet. El comando catch nos permite atrapar todas estas excepciones.
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)
Este sencillo ejemplo fue generado cuando los ficheros no se encontraban pero esta técnica puede usarse para problemas con datos posteados. Recordamos usar cont para permitir que el servidor web continúe. Para limpiar está trampa usamos el comando ignore.
webpageservice Handler[1] ignore java.io.IOException webpageservice Handler[1] catch webpageservice Handler[1]