JSP Debugging (in Tomcat)
How to debug servlets and JSP
Kay Streubel
Aprimus GmbH, Hamburg
kay.streubel@aprimus.de
Motivation
Developing applications using Java servlet and JSP
technologies is a complex task. Being able to use a debugger
helps in finding error situations which might be hard to
track down using "out.println" debugging and simple
logging.
Java comes in here with the JPDA (Java Platform Debugger
Architecture) which allows local and remote debugging of
objects and classes running in the Java Virtual Machine.
This document describes the configuration steps to set up
the Tomcat servlet container and Java debugging tools.
Prerequisites
You should have a functional Java development environment
and access to a server running Apache Tomcat. The following
steps have been tested with Sun's JDK 1.4.0 and Tomcat
4.0.3 running on Windows 2000 Professional.
General Setup
Tomcat is installed in %CATALINA_HOME% , JDK
in %JAVA_HOME% .
- Add this line to OS server and
client environment:
set CATALINA_OPTS=-server -Xdebug
-Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
These options turn on remote debugging on port 8000 for
the JVM Tomcat is running.
-
If you are starting Tomcat via
jk_nt_service.exe : add these lines to the
file
%CATALINA_HOME%\conf\jk\wrapper.properties :
# add this for remote debugging
# wrapper.remotedebug=%CATALINA_OPTS%
wrapper.remotedebug=-server -Xdebug -Xnoagent \
-Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,\
server=y,suspend=n,address=8000
# replace the wrapper.cmd_line entry:
# wrapper.cmd_line=$(wrapper.javabin) -Xrs \
-Djava.security.policy=="$(wrapper.tomcat_policy)" \
-Dtomcat.home="$(wrapper.tomcat_home)" \
-classpath $(wrapper.class_path) $(wrapper.startup_class) \
-config $(wrapper.server_xml) start
# debug version
wrapper.cmd_line=$(wrapper.javabin) $(wrapper.remotedebug) \
-Xrs -Djava.security.policy=="$(wrapper.tomcat_policy)" \
-Dtomcat.home="$(wrapper.tomcat_home)" -classpath \
$(wrapper.class_path) $(wrapper.startup_class) -config \
$(wrapper.server_xml) start
-
Be sure to compile servlet classes
with the "javac -g" option. Change the Tomcat
configuration to make sure JSPs are compiled with
"-g": set classdebuginfo and mappedfile entries
in
%CATALINA_HOME%\conf\web.xml for JSP
servlet.
Example:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<init-param>
<param-name>classpath</param-name>
<param-value>$CATALINA_HOME/common/classes</param-value>
</init-param>
<init-param>
<param-name>classdebuginfo</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>mappedfile</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
-
Start Tomcat by one of the
following:
- starting
%CATALINA_HOME%\bin\catalina.bat jpda start
- running
jk_nt_service
-
Start JDK debugger by one of the
following:
jdb -attach jdbconn
(for shared memory access, Tomcat started via
catalina.bat)
jdb -connect
com.sun.jdi.SocketAttach:hostname=localhost,port=8000
(for socket connection, Tomcat started via
jk_nt_service)
- Invoke servlet page and switch to
the debugger.
-
Enter debugger commands, such as the
examples shown below.
use c:\sourcepath
stop at MyServletClass.doGet
cont
list
next
locals
dump MyServletClass
eval MyServletClass.toString()
eval MyServletClass.aMethod()
Using JSwat to debug servlets and JSP
To use the JSwat graphical debugger to debug servlets and
JSP, you have to make sure that JSwat is able to locate the
source files for the servlet and JSP classes being debugged.
Usually, you set the source file path in JSwat. For servlets
this is easy, you just give the development path containing
the servlet source.
With JSPs, the situation becomes slightly more
complicated. When you invoke a JSP for the first time, Tomcat
takes the JSP code and compiles it into a servlet. The source
code and class file are stored in
%CATALINA_HOME%\work\localhost\<webapp>\jsp .
If you look at this directory, you will find files named
<jspname>$jsp.java and
<jspname>$jsp.class . If you look at the
generated source files, you will find that the JSP compiler
puts all the classes into the package
"org.apache.jsp".
Unfortunately, if you tell JSwat to use this directory as
a sourcepath, it will not be able to find the files. Do not
despair. I will show you how to convince it to show the
source code for the debugged JSP classes.
To use JSwat 2.4 for JSP debugging create a directory with
sub-directories org\apache\jsp in it
(mkdir
<...>\java\jspdebug\org\apache\jsp ). This is
where the source files will go. Copy the generated source
files from the Tomcat JSP work directory to your newly
created path (copy
%CATALINA_HOME%\work\localhost\<webapp>\jsp\<jspname>$jsp.java
<...>\java\jspdebug\org\apache\jsp ).
You will have to invoke the JSP pages first if the source
directory is still empty or your JSP does not show up yet. It
might be a good idea to clean up before you start your
debugging session to ensure the JSP servlets are created
again with debugging information inside.
Start JSwat and add the sourcepath. Select "Options /
Set Sourcepath..." from the menu and add path element
"<...>\java\jspdebug" (without the org\...
sub-directories). Now JSwat will be able to locate the source
files for the generated JSP classes.
Connect JSwat to the Tomcat JVM. Select "Session /
Attach to Remote..." from the menu bar and connect using
the appropriate method (see above).
Double-clicking the class name from the Classes panel will
not work directly, just start to debug. Set a breakpoint in
the servlet source file belonging to your project and step on
until you reach the JSP code. As soon as JSwat enters the
generated JSP code, it will show in the source window! If you
select the class entry from the Classes panel now, it will be
displayed correctly later in this session.
Conclusion
The steps outlined here show that debugging servlets and
JSP with freely available tools is possible. It might be
possible that this will work with other servlet containers as
well, as long as they produce source and class files for
generated JSP code and put them into a publicly accessible
directory. The process of name resolution in the class loader
might differ, but even this could be figured out using the
remote debugging facilities.
I have suggested to the JSwat developers to make this
configurable in future releases. Until then, this document
might help developers trying to cope with the mysteries of
servlet and JSP debugging.
Correction and further suggestions are welcome, please
send any comments to the email address stated above.
|