IBM Distributed Debugger enables you to debug JavaTM code, set breakpoints, stop on caught exceptions, and step through a program statement-by-statement. The previous articles in this series described how to obtain and install the Debugger, and how to use it to debug an application. This article focuses on the scenario where the Java code you want to debug is running inside WebSphere® Application Server as a servlet, EJB, or JSPTM. The article focuses on IBM Distributed Debugger 9.1 and WebSphere Application Server 4.0, both Advanced Edition (AE) and Advanced Single-Server Edition (AEs).
You can debug a Java program running inside WebSphere Application Server in two ways:
- Configure WebSphere Application Server to start its JVM as a debuggee that the Debugger can locate and attach to
- Use the Object Level Trace (OLT) utility.
Starting WebSphere Application Server AEs as a debuggee
To start WebSphere Application Server AEs in debug mode,
modify the arguments to the startServer program. The argument -debugEnable
is used to start the JVM in JPDA debug mode using a socket connector, and the
argument -jdwpPort is used to specify the port
number. This is shown in Figure 1 below, which tells WebSphere Application Server
to start the JVM as a debuggee that listens on port 3001 for the Debugger to
attach. For more information on JPDA and socket connectors, see my previous
article Remote
Debugging: Using the IBM Distributed Debugger and JDB.
Figure 1. The startServer command can start the server in debug mode and tell it which port the debuggee will listen to.
When startserver is run, it uses a configuration file, by
default server-cfg.xml, that contains details about the server
to be started. You can modify information about debugging, such as whether debug
should be enabled, by changing the configuration file directly rather than specifying
the -debugEnable argument each time you run startserver. To see
how to do this using the Administrative Console, see the OLT
tool section.
For AE, you must use the Administrative Console to configure the server for debug. Before starting the Administrative Console, start the Administrative Server must. AE is more complex to install and configure than AEs and there are a number of issues that may prevent the Administrative Server from starting correctly. To troubleshoot problems starting the Administrative Server, use the Problem Determination section in the WebSphere Information Center.
Once you've started the Administrative Server, launch the Administrative Console either by selecting Start => Administrator's Console, or by selecting Start the Administrative Console on the First Steps dialog. From the Console, expand to the server you want to debug as shown in Figure 2 below.
Figure 2. Use the administrative server to set the socket for a remote debugger to attach to.
On the server that you want to configure for debugging, select the JVM Settings tab and select Advanced JVM Settings. This brings up the dialog shown in Figure 3 below.
Figure 3. The Advanced JVM Settings let you specify the arguments for remote debugging.
When you select Enable debug mode, it adds the arguments
-Xdebug and -Xnoagent to the command line of the Java
command used by WebSphere Application Server. To specify more arguments, such
as the port number the Debugger uses to attach the debuggee, enter -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=nnnn
where nnnn is the socket number. Figure 2 above shows that after you close the
dialog, you can see the full set of command-line arguments. After modifying
the JVM arguments, you must stop the server and start it again for them to take
effect. You can do this by selecting Stop on the pop-up menu against
the server, and restart it by selecting Start. Do not select Enable
IBM distributed Debugger -- this is used only when the Debugger is used
with the OLT tool.
Attaching the Distributed Debugger to WebSphere Application Server
The previous sections showed how to configure WebSphere Application Server AE and AEs so that it begins its JVM in debug mode with a socket connector that allows a debugger to attach at Port 3001. We will now show you how to use the Distributed Debugger to attach to the WebSphere Application Server JVM and debug a servlet, EJB, and JSP. To do this, we will use the HitCount example provided with the examples package of both AE and AEs.
To start the Distributed Debugger, open a command prompt and
change to the directory where the Debugger is located -- usually C:\IBMDebug\bin.
Ensure that the java.exe located in the JDK
bin directory is the first occurrence of java.exe
in the path; otherwise the Distributed Debugger will not be able to locate the
necessary JDK classes required for debugging. You can do this by changing the
system path or the session path, as shown in Figure 4 below.
Figure 4. The bin directory of a JDK must be the first occurrence of java.exe in the path.
Do your debugging from the machine on which you start the Distributed Debugger. In Figure 4 above, the JDK that comes with WebSphere was used, although if you are doing remote debugging where WebSphere Application Server is not installed on the machine with the Debugger, make sure that the JDK levels of WebSphere Application Server and the machine with the Debugger user interface are the same. The command java -version will show you the JDK level.
To launch the Debugger so that it automatically opens ready
to attach to a debugger, use the -a option as shown in Figure 4 above. This
will bring up the attach dialog shown in Figure 5 below. If the Distributed
Debugger does not open on the Interpreted notebook page, it is because you have
not previously used it to debug a Java program. The Debugger remembers details
of your last debug session in your profile in the DbgProf directory, and if
there is no such history the attach dialog will open on the Compiled Page. To
force the Interpreted page to open, use the option idebug -qlang=Java
-a. On the attach dialog, enter the name of the machine where WebSphere
Application Server is running, in this case JoeWin.raleigh.ibm.com, and the
port number used as the argument to jdwp socket protocol, namely 3001. Instead
of using the machine name, you can use the numeric IP address. For more information
on using the Distributed Debugger for remote debugging, see the
previous
article in this series.
Figure 5. Enter the name or IP address of the machine running WebSphere Application Server and the port number used as the -jdwpPort argument to startServer.
After clicking Attach on the dialog shown in Figure 5 above, the Distributed Debugger tries to locate a debuggee on the machine name specified in the JVM host field that is listening for a JDWP socket connection on port 3001. While the Debugger is locating the JVM and attaching to it, a progress dialog will display, and when the Debugger has successfully attached, the stack frame of the WebSphere Application Server JVM will be shown. Be patient as it may take 30 seconds or so for the Debugger to attach.
Once the Debugger has located the WebSphere Application Server
JVM and attached to it, it will suspend the JVM and attempt to show you the
stack frame and source for the stopped location. Usually this is the wait()
method on java.lang.Object and in trying to show the source you will be prompted
for the location of the source for java.lang.Object. In most cases you can cancel
this dialog and then locate the classes you want to debug. If you do want to
use the JDK source with the Debugger, these are not shipped as part of WebSphere,
and you must obtain them from the JDK provider. Once you have obtained the source,
you will need to unzip the file src.jar and specify the location
of the /src directory in the Source Search path of the Debugger.
More information on this can be found in the previous
article. After the Debuggger has attached to the WebSphere Application Server
JVM, it will suspend the JVM, so to get WebSphere Application Server to continue,
click Run.
The HitCount application that we will debug is included in
the sampleApp.ear in the sampleapp.war
file, and it consists of a JSP that calls a servlet. To run the example, point
your browser to http://HOSTNAME/webapp/examples/HitCount, where HOSTNAME
is the name or IP address of the machine where WebSphere Application Server
is running. For this article, WebSphere Application Server is on the same machine
as the Debugger, so this was localhost. In the HitCount example, different calls
are made to increment a hit counter using a servlet or EJB depending on the
value of the radio buttons selected on the initial page. See Figure 6 below.
Figure 6. The HitCount JSP page runs a servlet that counts the number of visits to the Web site.
To begin with, we will add a breakpoint to the HitCount servlet
class. Use the list of loaded packages to find the class. The HitCount.java
file does not have a package specified in its source so it is part of the default
package, as shown in Figure 7 below.
Figure 7. The HitCount servlet is loaded in the default package.
After selecting the HitCount class, the Debugger tries to
load the source. Rather than specify the source for the individual Java file
on the Source Not Found dialog, it is better to cancel this dialog and change
the path that the Debugger uses to locate source by selecting Source => Source
Search Path. Figure 8 below shows the location of the directory containing
the HitCount.java file entered in the Source
Search Path. Besides specifying the source path in the Debugger source search
path, you can use the -debugSource argument
to the startServer command in AEs. System-wide, you can change the source path
that the Debugger uses by default via the DER_DBG_PATH environment variable.
The Administrative Consoles of AE and AEs let you specify debug source paths,
but these only take effect when using OLT.
Figure 8. Location of the directory containing the HitCount.java file.
After clicking Cancel on the HitCount source not found
dialog and then modifying the Source Search Path, you will need to get the Debugger
to refresh itself to display the source. You can do this by selecting Source
=> Change Text File => OK. The Debugger will then attempt to load HitCount.java
from its current, and modified, source search path, and the source should appear
as shown in Figure 7 above which shows that a breakpoint has been added at line
94, the first executable statement of the servlet's service(HttpServletRequest,
HttpServletResponds) method. Click Run to get the WebSphere Application
Server JVM to continue, after which the Debugger will become suspended once
more.
After clicking Increment, the servlet will be called and the breakpoint should be reached. The Debugger will become enabled and line 94 will be highlighted. From here you can step through the source, inspect variables, set exceptions to be caught, and add new breakpoints to help understand the program execution. Clicking Run will let the servlet continue execution and the Debugger become inactive once more. At any point when WebSphere Application Server is running, you can stop it by clicking Halt, which will suspend the WebSphere Application Server JVM and let you debug it once more. While the WebSphere Application Server JVM has been suspended, the Web browser may timeout because it doesn't get a response from the server after a set time and assumes the Web site is unavailable. For details on how to change timeout settings for different browsers, see the WebSphere Application Server InfoCenter.
In order to insert a breakpoint in the HitCount servlet, we had to find the program in the list of loaded packages, in this case in the package. If the WebSphere Application Server JVM has not already loaded the class that you want to debug, it will not be shown in the list. To add a breakpoint to a program that has not been loaded, use the Set Line or Set Method options from the Breakpoints menu. On these dialogs, select Deferred Breakpoint as shown in Figure 9 below and when the class is first loaded by the JVM being debugged, the breakpoint will be added.
Figure 9. If the class has not yet been loaded by the WebSphere Application Server JVM, then breakpoints must be added as deferred.
When you add a line breakpoint, the source is usually optional.
However, once you specify that the breakpoint is deferred, you must enter the
source, as shown in Figure 9 above. The HitCount class is in the default package,
so enter its source file as HitCount.java. However;
if the class is in a package, then enter the qualified source file, such as
com\ibm\examples\HitCount.java if HitCount is
in the package com.ibm.examples . If you don't enter the source, you will not
get an error, but the breakpoint will not be added. If you don't know the source
line, but want the Debugger to stop when a method is reached, then you can create
a deferred method breakpoint. All you need to do is enter the package name,
class name, and method signature. The Distributed Debugger is very clever here,
because you don't need to fully qualify the method signature to be used. For
example, the full method signature for the service method is
service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) |
However, if you just enter service as the method name with no arguments, then you get method breakpoints for all methods that match that name. This is very useful because it means you don't have to fully qualify hard-to-remember method names.
The HitCount example includes a number of different Java class
types, a servlet, an EJB, and a JSP. The EJB can be debugged just like the servlet.
For example, if you select the radio button option to use an EJB on the HitCount
page, the EJB com.ibm.WebSphere.examples.Inc.IncBean is used to retrieve the
value. You can navigate to this class from the list of packages, expand its
methods, and add a breakpoint on the getValue()
method. WebSphere does not ship the source for the IncBean, but even without
the source you can still add method breakpoints. For complex multi-tiered scenarios
where the servlet and JSPs are on a different WebSphere Application Server from
the EJBs, you'll need to use OLT to perform synchronous debugging across different
servers. Attaching the Distributed Debugger to a JPDA debuggee through a socket
can only be used to debug a single JVM.
Debugging a JSP is a bit different because, while JSP pages
execute at run time as servlets, their source is the Java file
for the servlet. A JSP source file is a mixture of the HTML and the Java that
are combined by the WebSphere Application Server page compiler to create the
servlet source. Figure 7 above shows that in the list of loaded classes, the
HitCount JSP exists as HitCount_jsp_0 -- the name of the servlet
that the HitCount.jsp was precompiled into. The problem that JSP
precompilation presents is that as a developer, you're not really interested
in debugging the servlet, but instead want to debug the JSP source as you wrote
it. JPDA has a layer known as Java Virtual Machine Debug Interface (JVMDI ),
which lets execution environments such as WebSphere Application Server use one
representation of a Java class internally, while externally the Debugger user
interface works with the original source.
To see this, select the file HitCount_jsp_0
in the list of loaded classes in Figure 7 above. Rather than prompting for the
location of the servlet source, namely HitCount_jsp_0.java,
the Debugger will instead prompt for the location of the JSP file. See Figure
10 below.
Figure 10. The Debugger prompts for the JSP source file instead of the precompiled servlet.
What is occurring is that the Debugger user interface is asking
the WebSphere Application Server JVMDI for the source file for HitCount_jsp_0,
and WebSphere Application Server knows that this is a servlet that it created
from a JSP page, so it returns the name of the source file for the JSP source
page. The Distributed Debugger doesn't have the file HitCount.jsp
in its source search path, so it prompts you for it. After you enter the location
of the HitCount.jsp file, it will be opened.
Figure 11. JSP files can be opened and used in the Distributed Debugger
In Figure 11 above, the list of methods for HitCount_jsp_0
has been expanded and a breakpoint added on _jspService(HttpServletRequest,HttpServletResponds).
The source pane shows a red breakpoint marker on line 1 of the JSP, the opening
<HTML> tag. When the JSP is loaded, the Debugger will stop on this line,
and you can continue debugging the pre-compiled servlet through the JSP source.
The Step Over function lets you step through the statements line-by-line. When
you enter a scriptlet, as in line 11, you can use the Step into function to
go into a Java scriptlet method call such as the response.setHeader(String,String)
method.
In addition to using the Step function with JSPs, you can add line breakpoints by double-clicking in the margin. A request is made to the WebSphere Application Server JVMDI to add a breakpoint at the given line number, and WebSphere Application Server maps this JSP statement number to the correct servlet statement number and adds the breakpoint. If the location is not valid for a breakpoint, an error dialog will be shown.
A number of modifications and fixes were made to JSP debugging in WebSphere Application Server 4.0. Use Version 9.1.5 of the Debugger together with the GA level of AE or the PTF level of AEs.
Debugging using Object Level Trace (OLT)
Another way to debug code running inside WebSphere Application Server is through the Object Level Trace (OLT) tool. OLT provides means to visualize execution of distributed applications by generating trace diagrams of application component interactions. OLT enables tracing servlets, JSPs, EJBs and Java/C++ objects as well as client applications requesting services from those. Traced applications may be multilingual and distributed across a network as well as local to the OLT. This means that if you have a servlet on one application server that calls an EJB running inside an EJS container on a different application server, as might be found in a complex n-tiered application, the OLT GUI lets you gather the trace heuristics across and within the different servers. This lets you analyze a program as it is running in order to understand its dynamics as well as diagnose bottlenecks.
OLT has three components:
- An OLT Server that runs on a single machine and gathers trace information from the different applications.
- An OLT Engine that runs within each application to be debugged. This OLT engine must be able to locate the OLT server so that it can send trace information, and it also provides a pipe through which debugging commands can be issued.
- An OLT Viewer that is connected to the OLT server and can show you details of the trace as well as launch a debugger.
For simple scenarios, you can start the OLT Viewer and let it start the OLT Server on the same machine. WebSphere Application Server is configured so that it starts the OLT Engine that can locate the OLT server. More complex scenarios are covered in the More Complex OLT scenarios section.
To start the OLT Viewer, run the command C:\ibmdebug\olt
from a command prompt. When OLT starts, it begins the Viewer and Server at the
same time and shows the client controller page as shown in Figure 12 below.
To specify that we want the OLT Viewer to not only trace applications but also
let us debug them, set the Execution mode to Trace and debug.
Figure 12. The Client Controller page lets you specify that you want Trace and debug.
When running in trace and debug mode, the OLT Viewer lets you debug the WebSphere Application Server JVMs using the Distributed Debugger user interface. When the OLT Viewer is opened it will start the OLT server and the next step is to begin WebSphere Application Server so that it starts the its OLT Engine that connects to the OLT Server.
To start AEs with OLT enabled, to use the -oltEnable
option. If the server is already running, end it with the stopserver
command, then start it with the options -oltEnable
and, if you wish to debug as well as trace, with the -debugEnable
option. After the OLT Engine starts inside WebSphere Application
Server, it must locate the OLT Server so that it can send trace
information. To supply this information, use the argument -oltHost
to give the name of the machine running the OLT Server, and -oltPort
to give the name of the port that the OLT Server listens on. This
port number is by default 2102 and can be configured in the OLT
Viewer Preferences page. Figure 13 below shows WebSphere Application
Server started with debug enabled and the OLT Engine started and
looking to connect to an OLT Server on machine JoeWin.raleigh.ibm.com
using port 2120:
Figure 13. To start WebSphere Application Server with the OLT Engine running, use the -oltEnable option.
If you run the startserver command without specifying any
of the above options, it uses the default from a configuration XML file, server-cfg.xml.
The Administrative Console lets you browse and change the values in a configuration
using a browser GUI. Figure 14 below shows the page that lets you change the
settings for OLT and the Distributed Debugger. Note that the hostName in both
Figure 14 and Figure 13 is the name of the machine on which the OLT server is
running, not the name of the machine on which WebSphere Application Server is
running.
Figure 14. The OLT and Debugger defaults can be set on the Administrative Console.
The Source path field is applicable only when debugging through
OLT, although the Administrative Console unnecessarily makes the field mandatory
even when OLT is not enabled. If you enter an invalid source path, the server
will fail to start correctly, so you must enter a valid path even if it is just
C:\temp. When the Debugger connection to the
WebSphere Application Server VM takes place, the source path information is
passed to the Debugger and used to locate source files in conjunction with its
own source search path.
To start AE with OLT enabled you must use the Administrative Console. There are two required steps for debugging through OLT: OLT must be enabled, and debugging must be enabled. You can use the Advanced JVM settings shown in Figure 15 below. On this dialog, check Enable IBM Distributed Debugger and leave Enable debug mode unchecked. This may be confusing because it seems like you've disabled debugging. But the option Enable IBM Distributed Debugger actually means, "enable IBM Distributed Debugger to be used in configuration with OLT." When the OLT Engine executes inside WebSphere Application Server, it communicates with its OLT Server. If the OLT Server has an OLT Viewer attached to it that is configured in debug mode, it will use the OLT Engine to make a private connection to WebSphere Application Server JVM and act as a remote debug agent for the Debugger. Therefore the traditional debug settings allowing JPDA socket debugging for the JVM are not used, and the Enable Debug mode check box is deselected.
Figure 15. The Advanced JVM Settings are used to enable debugging with OLT.
On Figure 15 you can also enter the source search path used by the Distributed Debugger. Selecting Enable IBM Distributed Debugger automatically enables OLT if it is not already enabled.
To configure the settings for OLT, select the Services tab on the server in the Administrative Console as shown in Figure 16 below. This will show a list of services -- select OLT Service and edit its properties, which let you enter the OLT server host name, OLT server port, and enable or disable OLT.
Figure 16. The properties of the Object Level Trace Service let you configure and enable or disable the OLT engine.
Example of using OLT and the HitCount application
The previous two sections showed how to configure WebSphere Application Server so that when it starts the OLT engine will be running.
With the OLT Viewer started in trace and debug mode, start WebSphere Application Server, which has been configured with OLT enabled. Then run the HitCount example by opening a browser to http://localhost/HOSTNAME/examples/HitCount. The first call is to the HitCount servlet, and the OLT Viewer will open the window shown in Figure 17 below. To debug the HitCount class, select it and click OK, otherwise click Cancel.
Figure 17. At the entry to each program you can launch the Debugger.
If you select the HitCount class and click OK, the
OLT Viewer launches the Debugger and stops on the entry method, namely service(HttpRequest,HttpResponse).
If the Debugger finds the source for HitCount.java
in the path specified in the Administrative Console, then the Debugger will
open directly on the method, otherwise it will prompt for the source location.
To continue the application, click Run and the next program call will
appear in the Methods breakpoints dialog on the OLT Viewer. This is the call
to the servlet created by the HitCount.jsp page.
After the Debugger has stopped and you've finished inspecting the program or
stepping through code, click Run to continue the WebSphere Application
Server application. If you don't want to continue debugging within WebSphere
Application Server, click Detach.
After completing a debug scenario using OLT, the Viewer shows you a history of the session being traced. Figure 18 below shows this history with the calls between the HitCount servlet and the JSP page. It is like an event trace diagram turned on its side, with the classes as rows and each column as a call between programs. Even without debug mode, when just trace only is used with the OLT Viewer, seeing a graphical picture of program calls within WebSphere Application Server is a huge help in understanding the dynamics of the application you want to debug, and the OLT Viewer is a very useful analysis tool.
Figure 18. The OLT shows an event trace diagram of the objects and their calls.
In the section above the OLT viewer was started and WebSphere Application Server configured so that its OLT engine connected to the viewer's machine for its oltHostName. What actually occurred is that an OLT server was started automatically by the OLT viewer and it was this that the OLT engine communicated to. To see this open the Preferences window on the OLT viewer from the File menu of the OLT viewer configuration settings dialog shown in Figure 12 above. This opens a browser preferences dialog that shows the OLT server host name which by default is localhost, as well as the OLT server port number which is 2102. When the server host name is localhost the OLT viewer automatically starts the OLT viewer when it is launched. The port number 2102 on the OLT viewer browser preferences is the port on the machine running the OLT server that the WAS runtime engines will use to communicate to it.
Rather than have the OLT viewer start the OLT server It is
possible that you wish to have the OLT server running stand alone on its own
dedicated machine and then remotely connect an OLT viewer to this machine. If
you do want to do this you should change the host name on the OLT viewer browser
preferences to the machine that the OLT server will be started on and then exit
the OLT viewer. On the machine that is running the OLT server use the command
oltsrv -standalone and then start the OLT viewer.
This will locate the OLT server and connect to it.
The OLT Viewer client controller dialog in Figure 12 shows
the debugger hostname and port name. If these are the same as the machine on
which the OLT viewer is running then the OLT viewer will start the IBM Distributed
Debugger. If you want to run the debugger user interface on another machine
you should start the debugger daemon manually on that machine manually using
the command idebug -qdaemon -quiport=nnnn, and
then specify this machine name and the nnnn port number on the client controller
page.
This article has covered how to debug Java code such as servlets, EJBs, or JSPs running inside WebSphere Application Server. It covered both AE and AEs, and the Debugger was attached either directly to WebSphere Application Server or indirectly through OLT. In addition to including IBM Distributed Debugger and OLT, WebSphere 4.0 introduces the new WebSphere Studio Application Developer tool suite, which integrates IBM development tools and run times even more closely. A future article will show you how to perform debugging and trace viewing with WebSphere Studio Application Developer. We hope you've found this article useful, and we welcome all feedback.





