Tips for Debugging ADF Applications Using JDeveloper
Oracle JDeveloper Tip
Tips for Debugging ADF
Applications Using JDeveloper
Author: Steve Muench, ADF Development
Team Date: February 15, 2006
When your J2EE application isn't working as you thought it
should, JDeveloper's excellent debugger is your friend. This quick article will
help you understand some of its features that I find I use most often.
Turning on Diagnostic Logging
Firstly, even before
starting to use the actual debugger, running with the framework diagnostics
logging turned on can be helpful to see what it's doing when the problem
occurs. To turn on diagnostic logging set the Java System property named
jbo.debugoutput to the value console.
Legal values for this flag are silent,
console, and file in JDeveloper 10.1.2.
In JDeveloper 10.1.3, a new value called ADFLogger is also
supported which routes diagnostics through the standard J2SE Logger
implementation which can be controlled in a standard way through the OC4J
j2ee-logging.xml file.
The easiest way to set
this system property while running your application inside JDeveloper 10g is to
edit your project properties and:
- In
JDeveloper 10.1.2, visit the Runner
panel
- In JDeveloper 10.1.3, visit the
Run/Debug panel, select a Run
Configuration and click (Edit...) to edit it.
Then add the string
-Djbo.debugoutput=console to the Java
Options field.
Debugging an Application
Module Using the Tester
Often you will find it useful to debug the
ADF Business Components in your application without having to start up the
visual user interface of your ADF application. You are likely already aware
that you can select any application module in the Application
Navigator, and choose Test... from its
right-mouse context menu to launch the Business Components Tester tool. What
you might not know is that you can also launch the Tester tool in the debugger.
This can be extremely useful and can make debugging ADF Business Components
applications even easier than when having to startup the complete front-end GUI
of your application.
To launch an ADF Application Module in the
tester in debug mode, do the following:
- Select the application module in question in the Application
Navigator
-
In the
Structure Window, notice the Sources
folder, and select the Java implementation class for your application
module.
If you application module is called
MyModule, this class will be named
MyModuleImpl.java
- Select
Debug... from the context menu on that application module
implementation class to launch the debugger.
You'll notice that the main() method of your
application module Java class looks like this:
public static void main(String[] args) {
launchTester("com.yourcompany.yourapp.model", /* package name */
"MyModuleLocal"); /* Configuration Name */
}
If you need to launch the application module in the
debugger using a different configuration than the one indicated (e.g.
MyModuleLocal in the code sample above), just change the
string that gets passed as the second argument to
launchTester() to be the name of the configuration you want
to use instead.
Understanding the Different Kinds of Breakpoints
You first
need to understand the different kinds of breakpoints we support and where to
create them.
To see the Debugger Breakpoints window, use the View |
Debugger > Breakpoints menu choice from the main JDeveloper
menu, or optionally the key accelerator for this:
Ctrl+Shift+R.
You can create a new breakpoint by selecting the New
Breakpoint... menu choice from the right-mouse menu anywhere in
the breakpoints window. The Breakpoint Type dropdown list
controls what kind of breakpoint you will create. The valid choices are:
-
Exception — break whenever
an exception of this class (or a subclass) is thrown.
This is
great when you don't know where the exception occurs, but you know what kind of
exception it is (e.g. java.lang.NullPointerException,
java.lang.ArrayIndexOutOfBoundsException,
oracle.jbo.JboException, etc.) The checkbox options allow
you to control whether to break on caught or uncaught exceptions of this class.
The (Browse...) button helps you find the fully-qualified class name of the
exception. The Exception Class combo-box remembers most recently used exception
breakpoint classes. Note that this is the default breakpoint type when you
create a breakpoint in the breakpoints window.
-
Source — break whenever a particular source line in
a particular class in a particular package is run.
You rarely
create a source breakpoint in the New Breakpoint window.
This is because it's much easier to create it by first using the
Navigate | Go to Class... menu (accelerator
Ctrl+Shift+Minus),
then scrolling to the line number you want -- or using Navigate |
Go to Line... (accelerator
Ctrl+G) -- and finally
clicking in the breakpoint margin at the left of the line you want to break on.
This is equivalent to creating a new source breakpoint, but it means you don't
have to type in the package, class, and line number by hand.
-
Method — break whenever a method in a
given class is invoked.
This is handy to set breakpoints on a
particular method you might have seen in the call stack while debugging a
problem. Of course, if you have the source you can set a source breakpoint
wherever you want in that class, but this kind of breakpoint lets you stop in
the debugger even when you don't have source for a class.
-
Class — break whenever any method in a
given class is invoked.
This can be handy when you might only know
the class involved in the problem, but not the exact method you want to stop
on. Again, this kind of breakpoint does not require source. The
(Browse...) button helps you quickly find the
fully-qualified class name you want to break on.
-
Watchpoint — break whenever a given field is
accessed or modified (new in 10.1.3)
This can be super helpful to
find a problem if the code inside a class modifies a member field directly from
several different places (instead of going through setter or getter methods
each time). You can stop the debugger in its tracks when any field is modified.
You can create a breakpoint of this type by using the Toggle
Watchpoint menu item on the right-mouse menu when pointing at a
member field in your class' source.
Editing Breakpoints to For Improved
Control
After creating a breakpoint you and edit the breakpoint in
the breakpoints window using the Edit... choice in
the context menu on the desired breakpoint.
Some really interesting
features you can do by editing your breakpoint are:
- Associate a logical "breakpoint group" name to group this
breakpoint with others having the same breakpoint group name. Breakpoint groups
make it easy to enable/disable an entire set of breakpoints in one operation.
- Associate a debugger action to occur when the
breakpoint is hit. The default action is to just stop the debugger so you can
inspect things, but you can add a beep, write something to a log file, and
enable or disable group of breakpoints.
-
Associate a conditional expression with the breakpoint so that it the
debugger only stops when that condition is met. In 10.1.3, the expressions can
be virtually any boolean expression, including:
expr ==
value
expr.equals("value")
expr instanceof
fully.qualified.ClassName
which are the three I use most frequently.
| NOTE: |
One tip is
to use the debugger watch window to evaluate the expression first to make sure
its valid. |
Filtering Your View of Class Members
An
excellent but often overlooked feature of the JDeveloper debugger is the
ability to filter the members you want to see in the debugger window for any
class. In the debugger's Data window, pointing at any item and selecting Object
Preferences... from the right-mouse context menu brings up a dialog where you
can customize which members appear in the debugger and (more importantly
sometimes) which members don't appear. These preferences
are set by class type and can really simplify the amount of scrolling you need
to do in the debugger data window when you might only really care about a
handful of a class' members while debugging.
Interesting ADF Framework Breakpoints to
Set
Interesting breakpoints in set it ADF framework code when
you're trying to debug a problem are:
-
Exception breakpoint for
oracle.jbo.JboException
When you're not sure
where to start, this is the base class of all ADF Business Components runtime
exceptions.
-
Exception breakpoint for
oracle.jbo.DMLException
This is the base class
for exceptions originating from the database, like a failed DML operation due
to an exception raised by a trigger or by a constraint
violation.
-
Source breakpoint in the
doIt() method of JUCtrlActionBinding
class (oracle.jbo.uicli.binding package).
This
is the method that will execute when any ADF action binding is invoked, and you
can step into the logic and look at parameters if relevant.
-
Source breakpoint in the handleLifecycle()
method of the DataAction class
(oracle.adf.controller.struts.actions package).
This is the method that controls the processing of the ADF/Struts request
handling lifecycle.
-
Method breakpoint in the
oracle.jbo.server.ViewObjectImpl.executeQueryForCollection
method.
This is the method that will be called when a view object
executes its SQL query.
-
Method breakpoint in
the oracle.jbo.server.ViewRowImpl.setAttributeInternal
method.
This is the method that will be called when any view row
attribute is set.
-
Method breakpoint in the
oracle.jbo.server.EntityImpl.setAttributeInternal method.
This is the method that will be called when any entity object
attribute is set.
By looking at the stack window when you hit
these breakpoints, and stepping through the source you can get a better idea of
what's going on.
Communicating Stack Trace Information to Someone Else
If
you are unable to use the tips in this article to determine what the problem is
and resolve it yourself, typically your next step is to ask someone else for
assistance. Whether you post a question in the OTN JDeveloper Discussion Forum
or open a Service Request on Metalink, including the stack trace information in
your posting is extremely useful to anyone who will need to assist you further
to understand exactly where the problem is occurring.
JDeveloper
10g's Stack window makes communicating this information
easy. Whenever the debugger is paused, you can view the
Stack window to see the program flow as a stack of method
calls that got you to the current line. Using the right-mouse Preferences...
menu on the Stack window background, you can set the Stack
window preference to include the Line number information as well as the class
and method name that will be there by default. Finally, the other handy context
menu option Export... lets you save the current stack
information to an external text file whose contents you can then post or send
to whomever might need to help you diagnose the problem.
| NOTE: |
As
of June 28th, 2005, supported Oracle ADF customers can
request
the ADF framework source from Oracle Worldside Support. This can make
debugging ADF Business Components framework code a lot
easier.
|
|