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:

  1. Select the application module in question in the Application Navigator
  2. 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

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