cattails

Blue Marsh Softworks

 Site Index
 o java projects
 o about me
 o search

 My Java
 o java tips
 o java faq
 o contributing
 General Java
 o JavaSoft
 o Developer Connection
 o The Java FAQ
 o Java Glossary

 JSwat
 o download
 o documentation
 o faq
 o mail lists
 o contributing
 o bugs
 Related Software
 o JPDA
 o Emacs JDEE
 o JDBTool
 o jEdit plugin
 o Jenus
 o NetBeans
 Related Links
 o Top Ten Reasons Not to Use a Java Debugger in School

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

  1. 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.
  2. 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
    
  3. 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>
    
  4. Start Tomcat by one of the following:
    • starting %CATALINA_HOME%\bin\catalina.bat jpda start
    • running jk_nt_service
  5. 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)
  6. Invoke servlet page and switch to the debugger.
  7. 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.

© Copyright 2000-2002 - Blue Marsh Softworks